diff options
Diffstat (limited to 'storage/mroonga/vendor/groonga/lib/mrb/scripts')
34 files changed, 1152 insertions, 152 deletions
diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/Makefile.am b/storage/mroonga/vendor/groonga/lib/mrb/scripts/Makefile.am index 631923e2e06..9b6acf8bbda 100644 --- a/storage/mroonga/vendor/groonga/lib/mrb/scripts/Makefile.am +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/Makefile.am @@ -1,3 +1,9 @@ +SUBDIRS = \ + command_line \ + context \ + initialize \ + logger + include sources.am EXTRA_DIST = \ @@ -5,5 +11,5 @@ EXTRA_DIST = \ $(RUBY_SCRIPT_FILES) if WITH_MRUBY -nobase_ruby_scripts_DATA = $(RUBY_SCRIPT_FILES) +ruby_scripts_DATA = $(RUBY_SCRIPT_FILES) endif diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/backtrace_entry.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/backtrace_entry.rb index 68ea9e4b6f2..34f95e968f5 100644 --- a/storage/mroonga/vendor/groonga/lib/mrb/scripts/backtrace_entry.rb +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/backtrace_entry.rb @@ -5,16 +5,24 @@ module Groonga match_data = /:(\d+):?/.match(entry) file = match_data.pre_match line = match_data[1].to_i - method = match_data.post_match.gsub(/\Ain /, "") - new(file, line, method) + detail_match_data = /\A(in )?(\S+)\s*/.match(match_data.post_match) + if detail_match_data[1] + method = detail_match_data[2] + message = detail_match_data.post_match + else + method = "" + message = match_data.post_match + end + new(file, line, method, message) end end - attr_reader :file, :line, :method - def initialize(file, line, method) + attr_reader :file, :line, :method, :message + def initialize(file, line, method, message) @file = file @line = line @method = method + @message = message end end end diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/command.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/command.rb new file mode 100644 index 00000000000..c4e3e94bc4e --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/command.rb @@ -0,0 +1,35 @@ +module Groonga + class Command + @@classes = {} + class << self + def register_class(name, klass) + @@classes[name] = klass + end + + def find_class(name) + @@classes[name] + end + end + + private + def context + @context ||= Context.instance + end + + def writer + @writer ||= context.writer + end + + def run_internal(input) + begin + run_body(input) + rescue GroongaError => groonga_error + context.set_groonga_error(groonga_error) + nil + rescue => error + context.record_error(:command_error, error) + nil + end + end + end +end diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/command_line/Makefile.am b/storage/mroonga/vendor/groonga/lib/mrb/scripts/command_line/Makefile.am new file mode 100644 index 00000000000..8d580810674 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/command_line/Makefile.am @@ -0,0 +1,9 @@ +include sources.am + +EXTRA_DIST = \ + $(RUBY_SCRIPT_FILES) + +if WITH_MRUBY +ruby_scripts_command_linedir = $(ruby_scriptsdir)/command_line +ruby_scripts_command_line_DATA = $(RUBY_SCRIPT_FILES) +endif diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/command_line/grndb.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/command_line/grndb.rb new file mode 100644 index 00000000000..96a99c80223 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/command_line/grndb.rb @@ -0,0 +1,169 @@ +module Groonga + module CommandLine + class Grndb + def initialize(argv) + @command, *@arguments = argv + @succeeded = true + @executed = false + @database_path = nil + end + + def run + slop = create_slop + rest = nil + begin + rest = slop.parse(@arguments) + rescue Slop::Error + $stderr.puts($!.message) + return false + end + + if slop.help? + $stdout.puts(slop.help) + return true + end + + unless @executed + if rest.empty? + $stderr.puts("No command is specified.") + else + $stderr.puts("Unknown command: <#{rest.first}>") + end + return false + end + + @succeeded + end + + private + def create_slop + slop = Slop.new + command_name = File.basename(@command) + slop.banner = "Usage: #{command_name} COMMAND [OPTIONS] DB_PATH" + slop_enable_help(slop) + + slop.command "check" do |command| + command.description "Check database" + slop_enable_help(command) + + command.run do |options, arguments| + run_command(options, arguments) do |database, new_arguments| + check(database, options, new_arguments) + end + end + end + + slop.command "recover" do |command| + command.description "Recover database" + slop_enable_help(command) + + command.run do |options, arguments| + run_command(options, arguments) do |database, new_arguments| + recover(database, options, new_arguments) + end + end + end + + slop + end + + def slop_enable_help(slop) + slop.on("-h", "--help", "Display this help message.", :tail => true) + end + + def open_database(arguments) + if arguments.empty? + $stderr.puts("Database path is missing") + @succeesed = false + return + end + + database = nil + @database_path, *rest_arguments = arguments + begin + database = Database.open(@database_path) + rescue Error => error + $stderr.puts("Failed to open database: <#{@database_path}>") + $stderr.puts(error.message) + @succeeded = false + return + end + + begin + yield(database, rest_arguments) + ensure + database.close + end + end + + def run_command(options, arguments) + @executed = true + + if options.help? + $stdout.puts(options.help) + return + end + + open_database(arguments) do |database| + yield(database) + end + end + + def recover(database, options, arguments) + begin + database.recover + rescue Error => error + $stderr.puts("Failed to recover database: <#{@database_path}>") + $stderr.puts(error.message) + @succeeded = false + end + end + + def check(database, options, arguments) + if database.locked? + message = + "Database is locked. " + + "It may be broken. " + + "Re-create the database." + $stdout.puts(message) + @succeeded = false + end + + database.each do |object| + case object + when IndexColumn + next unless object.locked? + message = + "[#{object.name}] Index column is locked. " + + "It may be broken. " + + "Re-create index by '#{@command} recover #{@database_path}'." + $stdout.puts(message) + @succeeded = false + when Column + next unless object.locked? + name = object.name + message = + "[#{name}] Data column is locked. " + + "It may be broken. " + + "(1) Truncate the column (truncate #{name}) or " + + "clear lock of the column (lock_clear #{name}) " + + "and (2) load data again." + $stdout.puts(message) + @succeeded = false + when Table + next unless object.locked? + name = object.name + message = + "[#{name}] Table is locked. " + + "It may be broken. " + + "(1) Truncate the table (truncate #{name}) or " + + "clear lock of the table (lock_clear #{name}) " + + "and (2) load data again." + $stdout.puts(message) + @succeeded = false + end + end + end + end + end +end diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/command_line/sources.am b/storage/mroonga/vendor/groonga/lib/mrb/scripts/command_line/sources.am new file mode 100644 index 00000000000..759948eecd6 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/command_line/sources.am @@ -0,0 +1,2 @@ +RUBY_SCRIPT_FILES = \ + grndb.rb diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/context.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/context.rb index 8ebe2c913b4..e65d6653110 100644 --- a/storage/mroonga/vendor/groonga/lib/mrb/scripts/context.rb +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/context.rb @@ -1,3 +1,6 @@ +require "context/error_level" +require "context/rc" + module Groonga class Context def guard(fallback=nil) @@ -13,19 +16,37 @@ module Groonga @logger ||= Logger.new end + def writer + @writer ||= Writer.new + end + + def set_groonga_error(groonga_error) + set_error_raw(groonga_error.class.rc, + ErrorLevel::ERROR, + groonga_error.message, + groonga_error.backtrace) + end + def record_error(rc, error) rc = RC.find(rc) if rc.is_a?(Symbol) + set_error_raw(rc, ErrorLevel::ERROR, error.message, error.backtrace) + + logger.log_error(error) + end + + private + def set_error_raw(rc, error_level, message, backtrace) self.rc = rc.to_i - self.error_level = ErrorLevel.find(:error).to_i + self.error_level = error_level.to_i - backtrace = error.backtrace - entry = BacktraceEntry.parse(backtrace.first) - self.error_file = entry.file - self.error_line = entry.line - self.error_method = entry.method - self.error_message = error.message + self.error_message = message - logger.log_error(error) + if backtrace + entry = BacktraceEntry.parse(backtrace.first) + self.error_file = entry.file + self.error_line = entry.line + self.error_method = entry.method + end end end end diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/context/Makefile.am b/storage/mroonga/vendor/groonga/lib/mrb/scripts/context/Makefile.am new file mode 100644 index 00000000000..8d862082cce --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/context/Makefile.am @@ -0,0 +1,9 @@ +include sources.am + +EXTRA_DIST = \ + $(RUBY_SCRIPT_FILES) + +if WITH_MRUBY +ruby_scripts_contextdir = $(ruby_scriptsdir)/context +ruby_scripts_context_DATA = $(RUBY_SCRIPT_FILES) +endif diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/context/rc.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/context/rc.rb index 2863c7f6195..f06b32d78b6 100644 --- a/storage/mroonga/vendor/groonga/lib/mrb/scripts/context/rc.rb +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/context/rc.rb @@ -5,13 +5,19 @@ module Groonga class << self def find(name) - @@names[name] + @@names[name] || UNKNOWN_ERROR + end + + def register(name, code, error_class) + rc = new(name, code) + @@names[name] = rc + error_class.rc = rc if error_class + rc end end attr_reader :name def initialize(name, code) - @@names[name] = self @name = name @code = code end @@ -20,80 +26,164 @@ module Groonga @code end - SUCCESS = new(:success, 0) - END_OF_DATA = new(:end_of_data, 1) - UNKNOWN_ERROR = new(:unknown_error, -1) - OPERATION_NOT_PERMITTED = new(:operation_not_permitted, -2) - NO_SUCH_FILE_OR_DIRECTORY = new(:no_such_file_or_directory, -3) - NO_SUCH_PROCESS = new(:no_such_process, -4) - INTERRUPTED_FUNCTION_CALL = new(:interrupted_function_call, -5) - INPUT_OUTPUT_ERROR = new(:input_output_error, -6) - NO_SUCH_DEVICE_OR_ADDRESS = new(:no_such_device_or_address, -7) - ARG_LIST_TOO_LONG = new(:arg_list_too_long, -8) - EXEC_FORMAT_ERROR = new(:exec_format_error, -9) - BAD_FILE_DESCRIPTOR = new(:bad_file_descriptor, -10) - NO_CHILD_PROCESSES = new(:no_child_processes, -11) - RESOURCE_TEMPORARILY_UNAVAILABLE = new(:resource_temporarily_unavailable, -12) - NOT_ENOUGH_SPACE = new(:not_enough_space, -13) - PERMISSION_DENIED = new(:permission_denied, -14) - BAD_ADDRESS = new(:bad_address, -15) - RESOURCE_BUSY = new(:resource_busy, -16) - FILE_EXISTS = new(:file_exists, -17) - IMPROPER_LINK = new(:improper_link, -18) - NO_SUCH_DEVICE = new(:no_such_device, -19) - NOT_A_DIRECTORY = new(:not_a_directory, -20) - IS_A_DIRECTORY = new(:is_a_directory, -21) - INVALID_ARGUMENT = new(:invalid_argument, -22) - TOO_MANY_OPEN_FILES_IN_SYSTEM = new(:too_many_open_files_in_system, -23) - TOO_MANY_OPEN_FILES = new(:too_many_open_files, -24) - INAPPROPRIATE_IO_CONTROL_OPERATION = new(:inappropriate_io_control_operation, -25) - FILE_TOO_LARGE = new(:file_too_large, -26) - NO_SPACE_LEFT_ON_DEVICE = new(:no_space_left_on_device, -27) - INVALID_SEEK = new(:invalid_seek, -28) - READ_ONLY_FILE_SYSTEM = new(:read_only_file_system, -29) - TOO_MANY_LINKS = new(:too_many_links, -30) - BROKEN_PIPE = new(:broken_pipe, -31) - DOMAIN_ERROR = new(:domain_error, -32) - RESULT_TOO_LARGE = new(:result_too_large, -33) - RESOURCE_DEADLOCK_AVOIDED = new(:resource_deadlock_avoided, -34) - NO_MEMORY_AVAILABLE = new(:no_memory_available, -35) - FILENAME_TOO_LONG = new(:filename_too_long, -36) - NO_LOCKS_AVAILABLE = new(:no_locks_available, -37) - FUNCTION_NOT_IMPLEMENTED = new(:function_not_implemented, -38) - DIRECTORY_NOT_EMPTY = new(:directory_not_empty, -39) - ILLEGAL_BYTE_SEQUENCE = new(:illegal_byte_sequence, -40) - SOCKET_NOT_INITIALIZED = new(:socket_not_initialized, -41) - OPERATION_WOULD_BLOCK = new(:operation_would_block, -42) - ADDRESS_IS_NOT_AVAILABLE = new(:address_is_not_available, -43) - NETWORK_IS_DOWN = new(:network_is_down, -44) - NO_BUFFER = new(:no_buffer, -45) - SOCKET_IS_ALREADY_CONNECTED = new(:socket_is_already_connected, -46) - SOCKET_IS_NOT_CONNECTED = new(:socket_is_not_connected, -47) - SOCKET_IS_ALREADY_SHUTDOWNED = new(:socket_is_already_shutdowned, -48) - OPERATION_TIMEOUT = new(:operation_timeout, -49) - CONNECTION_REFUSED = new(:connection_refused, -50) - RANGE_ERROR = new(:range_error, -51) - TOKENIZER_ERROR = new(:tokenizer_error, -52) - FILE_CORRUPT = new(:file_corrupt, -53) - INVALID_FORMAT = new(:invalid_format, -54) - OBJECT_CORRUPT = new(:object_corrupt, -55) - TOO_MANY_SYMBOLIC_LINKS = new(:too_many_symbolic_links, -56) - NOT_SOCKET = new(:not_socket, -57) - OPERATION_NOT_SUPPORTED = new(:operation_not_supported, -58) - ADDRESS_IS_IN_USE = new(:address_is_in_use, -59) - ZLIB_ERROR = new(:zlib_error, -60) - LZO_ERROR = new(:lzo_error, -61) - STACK_OVER_FLOW = new(:stack_over_flow, -62) - SYNTAX_ERROR = new(:syntax_error, -63) - RETRY_MAX = new(:retry_max, -64) - INCOMPATIBLE_FILE_FORMAT = new(:incompatible_file_format, -65) - UPDATE_NOT_ALLOWED = new(:update_not_allowed, -66) - TOO_SMALL_OFFSET = new(:too_small_offset, -67) - TOO_LARGE_OFFSET = new(:too_large_offset, -68) - TOO_SMALL_LIMIT = new(:too_small_limit, -69) - CAS_ERROR = new(:cas_error, -70) - UNSUPPORTED_COMMAND_VERSION = new(:unsupported_command_version, -71) - NORMALIZER_ERROR = new(:normalizer_error, -72) + SUCCESS = + register(:success, 0, nil) + END_OF_DATA = + register(:end_of_data, 1, EndOfData) + UNKNOWN_ERROR = + register(:unknown_error, -1, UnknownError) + OPERATION_NOT_PERMITTED = + register(:operation_not_permitted, -2, OperationNotPermitted) + NO_SUCH_FILE_OR_DIRECTORY = + register(:no_such_file_or_directory, -3, NoSuchFileOrDirectory) + NO_SUCH_PROCESS = + register(:no_such_process, -4, NoSuchProcess) + INTERRUPTED_FUNCTION_CALL = + register(:interrupted_function_call, -5, InterruptedFunctionCall) + INPUT_OUTPUT_ERROR = + register(:input_output_error, -6, InputOutputError) + NO_SUCH_DEVICE_OR_ADDRESS = + register(:no_such_device_or_address, -7, NoSuchDeviceOrAddress) + ARG_LIST_TOO_LONG = + register(:arg_list_too_long, -8, ArgListTooLong) + EXEC_FORMAT_ERROR = + register(:exec_format_error, -9, ExecFormatError) + BAD_FILE_DESCRIPTOR = + register(:bad_file_descriptor, -10, BadFileDescriptor) + NO_CHILD_PROCESSES = + register(:no_child_processes, -11, NoChildProcesses) + RESOURCE_TEMPORARILY_UNAVAILABLE = + register(:resource_temporarily_unavailable, -12, + ResourceTemporarilyUnavailable) + NOT_ENOUGH_SPACE = + register(:not_enough_space, -13, NotEnoughSpace) + PERMISSION_DENIED = + register(:permission_denied, -14, PermissionDenied) + BAD_ADDRESS = + register(:bad_address, -15, BadAddress) + RESOURCE_BUSY = + register(:resource_busy, -16, ResourceBusy) + FILE_EXISTS = + register(:file_exists, -17, FileExists) + IMPROPER_LINK = + register(:improper_link, -18, ImproperLink) + NO_SUCH_DEVICE = + register(:no_such_device, -19, NoSuchDevice) + NOT_DIRECTORY = + register(:not_directory, -20, NotDirectory) + IS_DIRECTORY = + register(:is_directory, -21, IsDirectory) + INVALID_ARGUMENT = + register(:invalid_argument, -22, InvalidArgument) + TOO_MANY_OPEN_FILES_IN_SYSTEM = + register(:too_many_open_files_in_system, -23, TooManyOpenFilesInSystem) + TOO_MANY_OPEN_FILES = + register(:too_many_open_files, -24, TooManyOpenFiles) + INAPPROPRIATE_IO_CONTROL_OPERATION = + register(:inappropriate_io_control_operation, -25, + InappropriateIOControlOperation) + FILE_TOO_LARGE = + register(:file_too_large, -26, FileTooLarge) + NO_SPACE_LEFT_ON_DEVICE = + register(:no_space_left_on_device, -27, NoSpaceLeftOnDevice) + INVALID_SEEK = + register(:invalid_seek, -28, InvalidSeek) + READ_ONLY_FILE_SYSTEM = + register(:read_only_file_system, -29, ReadOnlyFileSystem) + TOO_MANY_LINKS = + register(:too_many_links, -30, TooManyLinks) + BROKEN_PIPE = + register(:broken_pipe, -31, BrokenPipe) + DOMAIN_ERROR = + register(:domain_error, -32, DomainError) + RESULT_TOO_LARGE = + register(:result_too_large, -33, ResultTooLarge) + RESOURCE_DEADLOCK_AVOIDED = + register(:resource_deadlock_avoided, -34, ResourceDeadlockAvoided) + NO_MEMORY_AVAILABLE = + register(:no_memory_available, -35, NoMemoryAvailable) + FILENAME_TOO_LONG = + register(:filename_too_long, -36, FilenameTooLong) + NO_LOCKS_AVAILABLE = + register(:no_locks_available, -37, NoLocksAvailable) + FUNCTION_NOT_IMPLEMENTED = + register(:function_not_implemented, -38, FunctionNotImplemented) + DIRECTORY_NOT_EMPTY = + register(:directory_not_empty, -39, DirectoryNotEmpty) + ILLEGAL_BYTE_SEQUENCE = + register(:illegal_byte_sequence, -40, IllegalByteSequence) + SOCKET_NOT_INITIALIZED = + register(:socket_not_initialized, -41, SocketNotInitialized) + OPERATION_WOULD_BLOCK = + register(:operation_would_block, -42, OperationWouldBlock) + ADDRESS_IS_NOT_AVAILABLE = + register(:address_is_not_available, -43, AddressIsNotAvailable) + NETWORK_IS_DOWN = + register(:network_is_down, -44, NetworkIsDown) + NO_BUFFER = + register(:no_buffer, -45, NoBuffer) + SOCKET_IS_ALREADY_CONNECTED = + register(:socket_is_already_connected, -46, SocketIsAlreadyConnected) + SOCKET_IS_NOT_CONNECTED = + register(:socket_is_not_connected, -47, SocketIsNotConnected) + SOCKET_IS_ALREADY_SHUTDOWNED = + register(:socket_is_already_shutdowned, -48, SocketIsAlreadyShutdowned) + OPERATION_TIMEOUT = + register(:operation_timeout, -49, OperationTimeout) + CONNECTION_REFUSED = + register(:connection_refused, -50, ConnectionRefused) + RANGE_ERROR = + register(:range_error, -51, RangeError) + TOKENIZER_ERROR = + register(:tokenizer_error, -52, TokenizerError) + FILE_CORRUPT = + register(:file_corrupt, -53, FileCorrupt) + INVALID_FORMAT = + register(:invalid_format, -54, InvalidFormat) + OBJECT_CORRUPT = + register(:object_corrupt, -55, ObjectCorrupt) + TOO_MANY_SYMBOLIC_LINKS = + register(:too_many_symbolic_links, -56, TooManySymbolicLinks) + NOT_SOCKET = + register(:not_socket, -57, NotSocket) + OPERATION_NOT_SUPPORTED = + register(:operation_not_supported, -58, OperationNotSupported) + ADDRESS_IS_IN_USE = + register(:address_is_in_use, -59, AddressIsInUse) + ZLIB_ERROR = + register(:zlib_error, -60, ZlibError) + LZ4_ERROR = + register(:lz4_error, -61, LZ4Error) + STACK_OVER_FLOW = + register(:stack_over_flow, -62, StackOverFlow) + SYNTAX_ERROR = + register(:syntax_error, -63, SyntaxError) + RETRY_MAX = + register(:retry_max, -64, RetryMax) + INCOMPATIBLE_FILE_FORMAT = + register(:incompatible_file_format, -65, IncompatibleFileFormat) + UPDATE_NOT_ALLOWED = + register(:update_not_allowed, -66, UpdateNotAllowed) + TOO_SMALL_OFFSET = + register(:too_small_offset, -67, TooSmallOffset) + TOO_LARGE_OFFSET = + register(:too_large_offset, -68, TooLargeOffset) + TOO_SMALL_LIMIT = + register(:too_small_limit, -69, TooSmallLimit) + CAS_ERROR = + register(:cas_error, -70, CASError) + UNSUPPORTED_COMMAND_VERSION = + register(:unsupported_command_version, -71, UnsupportedCommandVersion) + NORMALIZER_ERROR = + register(:normalizer_error, -72, NormalizerError) + TOKEN_FILTER_ERROR = + register(:token_filter_error, -73, TokenFilterError) + COMMAND_ERROR = + register(:command_error, -74, CommandError) + PLUGIN_ERROR = + register(:plugin_error, -75, PluginError) + + GroongaError.rc = UNKNOWN_ERROR end end end diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/context/sources.am b/storage/mroonga/vendor/groonga/lib/mrb/scripts/context/sources.am new file mode 100644 index 00000000000..1f0d1624ce5 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/context/sources.am @@ -0,0 +1,3 @@ +RUBY_SCRIPT_FILES = \ + error_level.rb \ + rc.rb diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/database.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/database.rb new file mode 100644 index 00000000000..54d9dc1a631 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/database.rb @@ -0,0 +1,39 @@ +module Groonga + class Database + def each + context = Context.instance + flags = + TableCursorFlags::ASCENDING | + TableCursorFlags::BY_ID + TableCursor.open(self, :flags => flags) do |cursor| + cursor.each do |id| + object = context[id] + yield(object) if object + end + end + end + + def each_table(options={}) + context = Context.instance + min = options[:prefix] + flags = 0 + if options[:order] == :descending + flags |= TableCursorFlags::DESCENDING + else + flags |= TableCursorFlags::ASCENDING + end + if options[:order_by] == :id + flags |= TableCursorFlags::BY_ID + else + flags |= TableCursorFlags::BY_KEY + end + flags |= TableCursorFlags::PREFIX if min + TableCursor.open(self, :min => min, :flags => flags) do |cursor| + cursor.each do |id| + object = context[id] + yield(object) if object.is_a?(Table) + end + end + end + end +end diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/error.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/error.rb new file mode 100644 index 00000000000..e39c904534a --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/error.rb @@ -0,0 +1,16 @@ +module Groonga + class GroongaError + class << self + def rc + @rc + end + + def rc=(rc) + @rc = rc + end + end + end + + class ErrorMessage < Error + end +end diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/expression.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/expression.rb index 29290e207f2..7b1199b7795 100644 --- a/storage/mroonga/vendor/groonga/lib/mrb/scripts/expression.rb +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/expression.rb @@ -1,3 +1,8 @@ +require "scan_info" +require "scan_info_builder" + +require "expression_size_estimator" + module Groonga class Expression def build_scan_info(op, size) @@ -9,5 +14,23 @@ module Groonga nil end end + + def estimate_size(table) + begin + estimator = ExpressionSizeEstimator.new(self, table) + estimator.estimate + rescue GroongaError => groonga_error + context.set_groonga_error(groonga_error) + table.size + rescue => error + context.record_error(:unknown_error, error) + table.size + end + end + + private + def context + @context ||= Context.instance + end end end diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/expression_size_estimator.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/expression_size_estimator.rb new file mode 100644 index 00000000000..73b44cae3dd --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/expression_size_estimator.rb @@ -0,0 +1,155 @@ +module Groonga + class ExpressionSizeEstimator + def initialize(expression, table) + @expression = expression + @table = table + @table_size = @table.size + end + + def estimate + builder = ScanInfoBuilder.new(@expression, Operator::OR, 0) + data_list = builder.build + return @table_size if data_list.nil? + + or_data_list = group_data_list(data_list) + or_sizes = or_data_list.collect do |and_data_list| + and_sizes = and_data_list.collect do |data| + size = estimate_data(data) + if data.logical_op == Operator::AND_NOT + size = @table_size - size + size = 0 if size < 0 + end + size + end + and_sizes.min + end + or_sizes.max + end + + private + def group_data_list(data_list) + or_data_list = [[]] + data_list.each do |data| + next if data.op == Operator::NOP + + and_data_list = or_data_list.last + if and_data_list.empty? + and_data_list << data + else + case data.logical_op + when Operator::AND, Operator::AND_NOT + and_data_list << data + else + and_data_list = [data] + or_data_list << and_data_list + end + end + end + or_data_list + end + + def estimate_data(data) + search_index = data.search_indexes.first + return @table_size if search_index.nil? + + index_column = resolve_index_column(search_index.index_column, + data.op) + return @table_size if index_column.nil? + + size = nil + case data.op + when Operator::MATCH + size = estimate_match(data, index_column) + when Operator::REGEXP + size = estimate_regexp(data, index_column) + when Operator::EQUAL + size = estimate_equal(data, index_column) + when Operator::LESS, + Operator::LESS_EQUAL, + Operator::GREATER, + Operator::GREATER_EQUAL + size = estimate_range(data, index_column) + when Operator::CALL + procedure = data.args.first + if procedure.is_a?(Procedure) and procedure.name == "between" + size = estimate_between(data, index_column) + end + end + size || @table_size + end + + def resolve_index_column(index_column, operator) + while index_column.is_a?(Accessor) + index_info = index_column.find_index(operator) + return nil if index_info.nil? + index_column = index_info.index + end + + index_column + end + + def estimate_match(data, index_column) + index_column.estimate_size(:query => data.query.value) + end + + def estimate_regexp(data, index_column) + index_column.estimate_size(:query => data.query.value, + :mode => data.op) + end + + def estimate_equal(data, index_column) + lexicon = index_column.lexicon + term_id = lexicon[data.query] + return 0 if term_id.nil? + + index_column.estimate_size(:term_id => term_id) + end + + def estimate_range(data, index_column) + lexicon = index_column.lexicon + value = data.query.value + options = {} + case data.op + when Operator::LESS + options[:max] = value + options[:flags] = TableCursorFlags::LT + when Operator::LESS_EQUAL + options[:max] = value + options[:flags] = TableCursorFlags::LE + when Operator::GREATER + options[:min] = value + options[:flags] = TableCursorFlags::GT + when Operator::GREATER_EQUAL + options[:min] = value + options[:flags] = TableCursorFlags::GE + end + TableCursor.open(lexicon, options) do |cursor| + index_column.estimate_size(:lexicon_cursor => cursor) + end + end + + def estimate_between(data, index_column) + lexicon = index_column.lexicon + _, _, min, min_border, max, max_border = data.args + options = { + :min => min, + :max => max, + :flags => 0, + } + if min_border == "include" + options[:flags] |= TableCursorFlags::LT + else + options[:flags] |= TableCursorFlags::LE + end + if max_border == "include" + options[:flags] |= TableCursorFlags::GT + else + options[:flags] |= TableCursorFlags::GE + end + + TableCursor.open(lexicon, options) do |cursor| + index_column.estimate_size(:lexicon_cursor => cursor) + end + end + end +end diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/index_column.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/index_column.rb new file mode 100644 index 00000000000..25ebc149367 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/index_column.rb @@ -0,0 +1,39 @@ +module Groonga + class IndexColumn + private :estimate_size_for_term_id + private :estimate_size_for_query + private :estimate_size_for_lexicon_cursor + + # Estimate the number of matched records for term ID or query. + # + # @overload estimate_size(:term_id => term_id) + # @return [Integer] the number of matched records for the term ID. + # + # @overload estimate_size(:query => query) + # @return [Integer] the number of matched records for the query. + # + # @overload estimate_size(:lexicon_cursor => lexicon_cursor) + # @return [Integer] the number of matched records for the lexicon cursor. + # + def estimate_size(parameters) + term_id = parameters[:term_id] + if term_id + return estimate_size_for_term_id(term_id) + end + + query = parameters[:query] + if query + return estimate_size_for_query(query, parameters) + end + + lexicon_cursor = parameters[:lexicon_cursor] + if lexicon_cursor + return estimate_size_for_lexicon_cursor(lexicon_cursor) + end + + message = + "must specify :term_id, :query, :lexicon_cursor: #{parameters.inspect}" + raise InvalidArgument, message + end + end +end diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/index_cursor.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/index_cursor.rb new file mode 100644 index 00000000000..8044066930a --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/index_cursor.rb @@ -0,0 +1,18 @@ +module Groonga + class IndexCursor + class << self + def open(*arguments) + cursor = open_raw(*arguments) + if block_given? + begin + yield(cursor) + ensure + cursor.close + end + else + cursor + end + end + end + end +end diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/initialize/Makefile.am b/storage/mroonga/vendor/groonga/lib/mrb/scripts/initialize/Makefile.am new file mode 100644 index 00000000000..e7531fdc029 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/initialize/Makefile.am @@ -0,0 +1,9 @@ +include sources.am + +EXTRA_DIST = \ + $(RUBY_SCRIPT_FILES) + +if WITH_MRUBY +ruby_scripts_initializedir = $(ruby_scriptsdir)/initialize +ruby_scripts_initialize_DATA = $(RUBY_SCRIPT_FILES) +endif diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/initialize/post.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/initialize/post.rb new file mode 100644 index 00000000000..ea26a031e0a --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/initialize/post.rb @@ -0,0 +1,18 @@ +require "error" + +require "context" + +require "writer" + +require "object" +require "database" +require "index_column" +require "command" +require "table_cursor" +require "index_cursor" + +require "expression" + +require "plugin_loader" + +require "eval_context" diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/initialize/pre.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/initialize/pre.rb new file mode 100644 index 00000000000..99300d11a92 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/initialize/pre.rb @@ -0,0 +1,3 @@ +require "backtrace_entry" + +require "operator" diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/initialize/sources.am b/storage/mroonga/vendor/groonga/lib/mrb/scripts/initialize/sources.am new file mode 100644 index 00000000000..3c26e19b2ae --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/initialize/sources.am @@ -0,0 +1,3 @@ +RUBY_SCRIPT_FILES = \ + pre.rb \ + post.rb diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/logger.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/logger.rb index 06f99c14fc3..cb747a418d6 100644 --- a/storage/mroonga/vendor/groonga/lib/mrb/scripts/logger.rb +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/logger.rb @@ -3,14 +3,19 @@ module Groonga def log_error(error) log_level = Level::ERROR.to_i - message = "#{error.class}: #{error.message}" + if error.is_a?(Error) + message = error.message + else + message = "#{error.class}: #{error.message}" + end backtrace = error.backtrace - first_raw_entry = backtrace.first - if first_raw_entry - first_entry = BacktraceEntry.parse(first_raw_entry) - file = first_entry.file - line = first_entry.line - method = first_entry.method + last_raw_entry = backtrace.last + if last_raw_entry + last_entry = BacktraceEntry.parse(last_raw_entry) + file = last_entry.file + line = last_entry.line + method = last_entry.method + # message = "#{file}:#{line}:#{method}: #{message}" else file = "" line = 0 @@ -18,8 +23,11 @@ module Groonga end log(log_level, file, line, method, message) - backtrace.each do |raw_entry| + backtrace.reverse_each.with_index do |raw_entry, i| + next if i == 0 entry = BacktraceEntry.parse(raw_entry) + message = entry.message + message = raw_entry if message.empty? log(log_level, entry.file, entry.line, entry.method, raw_entry) end end diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/logger/Makefile.am b/storage/mroonga/vendor/groonga/lib/mrb/scripts/logger/Makefile.am new file mode 100644 index 00000000000..448e72ca5bc --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/logger/Makefile.am @@ -0,0 +1,9 @@ +include sources.am + +EXTRA_DIST = \ + $(RUBY_SCRIPT_FILES) + +if WITH_MRUBY +ruby_scripts_loggerdir = $(ruby_scriptsdir)/logger +ruby_scripts_logger_DATA = $(RUBY_SCRIPT_FILES) +endif diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/logger/sources.am b/storage/mroonga/vendor/groonga/lib/mrb/scripts/logger/sources.am new file mode 100644 index 00000000000..7231ee4eecb --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/logger/sources.am @@ -0,0 +1,2 @@ +RUBY_SCRIPT_FILES = \ + level.rb diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/object.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/object.rb index f1cc1a6aa79..d98b5069e7f 100644 --- a/storage/mroonga/vendor/groonga/lib/mrb/scripts/object.rb +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/object.rb @@ -1,7 +1,11 @@ module Groonga class Object - def inspect - super[0..-2] + ": #{grn_inspect}>" + def domain + Context.instance[domain_id] + end + + def range + Context.instance[range_id] end end end diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/operator.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/operator.rb new file mode 100644 index 00000000000..349695e1a53 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/operator.rb @@ -0,0 +1,22 @@ +module Groonga + class Operator + @values = {} + class << self + def register(operator) + const_set(operator.name, operator) + @values[operator.value] = operator + end + + def find(value) + @values[value] + end + end + + attr_reader :name + attr_reader :value + def initialize(name, value) + @name = name + @value = value + end + end +end diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/plugin_loader.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/plugin_loader.rb new file mode 100644 index 00000000000..09b972f120d --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/plugin_loader.rb @@ -0,0 +1,14 @@ +module Groonga + class PluginLoader + class << self + def load_file(path) + begin + load(path) + rescue => error + Context.instance.record_error(:plugin_error, error) + nil + end + end + end + end +end diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/require.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/require.rb new file mode 100644 index 00000000000..a824e92fa51 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/require.rb @@ -0,0 +1,68 @@ +$" = [__FILE__] + +class ScriptLoader + @@loading_paths = {} + + def initialize(path) + @base_path = path + end + + def load_once + if absolete_path?(@base_path) + loaded = load_once_path(@base_path) + if loaded.nil? + raise LoadError, error_message + else + loaded + end + else + $LOAD_PATH.each do |load_path| + unless absolete_path?(load_path) + load_path = File.expand_path(load_path) + end + loaded = load_once_path(File.join(load_path, @base_path)) + return loaded unless loaded.nil? + end + raise LoadError, error_message + end + end + + private + def error_message + "cannot load such file -- #{@base_path}" + end + + def absolete_path?(path) + path.start_with?("/") + end + + def load_once_path(path) + loaded = load_once_absolete_path(path) + return loaded unless loaded.nil? + + return nil unless File.extname(path).empty? + + load_once_absolete_path("#{path}.rb") + end + + def load_once_absolete_path(path) + return false if $".include?(path) + return false if @@loading_paths.key?(path) + + return nil unless File.file?(path) + + @@loading_paths[path] = true + load(path) + $" << path + @@loading_paths.delete(path) + + true + end +end + +module Kernel + def require(path) + loader = ScriptLoader.new(path) + loader.load_once + end +end diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/scan_info.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/scan_info.rb index cf0056d7fd3..a98cf792a9c 100644 --- a/storage/mroonga/vendor/groonga/lib/mrb/scripts/scan_info.rb +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/scan_info.rb @@ -22,8 +22,13 @@ module Groonga data.args.each do |arg| push_arg(arg) end - data.indexes.each do |index, section_id, weight| - put_index(index, section_id, weight) + data.search_indexes.each do |search_index| + put_index(search_index.index_column, + search_index.section_id, + search_index.weight, + search_index.scorer, + search_index.scorer_args_expr, + search_index.scorer_args_expr_offset || 0) end end end diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/scan_info_builder.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/scan_info_builder.rb index 5e258e90e5a..dc003f88948 100644 --- a/storage/mroonga/vendor/groonga/lib/mrb/scripts/scan_info_builder.rb +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/scan_info_builder.rb @@ -1,11 +1,6 @@ -module Groonga - # TODO: Move me - class ExpressionCode - module Flags - RELATIONAL_EXPRESSION = 0x01 - end - end +require "scan_info_data" +module Groonga class ScanInfoBuilder module Status START = 0 @@ -39,6 +34,21 @@ module Groonga Operator::GEO_WITHINP6, Operator::GEO_WITHINP8, Operator::TERM_EXTRACT, + Operator::REGEXP, + ] + + ARITHMETIC_OPERATORS = [ + Operator::BITWISE_OR, + Operator::BITWISE_XOR, + Operator::BITWISE_AND, + Operator::BITWISE_NOT, + Operator::SHIFTL, + Operator::SHIFTR, + Operator::SHIFTRR, + Operator::PLUS, + Operator::MINUS, + Operator::STAR, + Operator::MOD, ] LOGICAL_OPERATORS = [ @@ -89,7 +99,7 @@ module Groonga status = Status::COL1 data.args << code.value when Status::COL1 - raise "invalid expression: can't use column as a value: <#{code.value.name}>: <#{@expression.grn_inspect}>" + raise ErrorMessage, "invalid expression: can't use column as a value: <#{code.value.name}>: <#{@expression.grn_inspect}>" status = Status::COL2 when Status::COL2 # Do nothing @@ -114,7 +124,7 @@ module Groonga first_data = @data_list.first if (first_data.flags & ScanInfo::Flags::PUSH) == 0 or first_data.logical_op != @operator - raise "invalid expr" + raise ErrorMessage, "invalid expr" else first_data.flags &= ~ScanInfo::Flags::PUSH first_data.logical_op = @operator @@ -140,6 +150,11 @@ module Groonga return false if status > Status::CONST status = Status::START n_relation_expressions += 1 + when *ARITHMETIC_OPERATORS + return false if status < Status::COL1 + return false if status > Status::CONST + status = Status::START + return false if n_relation_expressions != (n_logical_expressions + 1) when *LOGICAL_OPERATORS return false if status != Status::START n_logical_expressions += 1 @@ -206,10 +221,12 @@ module Groonga new_data.flags = ScanInfo::Flags::POP new_data.logical_op = operator @data_list << new_data + break end else data.flags &= ~ScanInfo::Flags::PUSH data.logical_op = operator + break end else if n_dif_ops > 0 @@ -225,6 +242,7 @@ module Groonga @data_list[r..-1] + @data_list[j...r] end + break end end else @@ -235,7 +253,7 @@ module Groonga end if j < 0 - raise GRN_INVALID_ARGUMENT.new("unmatched nesting level") + raise ErrorMessage, "unmatched nesting level" end end end @@ -272,10 +290,10 @@ module Groonga return false if data.args[0] != next_data.args[0] - data_indexes = data.indexes - return false if data_indexes.empty? + data_search_indexes = data.search_indexes + return false if data_search_indexes.empty? - data_indexes == next_data.indexes + data_search_indexes == next_data.search_indexes end def lower_condition?(operator) @@ -303,7 +321,7 @@ module Groonga between_data.op = Operator::CALL between_data.logical_op = data.logical_op between_data.args = create_between_data_args(data, next_data) - between_data.indexes = data.indexes + between_data.search_indexes = data.search_indexes between_data end diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/scan_info_data.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/scan_info_data.rb index 67d0bc3aef7..4a6e58a951a 100644 --- a/storage/mroonga/vendor/groonga/lib/mrb/scripts/scan_info_data.rb +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/scan_info_data.rb @@ -1,3 +1,5 @@ +require "scan_info_search_index" + module Groonga class ScanInfoData attr_accessor :start @@ -6,18 +8,18 @@ module Groonga attr_accessor :logical_op attr_accessor :query attr_accessor :args - attr_accessor :indexes + attr_accessor :search_indexes attr_accessor :flags attr_accessor :max_interval attr_accessor :similarity_threshold def initialize(start) @start = start @end = 0 - @op = 0 + @op = Operator::NOP @logical_op = Operator::OR @query = nil @args = [] - @indexes = [] + @search_indexes = [] @flags = ScanInfo::Flags::PUSH @max_interval = nil @similarity_threshold = nil @@ -57,7 +59,7 @@ module Groonga else message = "The first argument of NEAR/NEAR2 must be Expression, Accessor or Object: #{arg.class}" - raise message + raise ErrorMessage, message end self.query = @args[1] @@ -80,7 +82,7 @@ module Groonga else message = "The first argument of SIMILAR must be Expression, Accessor or Object: #{arg.class}" - raise message + raise ErrorMesesage, message end self.query = @args[1] @@ -100,6 +102,41 @@ module Groonga self.query = arg end end + if @op == Operator::REGEXP and not index_searchable_regexp?(@query) + @search_indexes.clear + end + end + + def index_searchable_regexp?(pattern) + return false if pattern.nil? + + previous_char = nil + pattern.value.each_char do |char| + if previous_char == "\\" + case char + when "Z" + return false + when "b", "B" + return false + when "d", "D", "h", "H", "p", "s", "S", "w", "W" + return false + when "X" + return false + when "k", "g", "1", "2", "3", "4", "5", "6", "7", "8", "9" + return false + when "\\" + previous_char = nil + next + end + else + case char + when ".", "[", "]", "|", "?", "+", "*", "{", "}", "^", "$", "(", ")" + return false + end + end + previous_char = char + end + true end def match_resolve_index_expression(expression) @@ -107,28 +144,96 @@ module Groonga n_codes = codes.size i = 0 while i < n_codes - code = codes[i] - value = code.value - case value - when Accessor - match_resolve_index_expression_accessor(code) - when FixedSizeColumn, VariableSizeColumn - match_resolve_index_expression_data_column(code) - when IndexColumn - section_id = 0 - rest_n_codes = n_codes - i - if rest_n_codes >= 2 and - codes[i + 1].value.is_a?(Bulk) and - codes[i + 1].value.domain == ID::UINT32 and - codes[i + 2].op == Operator::GET_MEMBER - section_id = codes[i + 1].value.value + 1 - code = codes[i + 2] - i += 2 + i = match_resolve_index_expression_codes(expression, codes, i, n_codes) + end + end + + def match_resolve_index_expression_codes(expression, codes, i, n_codes) + code = codes[i] + value = code.value + return i + 1 if value.nil? + + case value + when Accessor, Column + index_info, offset = + match_resolve_index_expression_find_index(expression, + codes, i, n_codes) + i += offset - 1 + if index_info + if value.is_a?(Accessor) + self.flags |= ScanInfo::Flags::ACCESSOR end - put_index(value, section_id, code.weight) + weight, offset = codes[i].weight + i += offset + put_search_index(index_info.index, index_info.section_id, weight) + end + when Procedure + unless value.scorer? + message = "procedure must be scorer: #{scorer.name}>" + raise ErrorMessage, message end + scorer = value i += 1 + index_info, offset = + match_resolve_index_expression_find_index(expression, + codes, i, n_codes) + i += offset + if index_info + scorer_args_expr_offset = 0 + if codes[i].op != Operator::CALL + scorer_args_expr_offset = i + end + while i < n_codes and codes[i].op != Operator::CALL + i += 1 + end + weight, offset = codes[i].weight + i += offset + search_index = ScanInfoSearchIndex.new(index_info.index, + index_info.section_id, + weight, + scorer, + expression, + scorer_args_expr_offset) + @search_indexes << search_index + end + when Table + raise ErrorMessage, "invalid match target: <#{value.name}>" end + i + 1 + end + + def match_resolve_index_expression_find_index(expression, codes, i, n_codes) + code = codes[i] + value = code.value + index_info = nil + offset = 1 + case value + when Accessor + accessor = value + index_info = accessor.find_index(@op) + if index_info + if accessor.have_next? and index_info.index != accessor.object + index_info = IndexInfo.new(accessor, index_info.section_id) + end + end + when FixedSizeColumn, VariableSizeColumn + index_info = value.find_index(@op) + when IndexColumn + index = value + section_id = 0 + rest_n_codes = n_codes - i + if rest_n_codes >= 2 and + codes[i + 1].value.is_a?(Bulk) and + (codes[i + 1].value.domain == ID::UINT32 or + codes[i + 1].value.domain == ID::INT32) and + codes[i + 2].op == Operator::GET_MEMBER + section_id = codes[i + 1].value.value + 1 + offset += 2 + end + index_info = IndexInfo.new(index, section_id) + end + + [index_info, offset] end def match_resolve_index_expression_accessor(expr_code) @@ -136,10 +241,13 @@ module Groonga self.flags |= ScanInfo::Flags::ACCESSOR index_info = accessor.find_index(op) return if index_info.nil? + + section_id = index_info.section_id + weight = expr_code.weight if accessor.next - put_index(accessor, index_info.section_id, expr_code.weight) + put_search_index(accessor, section_id, weight) else - put_index(index_info.index, index_info.section_id, expr_code.weight) + put_search_index(index_info.index, section_id, weight) end end @@ -147,13 +255,13 @@ module Groonga column = expr_code.value index_info = column.find_index(op) return if index_info.nil? - put_index(index_info.index, index_info.section_id, expr_code.weight) + put_search_index(index_info.index, index_info.section_id, expr_code.weight) end def match_resolve_index_db_obj(db_obj) index_info = db_obj.find_index(op) return if index_info.nil? - put_index(index_info.index, index_info.section_id, 1) + put_search_index(index_info.index, index_info.section_id, 1) end def match_resolve_index_accessor(accessor) @@ -161,9 +269,9 @@ module Groonga index_info = accessor.find_index(op) return if index_info.nil? if accessor.next - put_index(accessor, index_info.section_id, 1) + put_search_index(accessor, index_info.section_id, 1) else - put_index(index_info.index, index_info.section_id, 1) + put_search_index(index_info.index, index_info.section_id, 1) end end @@ -181,18 +289,19 @@ module Groonga def call_relational_resolve_index_db_obj(db_obj) index_info = db_obj.find_index(op) return if index_info.nil? - put_index(index_info.index, index_info.section_id, 1) + put_search_index(index_info.index, index_info.section_id, 1) end def call_relational_resolve_index_accessor(accessor) self.flags |= ScanInfo::Flags::ACCESSOR index_info = accessor.find_index(op) return if index_info.nil? - put_index(index_info.index, index_info.section_id, 1) + put_search_index(index_info.index, index_info.section_id, 1) end - def put_index(index, section_id, weight) - @indexes << [index, section_id, weight] + def put_search_index(index, section_id, weight) + search_index = ScanInfoSearchIndex.new(index, section_id, weight) + @search_indexes << search_index end end end diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/scan_info_search_index.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/scan_info_search_index.rb new file mode 100644 index 00000000000..a2818160310 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/scan_info_search_index.rb @@ -0,0 +1,9 @@ +module Groonga + class ScanInfoSearchIndex < Struct.new(:index_column, + :section_id, + :weight, + :scorer, + :scorer_args_expr, + :scorer_args_expr_offset) + end +end diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/sources.am b/storage/mroonga/vendor/groonga/lib/mrb/scripts/sources.am index 93ade1627e6..5ddcba18d4c 100644 --- a/storage/mroonga/vendor/groonga/lib/mrb/scripts/sources.am +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/sources.am @@ -1,13 +1,23 @@ RUBY_SCRIPT_FILES = \ backtrace_entry.rb \ + command.rb \ context.rb \ - context/error_level.rb \ - context/rc.rb \ + database.rb \ + error.rb \ eval_context.rb \ expression.rb \ + expression_size_estimator.rb \ + index_column.rb \ + index_cursor.rb \ index_info.rb \ logger.rb \ - logger/level.rb \ + object.rb \ + operator.rb \ + plugin_loader.rb \ + require.rb \ scan_info.rb \ scan_info_builder.rb \ - scan_info_data.rb + scan_info_data.rb \ + scan_info_search_index.rb \ + table_cursor.rb \ + writer.rb diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/table_cursor.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/table_cursor.rb new file mode 100644 index 00000000000..a36d88d556d --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/table_cursor.rb @@ -0,0 +1,26 @@ +module Groonga + class TableCursor + class << self + def open(*arguments) + cursor = open_raw(*arguments) + if block_given? + begin + yield(cursor) + ensure + cursor.close + end + else + cursor + end + end + end + + def each + loop do + id = self.next + return if id == Groonga::ID::NIL + yield(id) + end + end + end +end diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/writer.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/writer.rb new file mode 100644 index 00000000000..de2bc2611e9 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/writer.rb @@ -0,0 +1,21 @@ +module Groonga + class Writer + def array(name, n_elements) + open_array(name, n_elements) + begin + yield + ensure + close_array + end + end + + def map(name, n_elements) + open_map(name, n_elements) + begin + yield + ensure + close_map + end + end + end +end |