UNPKG

@yagisumi/groonga-command

Version:

Port of groonga-command and groonga-command-parser.

1,868 lines (1,806 loc) 50.2 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); function integer_value(args, name) { if (name in args) { return parse_integer_value(args[name]); } else { return undefined; } } function parse_integer_value(value) { const n = parseInt(value); return isNaN(n) ? undefined : n; } function array_value(args, name) { if (name in args) { return parse_array_value(args[name]); } else { return []; } } function parse_array_value(value) { return value .trim() .split(/\s*,\s*/) .filter((s) => s.length > 0); } function flags_value(args, name) { if (name in args) { return parse_flags_value(args[name]); } else { return []; } } function parse_flags_value(value) { return value .trim() .split(/\s*[| ]\s*/) .filter((s) => s.length > 0); } function boolean_value(args, name, default_value, invalid) { if (name in args) { return parse_boolean_value(args[name], default_value, invalid); } else { return default_value; } } function parse_boolean_value(value, default_value, invalid) { if (value.length === 0) { return default_value; } if (value === 'yes') { return true; } else if (value === 'no') { return false; } else { return invalid; } } function escapePattern(str) { return str.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&'); } function escapeValue(value) { return `"${value.replace(/[\n"\\]/g, (match) => (match === '\n' ? '\\n' : `\\${match}`))}"`; } function equalsStringPairs(obj1, obj2) { for (const name in obj1) { if (!(name in obj2) || obj1[name] !== obj2[name]) { return false; } } return true; } function isPairArguments(obj) { return typeof obj === 'object'; } function isOrderedArguments(obj) { return obj === undefined || Array.isArray(obj); } function construct_arguments(args, pair_arguments, ordered_arguments, parameter_names = []) { Object.keys(pair_arguments).forEach((key) => { args[key] = pair_arguments[key]; }); for (let i = 0; i < ordered_arguments.length; i++) { const name = parameter_names[i]; if (name == null) { break; } args[name] = ordered_arguments[i]; } } function createCommand(command_name, pair_arguments, ordered_arguments) { if (command_name in GroongaCommand.CommandList) { return new GroongaCommand.CommandList[command_name](pair_arguments, ordered_arguments); } else { return new GroongaCommand(command_name, pair_arguments, ordered_arguments); } } class GroongaCommand { constructor(arg1, arg2, arg3) { this.arguments = Object.create(null); this.path_prefix = '/d/'; if (typeof arg1 === 'string' && isPairArguments(arg2) && isOrderedArguments(arg3)) { this.command_name = arg1; if (arg1 in GroongaCommand.CommandList) { const CommandClass = GroongaCommand.CommandList[arg1]; construct_arguments(this.arguments, arg2, arg3 || [], CommandClass.parameter_names); Object.setPrototypeOf(this, CommandClass.prototype); } else { construct_arguments(this.arguments, arg2, arg3 || []); } } else if (isPairArguments(arg1) && isOrderedArguments(arg2)) { // @ts-ignore 2564 this.command_name = this.constructor.command_name; // @ts-ignore 2564 construct_arguments(this.arguments, arg1, arg2 || [], this.constructor.parameter_names); } else { throw new Error('invalid arguments'); } } has_key(name) { return name in this.arguments; } equals(cmd) { return (cmd === this || (typeof cmd === 'object' && cmd instanceof GroongaCommand && cmd.command_name === this.command_name && equalsStringPairs(cmd.arguments, this.arguments))); } is_uri_format() { return this.original_format === 'uri'; } is_command_format() { return this.original_format === 'command'; } get output_type() { return this.arguments['output_type'] || 'json'; } get request_id() { return this.arguments['request_id']; } to_uri_format(options) { var _a; const prefix = this.path_prefix.endsWith('/') ? this.path_prefix.slice(0, -1) : this.path_prefix; let path = [prefix, this.command_name].join('/'); const exclude = (_a = options === null || options === void 0 ? void 0 : options.exclude) !== null && _a !== void 0 ? _a : []; if (this.has_key('output_type')) { path += `.${this.arguments['output_type']}`; } const queries = []; Object.keys(this.arguments) .sort() .forEach((name) => { if (name !== 'output_type' && !exclude.includes(name)) { queries.push(`${encodeURIComponent(name)}=${encodeURIComponent(this.arguments[name])}`); } }); if (queries.length > 0) { path += `?${queries.join('&')}`; } return path; } to_command_format(options) { var _a, _b; const pretty_print = (_a = options === null || options === void 0 ? void 0 : options.pretty_print) !== null && _a !== void 0 ? _a : false; const exclude = (_b = options === null || options === void 0 ? void 0 : options.exclude) !== null && _b !== void 0 ? _b : []; const components = [this.command_name]; Object.keys(this.arguments) .sort() .forEach((name) => { if (!exclude.includes(name)) { components.push(`--${name} ${escapeValue(this.arguments[name])}`); } }); return pretty_print ? components.join(' \\\n ') : components.join(' '); } toString() { if (this.is_uri_format()) { return this.to_uri_format(); } else { return this.to_command_format(); } } } GroongaCommand.command_name = ''; GroongaCommand.parameter_names = []; GroongaCommand.CommandList = Object.create(null); class ColumnCopy extends GroongaCommand { get from_table() { return this.arguments['from_table']; } get from_name() { return this.arguments['from_name']; } get to_table() { return this.arguments['to_table']; } get to_name() { return this.arguments['to_name']; } } ColumnCopy.command_name = 'column_copy'; ColumnCopy.parameter_names = [ 'from_table', 'from_name', 'to_table', 'to_name', ]; function isColumnCopy(cmd) { return cmd.command_name === ColumnCopy.command_name; } GroongaCommand.CommandList[ColumnCopy.command_name] = ColumnCopy; class ColumnCreate extends GroongaCommand { get table() { return this.arguments['table']; } get name() { return this.arguments['name']; } get flags() { return flags_value(this.arguments, 'flags'); } get type() { return this.arguments['type']; } get COLUMN_SCALAR() { return this.flags.includes('COLUMN_SCALAR'); } get COLUMN_VECTOR() { return this.flags.includes('COLUMN_VECTOR'); } get COLUMN_INDEX() { return this.flags.includes('COLUMN_INDEX'); } get WITH_SECTION() { return this.flags.includes('WITH_SECTION'); } get WITH_WEIGHT() { return this.flags.includes('WITH_WEIGHT'); } get WITH_POSITION() { return this.flags.includes('WITH_POSITION'); } get sources() { return array_value(this.arguments, 'source'); } } ColumnCreate.command_name = 'column_create'; ColumnCreate.parameter_names = [ 'table', 'name', 'flags', 'type', 'source', ]; function isColumnCreate(cmd) { return cmd.command_name === ColumnCreate.command_name; } GroongaCommand.CommandList[ColumnCreate.command_name] = ColumnCreate; class ColumnList extends GroongaCommand { get table() { return this.arguments['table']; } } ColumnList.command_name = 'column_list'; ColumnList.parameter_names = [ 'table', ]; function isColumnList(cmd) { return cmd.command_name === ColumnList.command_name; } GroongaCommand.CommandList[ColumnList.command_name] = ColumnList; class ColumnRemove extends GroongaCommand { get name() { return this.arguments['name']; } get table() { return this.arguments['table']; } } ColumnRemove.command_name = 'column_remove'; ColumnRemove.parameter_names = [ 'table', 'name', ]; function isColumnRemove(cmd) { return cmd.command_name === ColumnRemove.command_name; } GroongaCommand.CommandList[ColumnRemove.command_name] = ColumnRemove; class ColumnRename extends GroongaCommand { get table() { return this.arguments['table']; } get name() { return this.arguments['name']; } get new_name() { return this.arguments['new_name']; } } ColumnRename.command_name = 'column_rename'; ColumnRename.parameter_names = [ 'table', 'name', 'new_name', ]; function isColumnRename(cmd) { return cmd.command_name === ColumnRename.command_name; } GroongaCommand.CommandList[ColumnRename.command_name] = ColumnRename; class ConfigDelete extends GroongaCommand { get key() { return this.arguments['key']; } } ConfigDelete.command_name = 'config_delete'; ConfigDelete.parameter_names = [ 'key', ]; function isConfigDelete(cmd) { return cmd.command_name === ConfigDelete.command_name; } GroongaCommand.CommandList[ConfigDelete.command_name] = ConfigDelete; class ConfigGet extends GroongaCommand { get key() { return this.arguments['key']; } } ConfigGet.command_name = 'config_get'; ConfigGet.parameter_names = [ 'key', ]; function isConfigGet(cmd) { return cmd.command_name === ConfigGet.command_name; } GroongaCommand.CommandList[ConfigGet.command_name] = ConfigGet; class ConfigSet extends GroongaCommand { get key() { return this.arguments['key']; } get value() { return this.arguments['value']; } } ConfigSet.command_name = 'config_set'; ConfigSet.parameter_names = [ 'key', 'value', ]; function isConfigSet(cmd) { return cmd.command_name === ConfigSet.command_name; } GroongaCommand.CommandList[ConfigSet.command_name] = ConfigSet; class Delete extends GroongaCommand { get table() { return this.arguments['table']; } } Delete.command_name = 'delete'; Delete.parameter_names = [ 'table', 'key', 'id', 'filter', ]; function isDelete(cmd) { return cmd.command_name === Delete.command_name; } GroongaCommand.CommandList[Delete.command_name] = Delete; class Dump extends GroongaCommand { get output_type() { return 'none'; } is_sort_hash_table() { return boolean_value(this.arguments, 'sort_hash_table', false, false); } } Dump.command_name = 'dump'; Dump.parameter_names = [ 'tables', 'dump_plugins', 'dump_schema', 'dump_records', 'dump_indexes', 'dump_configs', 'sort_hash_table', ]; function isDump(cmd) { return cmd.command_name === Dump.command_name; } GroongaCommand.CommandList[Dump.command_name] = Dump; class Get extends GroongaCommand { } Get.command_name = 'get'; Get.parameter_names = [ 'table', 'key', 'output_columns', 'id', ]; function isGet(cmd) { return cmd.command_name === Get.command_name; } GroongaCommand.CommandList[Get.command_name] = Get; class IndexColumnDiff extends GroongaCommand { get table() { return this.arguments['table']; } get name() { return this.arguments['name']; } } IndexColumnDiff.command_name = 'index_column_diff'; IndexColumnDiff.parameter_names = [ 'table', 'name', ]; function isIndexColumnDiff(cmd) { return cmd.command_name === IndexColumnDiff.command_name; } GroongaCommand.CommandList[IndexColumnDiff.command_name] = IndexColumnDiff; class IOFlush extends GroongaCommand { get target_name() { return this.arguments['target_name']; } is_recursive() { return this.arguments['recursive'] !== 'no'; } } IOFlush.command_name = 'io_flush'; IOFlush.parameter_names = [ 'target_name', 'recursive', ]; function isIOFlush(cmd) { return cmd.command_name === IOFlush.command_name; } GroongaCommand.CommandList[IOFlush.command_name] = IOFlush; class Load extends GroongaCommand { get table() { return this.arguments['table']; } set table(name) { if (name) { this.arguments['table'] = name; } else { delete this.arguments['table']; } } parse_values(values) { if (values === undefined) { return undefined; } else { return JSON.parse(values); } } get values() { return this.parse_values(this.arguments['values']); } set values(values) { if (Array.isArray(values)) { this.arguments['values'] = JSON.stringify(values); } } parse_columns(columns) { if (columns === undefined) { return []; } else { return columns.split(/\s*,\s*/).filter((str) => str.length > 0); } } get columns() { return this.parse_columns(this.arguments['columns']); } set columns(columns) { if (columns.length === 0) { delete this.arguments['columns']; } else { this.arguments['columns'] = columns.join(','); } } is_output_ids() { return boolean_value(this.arguments, 'output_ids', false, false); } } Load.command_name = 'load'; Load.parameter_names = [ 'values', 'table', 'columns', 'ifexists', 'input_type', 'each', 'output_ids', ]; function isLoad(cmd) { return cmd.command_name === Load.command_name; } GroongaCommand.CommandList[Load.command_name] = Load; class LogicalCount extends GroongaCommand { get logical_table() { return this.arguments['logical_table']; } get shard_key() { return this.arguments['shard_key']; } get min() { return this.arguments['min']; } get min_border() { return this.arguments['min_border']; } get max() { return this.arguments['max']; } get max_border() { return this.arguments['max_border']; } get filter() { return this.arguments['filter']; } } LogicalCount.command_name = 'logical_count'; LogicalCount.parameter_names = [ 'logical_table', 'shard_key', 'min', 'min_border', 'max', 'max_border', 'filter', ]; function isLogicalCount(cmd) { return cmd.command_name === LogicalCount.command_name; } GroongaCommand.CommandList[LogicalCount.command_name] = LogicalCount; function split_filter_conditions(args) { return (args['filter'] || '') .split(/(?:&&|&!|\|\|)/) .filter((str) => str.length > 0) .map((condition) => { let cond = condition.trim().replace(/^[\s(]*/g, ''); if (!cond.match(/\(/)) { cond = cond.replace(/[\s)]*$/g, ''); } return cond; }); } function Searchable(Base) { return class extends Base { get conditions() { return split_filter_conditions(this.arguments); } }; } class LogicalRangeFilter extends Searchable(GroongaCommand) { get logical_table() { return this.arguments['logical_table']; } get shard_key() { return this.arguments['shard_key']; } get min() { return this.arguments['min']; } get min_border() { return this.arguments['min_border']; } get max() { return this.arguments['max']; } get max_border() { return this.arguments['max_border']; } get order() { return this.arguments['order']; } get offset() { return integer_value(this.arguments, 'offset'); } get limit() { return integer_value(this.arguments, 'limit'); } get filter() { return this.arguments['filter']; } get output_columns() { return array_value(this.arguments, 'output_columns'); } get use_range_index() { if ('use_range_index' in this.arguments) { const value = this.arguments['use_range_index']; if (value.length === 0) { return undefined; } if (value === 'yes') { return true; } else if (value === 'no') { return false; } else { return undefined; } } else { return undefined; } } get post_filter() { return this.arguments['post_filter']; } get sort_keys() { return array_value(this.arguments, 'sort_keys'); } } LogicalRangeFilter.command_name = 'logical_range_filter'; LogicalRangeFilter.parameter_names = [ 'logical_table', 'shard_key', 'min', 'min_border', 'max', 'max_border', 'order', 'offset', 'limit', 'filter', 'output_columns', 'use_range_index', 'post_filter', 'sort_keys', ]; function isLogicalRangeFilter(cmd) { return cmd.command_name === LogicalRangeFilter.command_name; } GroongaCommand.CommandList[LogicalRangeFilter.command_name] = LogicalRangeFilter; function parse_labeled_drilldowns(args, prefix = '') { const raw_labeled_drilldowns = Object.create(null); const re_drilldowns = new RegExp(`^${escapePattern(prefix)}drilldowns?\\[(.+?)\\]\\.(.+?)$`); Object.keys(args).forEach((name) => { if (name.match(re_drilldowns)) { const label = RegExp.$1; const parameter_name = RegExp.$2; if (!(label in raw_labeled_drilldowns)) { raw_labeled_drilldowns[label] = Object.create(null); } raw_labeled_drilldowns[label][parameter_name] = args[name]; } }); return build_labeled_drilldowns(raw_labeled_drilldowns); } function build_labeled_drilldowns(raw_labeled_drilldowns) { const labeled_drilldowns = Object.create(null); Object.keys(raw_labeled_drilldowns).forEach((label) => { const raw_drilldown = raw_labeled_drilldowns[label]; const keys = parse_array_value(raw_drilldown['keys'] || ''); const sort_keys = parse_array_value(raw_drilldown['sort_keys'] || raw_drilldown['sortby'] || ''); const output_columns = parse_array_value(raw_drilldown['output_columns'] || ''); const offset = parse_integer_value(raw_drilldown['offset'] || ''); const limit = parse_integer_value(raw_drilldown['limit'] || ''); const calc_types = parse_array_value(raw_drilldown['calc_types'] || ''); const calc_target = raw_drilldown['calc_target']; const filter = raw_drilldown['filter']; const drilldown = { keys, sort_keys, output_columns, calc_types, label, }; if (offset !== undefined) { drilldown.offset = offset; } if (limit !== undefined) { drilldown.limit = limit; } if (calc_target !== undefined) { drilldown.calc_target = calc_target; } if (filter !== undefined) { drilldown.filter = filter; } labeled_drilldowns[label] = drilldown; }); return labeled_drilldowns; } function Drilldownable(Base) { return class extends Base { get drilldown() { return this.arguments['drilldown']; } get drilldowns() { return array_value(this.arguments, 'drilldown'); } get drilldown_filter() { return this.arguments['drilldown_filter']; } get drilldown_sortby() { return this.arguments['drilldown_sortby']; } get drilldown_sort_keys() { var _a, _b; return parse_array_value((_b = (_a = this.arguments['drilldown_sort_keys']) !== null && _a !== void 0 ? _a : this.arguments['drilldown_sortby']) !== null && _b !== void 0 ? _b : ''); } get drilldown_output_columns() { return array_value(this.arguments, 'drilldown_output_columns'); } get drilldown_offset() { return integer_value(this.arguments, 'drilldown_offset'); } get drilldown_limit() { return integer_value(this.arguments, 'drilldown_limit'); } get drilldown_calc_types() { return this.arguments['drilldown_calc_types']; } get drilldown_calc_target() { return this.arguments['drilldown_calc_target']; } get labeled_drilldowns() { return parse_labeled_drilldowns(this.arguments, ''); } }; } function parse_slices(args) { const raw_slices = Object.create(null); Object.keys(args).forEach((name) => { if (name.match(/^slices?\[(.+?)\]\.(.+?)$/)) { const label = RegExp.$1; const parameter_name = RegExp.$2; if (!(label in raw_slices)) { raw_slices[label] = Object.create(null); } raw_slices[label][parameter_name] = args[name]; } }); return build_slices(args, raw_slices); } function build_slices(args, raw_slices) { const slices = Object.create(null); Object.keys(raw_slices).forEach((label) => { const raw_slice = raw_slices[label]; const match_columns = array_value(raw_slice, 'match_columns'); const query = raw_slice['query']; const query_expander = raw_slice['query_expander']; const query_flags = flags_value(raw_slice, 'query_flags'); const filter = raw_slice['filter']; const sort_keys = array_value(raw_slice, 'sort_keys'); const output_columns = array_value(raw_slice, 'output_columns'); const offset = integer_value(raw_slice, 'offset'); const limit = integer_value(raw_slice, 'limit'); const labeled_drilldowns = parse_labeled_drilldowns(args, `slices[${label}].`); const slice = { label, match_columns, query_flags, sort_keys, output_columns, labeled_drilldowns, }; if (query !== undefined) { slice.query = query; } if (query_expander !== undefined) { slice.query_expander = query_expander; } if (filter !== undefined) { slice.filter = filter; } if (offset !== undefined) { slice.offset = offset; } if (limit !== undefined) { slice.limit = limit; } slices[label] = slice; }); return slices; } function Sliceable(Base) { return class extends Base { get slices() { return parse_slices(this.arguments); } }; } class LogicalSelect extends Sliceable(Searchable(Drilldownable(GroongaCommand))) { get logical_table() { return this.arguments['logical_table']; } get shard_key() { return this.arguments['shard_key']; } get min() { return this.arguments['min']; } get min_border() { return this.arguments['min_border']; } get max() { return this.arguments['max']; } get max_border() { return this.arguments['max_border']; } get filter() { return this.arguments['filter']; } get sortby() { return this.arguments['sortby']; } get output_columns() { return array_value(this.arguments, 'output_columns'); } get offset() { return integer_value(this.arguments, 'offset'); } get limit() { return integer_value(this.arguments, 'limit'); } get sort_keys() { var _a, _b; return parse_array_value((_b = (_a = this.arguments['sort_keys']) !== null && _a !== void 0 ? _a : this.arguments['sortby']) !== null && _b !== void 0 ? _b : ''); } } LogicalSelect.command_name = 'logical_select'; LogicalSelect.parameter_names = [ 'logical_table', 'shard_key', 'min', 'min_border', 'max', 'max_border', 'filter', 'sortby', 'output_columns', 'offset', 'limit', 'drilldown', 'drilldown_sortby', 'drilldown_output_columns', 'drilldown_offset', 'drilldown_limit', 'drilldown_calc_types', 'drilldown_calc_target', 'sort_keys', 'drilldown_sort_keys', 'match_columns', 'query', 'drilldown_filter', 'load_table', 'load_columns', 'load_values', ]; function isLogicalSelect(cmd) { return cmd.command_name === LogicalSelect.command_name; } GroongaCommand.CommandList[LogicalSelect.command_name] = LogicalSelect; class LogicalShardList extends GroongaCommand { get logical_table() { return this.arguments['logical_table']; } } LogicalShardList.command_name = 'logical_shard_list'; LogicalShardList.parameter_names = [ 'logical_table', ]; function isLogicalShardList(cmd) { return cmd.command_name === LogicalShardList.command_name; } GroongaCommand.CommandList[LogicalShardList.command_name] = LogicalShardList; class LogicalTableRemove extends GroongaCommand { get logical_table() { return this.arguments['logical_table']; } get shard_key() { return this.arguments['shard_key']; } get min() { return this.arguments['min']; } get min_border() { return this.arguments['min_border']; } get max() { return this.arguments['max']; } get max_border() { return this.arguments['max_border']; } } LogicalTableRemove.command_name = 'logical_table_remove'; LogicalTableRemove.parameter_names = [ 'logical_table', 'shard_key', 'min', 'min_border', 'max', 'max_border', ]; function isLogicalTableRemove(cmd) { return cmd.command_name === LogicalTableRemove.command_name; } GroongaCommand.CommandList[LogicalTableRemove.command_name] = LogicalTableRemove; class LogLevel extends GroongaCommand { get level() { return this.arguments['level']; } } LogLevel.command_name = 'log_level'; LogLevel.parameter_names = [ 'level', ]; function isLogLevel(cmd) { return cmd.command_name === LogLevel.command_name; } GroongaCommand.CommandList[LogLevel.command_name] = LogLevel; class LogPut extends GroongaCommand { get message() { return this.arguments['message']; } get level() { return this.arguments['level']; } } LogPut.command_name = 'log_put'; LogPut.parameter_names = [ 'level', 'message', ]; function isLogPut(cmd) { return cmd.command_name === LogPut.command_name; } GroongaCommand.CommandList[LogPut.command_name] = LogPut; class Normalize extends GroongaCommand { get normalizer() { return this.arguments['normalizer']; } get string() { return this.arguments['string']; } get flags() { return flags_value(this.arguments, 'flags'); } } Normalize.command_name = 'normalize'; Normalize.parameter_names = [ 'normalizer', 'string', 'flags', ]; function isNormalize(cmd) { return cmd.command_name === Normalize.command_name; } GroongaCommand.CommandList[Normalize.command_name] = Normalize; class ObjectExist extends GroongaCommand { get name() { return this.arguments['name']; } } ObjectExist.command_name = 'object_exist'; ObjectExist.parameter_names = [ 'name', ]; function isObjectExist(cmd) { return cmd.command_name === ObjectExist.command_name; } GroongaCommand.CommandList[ObjectExist.command_name] = ObjectExist; class ObjectInspect extends GroongaCommand { get name() { return this.arguments['name']; } } ObjectInspect.command_name = 'object_inspect'; ObjectInspect.parameter_names = [ 'name', ]; function isObjectInspect(cmd) { return cmd.command_name === ObjectInspect.command_name; } GroongaCommand.CommandList[ObjectInspect.command_name] = ObjectInspect; class ObjectRemove extends GroongaCommand { get name() { return this.arguments['name']; } is_force() { return boolean_value(this.arguments, 'force', false, false); } } ObjectRemove.command_name = 'object_remove'; ObjectRemove.parameter_names = [ 'name', 'force', ]; function isObjectRemove(cmd) { return cmd.command_name === ObjectRemove.command_name; } GroongaCommand.CommandList[ObjectRemove.command_name] = ObjectRemove; class PluginRegister extends GroongaCommand { get name() { return this.arguments['name']; } } PluginRegister.command_name = 'plugin_register'; PluginRegister.parameter_names = [ 'name', ]; function isPluginRegister(cmd) { return cmd.command_name === PluginRegister.command_name; } GroongaCommand.CommandList[PluginRegister.command_name] = PluginRegister; class PluginUnregister extends GroongaCommand { get name() { return this.arguments['name']; } } PluginUnregister.command_name = 'plugin_unregister'; PluginUnregister.parameter_names = [ 'name', ]; function isPluginUnregister(cmd) { return cmd.command_name === PluginUnregister.command_name; } GroongaCommand.CommandList[PluginUnregister.command_name] = PluginUnregister; class QueryExpand extends GroongaCommand { get expander() { return this.arguments['expander']; } get query() { return this.arguments['query']; } get flags() { return flags_value(this.arguments, 'flags'); } get ALLOW_PRAGMA() { return this.flags.includes('ALLOW_PRAGMA'); } get ALLOW_COLUMN() { return this.flags.includes('ALLOW_COLUMN'); } get ALLOW_UPDATE() { return this.flags.includes('ALLOW_UPDATE'); } get ALLOW_LEADING_NOT() { return this.flags.includes('ALLOW_LEADING_NOT'); } get NONE() { return this.flags.includes('NONE'); } } QueryExpand.command_name = 'query_expand'; QueryExpand.parameter_names = [ 'expander', 'query', 'flags', ]; function isQueryExpand(cmd) { return cmd.command_name === QueryExpand.command_name; } GroongaCommand.CommandList[QueryExpand.command_name] = QueryExpand; class QueryLogFlagsAdd extends GroongaCommand { get flags() { return flags_value(this.arguments, 'flags'); } } QueryLogFlagsAdd.command_name = 'query_log_flags_add'; QueryLogFlagsAdd.parameter_names = [ 'flags', ]; function isQueryLogFlagsAdd(cmd) { return cmd.command_name === QueryLogFlagsAdd.command_name; } GroongaCommand.CommandList[QueryLogFlagsAdd.command_name] = QueryLogFlagsAdd; class QueryLogFlagsGet extends GroongaCommand { } QueryLogFlagsGet.command_name = 'query_log_flags_get'; QueryLogFlagsGet.parameter_names = []; function isQueryLogFlagsGet(cmd) { return cmd.command_name === QueryLogFlagsGet.command_name; } GroongaCommand.CommandList[QueryLogFlagsGet.command_name] = QueryLogFlagsGet; class QueryLogFlagsRemove extends GroongaCommand { get flags() { return flags_value(this.arguments, 'flags'); } } QueryLogFlagsRemove.command_name = 'query_log_flags_remove'; QueryLogFlagsRemove.parameter_names = [ 'flags', ]; function isQueryLogFlagsRemove(cmd) { return cmd.command_name === QueryLogFlagsRemove.command_name; } GroongaCommand.CommandList[QueryLogFlagsRemove.command_name] = QueryLogFlagsRemove; class QueryLogFlagsSet extends GroongaCommand { get flags() { return flags_value(this.arguments, 'flags'); } } QueryLogFlagsSet.command_name = 'query_log_flags_set'; QueryLogFlagsSet.parameter_names = [ 'flags', ]; function isQueryLogFlagsSet(cmd) { return cmd.command_name === QueryLogFlagsSet.command_name; } GroongaCommand.CommandList[QueryLogFlagsSet.command_name] = QueryLogFlagsSet; class RangeFilter extends Searchable(GroongaCommand) { get table() { return this.arguments['table']; } get column() { return this.arguments['column']; } get min() { return this.arguments['min']; } get min_border() { return this.arguments['min_border']; } get max() { return this.arguments['max']; } get max_border() { return this.arguments['max_border']; } get offset() { return integer_value(this.arguments, 'offset'); } get limit() { return integer_value(this.arguments, 'limit'); } get filter() { return this.arguments['filter']; } get output_columns() { return array_value(this.arguments, 'output_columns'); } } RangeFilter.command_name = 'range_filter'; RangeFilter.parameter_names = [ 'table', 'column', 'min', 'min_border', 'max', 'max_border', 'offset', 'limit', 'filter', 'output_columns', ]; function isRangeFilter(cmd) { return cmd.command_name === RangeFilter.command_name; } GroongaCommand.CommandList[RangeFilter.command_name] = RangeFilter; class Register extends GroongaCommand { get path() { return this.arguments['path']; } } Register.command_name = 'register'; Register.parameter_names = [ 'path', ]; function isRegister(cmd) { return cmd.command_name === Register.command_name; } GroongaCommand.CommandList[Register.command_name] = Register; class Reindex extends GroongaCommand { get target_name() { return this.arguments['target_name']; } } Reindex.command_name = 'reindex'; Reindex.parameter_names = [ 'target_name', ]; function isReindex(cmd) { return cmd.command_name === Reindex.command_name; } GroongaCommand.CommandList[Reindex.command_name] = Reindex; class RequestCancel extends GroongaCommand { get id() { return this.arguments['id']; } } RequestCancel.command_name = 'request_cancel'; RequestCancel.parameter_names = [ 'id', ]; function isRequestCancel(cmd) { return cmd.command_name === RequestCancel.command_name; } GroongaCommand.CommandList[RequestCancel.command_name] = RequestCancel; class RubyEval extends GroongaCommand { get script() { return this.arguments['script']; } } RubyEval.command_name = 'ruby_eval'; RubyEval.parameter_names = [ 'script', ]; function isRubyEval(cmd) { return cmd.command_name === RubyEval.command_name; } GroongaCommand.CommandList[RubyEval.command_name] = RubyEval; class RubyLoad extends GroongaCommand { get path() { return this.arguments['path']; } } RubyLoad.command_name = 'ruby_load'; RubyLoad.parameter_names = [ 'path', ]; function isRubyLoad(cmd) { return cmd.command_name === RubyLoad.command_name; } GroongaCommand.CommandList[RubyLoad.command_name] = RubyLoad; class Schema extends GroongaCommand { } Schema.command_name = 'schema'; Schema.parameter_names = []; function isSchema(cmd) { return cmd.command_name === Schema.command_name; } GroongaCommand.CommandList[Schema.command_name] = Schema; class Select extends Sliceable(Searchable(Drilldownable(GroongaCommand))) { // incompatible get table() { return this.arguments['table']; } get sortby() { return this.arguments['sortby']; } get sort_keys() { var _a, _b; return parse_array_value((_b = (_a = this.arguments['sort_keys']) !== null && _a !== void 0 ? _a : this.arguments['sortby']) !== null && _b !== void 0 ? _b : ''); } get scorer() { return this.arguments['scorer']; } get filter() { return this.arguments['filter']; } get query() { return this.arguments['query']; } get output_columns() { return array_value(this.arguments, 'output_columns'); } } Select.command_name = 'select'; Select.parameter_names = [ 'table', 'match_columns', 'query', 'filter', 'scorer', 'sortby', 'output_columns', 'offset', 'limit', 'drilldown', 'drilldown_sortby', 'drilldown_output_columns', 'drilldown_offset', 'drilldown_limit', 'cache', 'match_escalation_threshold', 'query_expansion', 'query_flags', 'query_expander', 'adjuster', 'drilldown_calc_types', 'drilldown_calc_target', 'drilldown_filter', 'sort_keys', 'drilldown_sort_keys', ]; function isSelect(cmd) { return cmd.command_name === Select.command_name; } GroongaCommand.CommandList[Select.command_name] = Select; class Shutdown extends GroongaCommand { get mode() { return this.arguments['mode']; } } Shutdown.command_name = 'shutdown'; Shutdown.parameter_names = [ 'mode', ]; function isShutdown(cmd) { return cmd.command_name === Shutdown.command_name; } GroongaCommand.CommandList[Shutdown.command_name] = Shutdown; class Status extends GroongaCommand { } Status.command_name = 'status'; Status.parameter_names = []; function isStatus(cmd) { return cmd.command_name === Status.command_name; } GroongaCommand.CommandList[Status.command_name] = Status; class Suggest extends GroongaCommand { } Suggest.command_name = 'suggest'; Suggest.parameter_names = [ 'types', 'table', 'column', 'query', 'sortby', 'output_columns', 'offset', 'limit', 'frequency_threshold', 'conditional_probability_threshold', 'prefix_search', 'similar_search', ]; function isSuggest(cmd) { return cmd.command_name === Suggest.command_name; } GroongaCommand.CommandList[Suggest.command_name] = Suggest; class TableCopy extends GroongaCommand { get from_name() { return this.arguments['from_name']; } get to_name() { return this.arguments['to_name']; } } TableCopy.command_name = 'table_copy'; TableCopy.parameter_names = [ 'from_name', 'to_name', ]; function isTableCopy(cmd) { return cmd.command_name === TableCopy.command_name; } GroongaCommand.CommandList[TableCopy.command_name] = TableCopy; class TableCreate extends GroongaCommand { get name() { return this.arguments['name']; } get key_type() { return this.arguments['key_type']; } get value_type() { return this.arguments['value_type']; } get flags() { return flags_value(this.arguments, 'flags'); } get TABLE_NO_KEY() { return this.flags.includes('TABLE_NO_KEY'); } get TABLE_HASH_KEY() { return this.flags.includes('TABLE_HASH_KEY'); } get TABLE_PAT_KEY() { return this.flags.includes('TABLE_PAT_KEY'); } get TABLE_DAT_KEY() { return this.flags.includes('TABLE_DAT_KEY'); } get KEY_WITH_SIS() { return this.flags.includes('KEY_WITH_SIS'); } get default_tokenizer() { return this.arguments['default_tokenizer']; } get normalizer() { return this.arguments['normalizer']; } get token_filters() { return array_value(this.arguments, 'token_filters'); } } TableCreate.command_name = 'table_create'; TableCreate.parameter_names = [ 'name', 'flags', 'key_type', 'value_type', 'default_tokenizer', 'normalizer', 'token_filters', ]; function isTableCreate(cmd) { return cmd.command_name === TableCreate.command_name; } GroongaCommand.CommandList[TableCreate.command_name] = TableCreate; class TableList extends GroongaCommand { get prefix() { return this.arguments['prefix']; } } TableList.command_name = 'table_list'; TableList.parameter_names = [ 'prefix', ]; function isTableList(cmd) { return cmd.command_name === TableList.command_name; } GroongaCommand.CommandList[TableList.command_name] = TableList; class TableRemove extends GroongaCommand { get name() { return this.arguments['name']; } is_dependent() { return this.arguments['dependent'] !== 'no'; } } TableRemove.command_name = 'table_remove'; TableRemove.parameter_names = [ 'name', 'dependent', ]; function isTableRemove(cmd) { return cmd.command_name === TableRemove.command_name; } GroongaCommand.CommandList[TableRemove.command_name] = TableRemove; class TableRename extends GroongaCommand { get name() { return this.arguments['name']; } get new_name() { return this.arguments['new_name']; } } TableRename.command_name = 'table_rename'; TableRename.parameter_names = [ 'name', 'new_name', ]; function isTableRename(cmd) { return cmd.command_name === TableRename.command_name; } GroongaCommand.CommandList[TableRename.command_name] = TableRename; class TableTokenize extends GroongaCommand { get table() { return this.arguments['table']; } get string() { return this.arguments['string']; } get flags() { return flags_value(this.arguments, 'flags'); } get mode() { return this.arguments['mode']; } } TableTokenize.command_name = 'table_tokenize'; TableTokenize.parameter_names = [ 'table', 'string', 'flags', 'mode', ]; function isTableTokenize(cmd) { return cmd.command_name === TableTokenize.command_name; } GroongaCommand.CommandList[TableTokenize.command_name] = TableTokenize; class ThreadLimit extends GroongaCommand { get max() { return integer_value(this.arguments, 'max'); } } ThreadLimit.command_name = 'thread_limit'; ThreadLimit.parameter_names = [ 'max', ]; function isThreadLimit(cmd) { return cmd.command_name === ThreadLimit.command_name; } GroongaCommand.CommandList[ThreadLimit.command_name] = ThreadLimit; class Tokenize extends GroongaCommand { get tokenizer() { return this.arguments['tokenizer']; } get string() { return this.arguments['string']; } get normalizer() { return this.arguments['normalizer']; } get flags() { return flags_value(this.arguments, 'flags'); } get mode() { return this.arguments['mode']; } get token_filters() { return array_value(this.arguments, 'token_filters'); } } Tokenize.command_name = 'tokenize'; Tokenize.parameter_names = [ 'tokenizer', 'string', 'normalizer', 'flags', 'mode', 'token_filters', ]; function isTokenize(cmd) { return cmd.command_name === Tokenize.command_name; } GroongaCommand.CommandList[Tokenize.command_name] = Tokenize; class Truncate extends GroongaCommand { get target_name() { return this.arguments['target_name'] || this.arguments['table']; } } Truncate.command_name = 'truncate'; Truncate.parameter_names = [ 'target_name', 'table', ]; function isTruncate(cmd) { return cmd.command_name === Truncate.command_name; } GroongaCommand.CommandList[Truncate.command_name] = Truncate; const TypeGuards = { isColumnCopy, isColumnCreate, isColumnList, isColumnRemove, isColumnRename, isConfigDelete, isConfigGet, isConfigSet, isDelete, isDump, isGet, isIndexColumnDiff, isIOFlush, isLoad, isLogicalCount, isLogicalRangeFilter, isLogicalSelect, isLogicalShardList, isLogicalTableRemove, isLogLevel, isLogPut, isNormalize, isObjectExist, isObjectInspect, isObjectRemove, isPluginRegister, isPluginUnregister, isQueryExpand, isQueryLogFlagsAdd, isQueryLogFlagsGet, isQueryLogFlagsRemove, isQueryLogFlagsSet, isRangeFilter, isRegister, isReindex, isRequestCancel, isRubyEval, isRubyLoad, isSchema, isSelect, isShutdown, isStatus, isSuggest, isTableCopy, isTableCreate, isTableList, isTableRemove, isTableRename, isTableTokenize, isThreadLimit, isTokenize, isTruncate, }; class CommandLineScanner { constructor(str) { this._pos = 0; this.re_spaces = /\s+/y; this.re_nonspaces = /\S+/y; this.re_quote = /['"]/y; this.string = str; } is_end() { return this._pos >= this.string.length; } get pos() { return this._pos; } skip_spaces() { return this.scan(this.re_spaces); } scan_nonspaces() { return this.scan(this.re_nonspaces); } scan_quote() { return this.scan(this.re_quote); } scan(pattern) { pattern.lastIndex = this._pos; const m = this.string.match(pattern); if (m) { this._pos = pattern.lastIndex; return m[0]; } return undefined; } rest() { return this.string.slice(this._pos); } terminate() { this._pos = this.string.length; } scan_until(str) { const idx = this.string.indexOf(str, this._pos); if (idx < 0) { return undefined; } else { const start = this._pos; this._pos = idx + str.length; return this.string.slice(start, this._pos); } } } function unescape(token) { return token.replace(/\\(.)/g, (_, character) => { switch (character) { case 'b': return '\b'; case 'f': return '\f'; case 'n': return '\n'; case 'r': return '\r'; case 't': return '\t'; default: return character; } }); } function splitCommandLine(line) { const tokens = []; const scanner = new CommandLineScanner(line); let start_quote = undefined; scanner.skip_spaces(); while (!scanner.is_end()) { if (start_quote === undefined) { start_quote = scanner.scan_quote(); if (start_quote === undefined) { const token = scanner.scan_nonspaces(); if (token !== undefined) { tokens.push(token); } scanner.skip_spaces(); } } else { let token = ''; while (true) { const chunk = scanner.scan_until(start_quote); if (chunk === undefined) { token = start_quote + token + scanner.rest(); scanner.terminate(); break; } if (chunk.slice(-2, -1) === '\\') { token += chunk; } else { token += chunk.slice(0, -1); break; } } tokens.push(unescape(token)); start_quote = undefined; scanner.skip_spaces(); } } return tokens; } function parseCommand(command_line, pair_arguments) { const line = getCommandString(command_line); const cargs = line.startsWith('/') ? parseUriPath(line) : parseCommandLine(line); if (cargs.name === undefined || cargs.name.length === 0) { return undefined; } const command = createCommand(cargs.name, cargs.pair_arguments, cargs.ordered_arguments); command.original_format = cargs.format; command.original_source = line; if (cargs.path_prefix) { command.path_prefix = cargs.path_prefix; } if (pair_arguments != null) { Object.keys(pair_arguments).forEach((name) => { const v = pair_arguments[name]; if (v != null) { command.arguments[name] = v.toString(); } }); } return command; } function getCommandString(command_line) { const lines = command_line.split(/\r?\n/); let line = lines[0]; if (line.startsWith('/')) { return line; } let idx = 1; let next = lines[idx]; while (line.endsWith('\\') && next !== undefined) { line = line.slice(0, -1) + ' ' + next; idx += 1; next = lines[idx]; } if (line.endsWith('\\')) { line = line.slice(0, -1); } return line; } function parseCommandLine(line) { const [name, ...args] = splitCommandLine(line); const cargs = { pair_arguments: Object.create(null), ordered_arguments: [], format: 'command', }; if (name === undefined || name.length === 0) { return cargs; } cargs.name = name; for (let i = 0; i < args.length; i++) { const arg = args[i]; if (arg.startsWith('--')) { i += 1; const value = args[i]; if (value !== undefined) { cargs.pair_arguments[arg.slice(2)] = value; } } else { cargs.ordered_arguments.push(arg); } } return cargs; } function split(str, pattern) { const pos = str.indexOf(pattern); return pos >= 0 ? [str.slice(0, pos), str.slice(pos + 1)] : [str, '']; } function parseUriPath(line) { const [path, arguments_string] = split(line, '?'); const cargs = { format: 'uri', pair_arguments: Object.create(null), ordered_arguments: [], }; const m = path.match(/\/([^/]*)$/); if (m == null || m[1].length === 0) { return cargs; } const [name, type] = split(m[1], '.'); if (name.length === 0) { return cargs; } cargs.name = name; cargs.path_prefix = path.slice(0, m.index); if (type.length !== 0) { cargs.pair_arguments['output_type'] = type; } arguments_string.split(/&/).forEach((argument_string) => { const [key, value] = split(argument_string, '='); if (key !== '' && value !== '') { cargs.pair_arguments[decodeURIComponent(key)] = decodeURIComponent(value); } }); return cargs; } exports.GroongaCommand = GroongaCom