null+****@clear*****
null+****@clear*****
2012年 8月 3日 (金) 21:43:16 JST
Kouhei Sutou 2012-08-03 21:43:16 +0900 (Fri, 03 Aug 2012) New Revision: 6f79ed1c6601231e6bcc5170b14bd6cbce3261fb https://github.com/groonga/gcs/commit/6f79ed1c6601231e6bcc5170b14bd6cbce3261fb Log: bq: pass query as property instead of argument Modified files: lib/bq-translator.js test/bq-translator.test.js Modified: lib/bq-translator.js (+99 -105) =================================================================== --- lib/bq-translator.js 2012-08-03 21:31:56 +0900 (e001cf3) +++ lib/bq-translator.js 2012-08-03 21:43:16 +0900 (4cf3daf) @@ -17,84 +17,81 @@ */ -function BooleanQueryTranslator() { +function BooleanQueryTranslator(query) { + this.query = query; + this.offset = 0; + this.defaultField = null; } -function throwTranslateError(query, context, detail) { - var message = ""; - message += "<"; - message += query.substring(0, context.offset); - message += "|" + query[context.offset] + "|"; - message += query.substring(context.offset + 1); - message += ">"; - message += ": " + detail; - throw new Error(message); -}; - BooleanQueryTranslator.prototype = { - translate: function(query, defaultField) { - var context = { - defaultField: defaultField, - offset: 0 - }; + translate: function() { var expression; - if (query[0] == "(") { - expression = this.translateGroup(query, context); + if (this.query[0] == "(") { + expression = this.translateGroup(); } else { - expression = this.translateExpression(query, context); + expression = this.translateExpression(); } - if (context.offset != query.length) { - throwTranslateError(query, context, - "garbages exist after valid boolean query"); + if (this.offset != this.query.length) { + this.throwTranslateError("garbages exist after valid boolean query"); } return expression; }, - skipSpaces: function(query, context) { - for (; context.offset < query.length; context.offset++) { - if (query[context.offset] != " ") { + throwTranslateError: function(detail) { + var message = ""; + message += "<"; + message += this.query.substring(0, this.offset); + message += "|" + this.query[this.offset] + "|"; + message += this.query.substring(this.offset + 1); + message += ">"; + message += ": " + detail; + throw new Error(message); + }, + skipSpaces: function() { + for (; this.offset < this.query.length; this.offset++) { + if (this.query[this.offset] != " ") { return; } } }, - translateGroup: function(query, context) { - if (query[context.offset] != "(") { + translateGroup: function() { + if (this.query[this.offset] != "(") { // TODO: report error return ""; } - context.offset++; + this.offset++; var operator = ""; - for (; context.offset < query.length; context.offset++) { - var character = query[context.offset]; + for (; this.offset < this.query.length; this.offset++) { + var character = this.query[this.offset]; if (/^[a-z]$/.test(character)) { operator += character; } else if (character == " ") { - this.skipSpaces(query, context); + this.skipSpaces(); var expression; switch (operator) { case "field": - expression = this.translateGroupField(query, context); + expression = this.translateGroupField(); break; case "filter": - expression = this.translateGroupFilter(query, context); + expression = this.translateGroupFilter(); break; case "and": - expression = this.translateGroupSetOperation(query, "&&", context); + expression = this.translateGroupSetOperation("&&"); break; case "or": - expression = this.translateGroupSetOperation(query, "||", context); + expression = this.translateGroupSetOperation("||"); break; default: // TODO: report error: unknown operator return ""; break; } - this.skipSpaces(query, context); - if (query[context.offset] != ")") { + this.skipSpaces(); + if (this.query[this.offset] != ")") { // TODO: report error: have garbage return ""; } - context.offset++; + this.offset++; return expression; } else if (character == ")") { // TODO: report error: no arguments for operator @@ -108,19 +105,17 @@ BooleanQueryTranslator.prototype = { // TODO: report error: missing close paren <)> return ""; }, - translateGroupField: function(query, context) { + translateGroupField: function() { var field = ""; - for (; context.offset < query.length; context.offset++) { - var character = query[context.offset]; + for (; this.offset < this.query.length; this.offset++) { + var character = this.query[this.offset]; if (/^[\-a-z0-9]$/.test(character)) { field += character; } else if (character == " ") { - this.skipSpaces(query, context); - var expression = this.translateExpressionValueString(query, - field, - context); - this.skipSpaces(query, context); - if (query[context.offset] != ")") { + this.skipSpaces(); + var expression = this.translateExpressionValueString(field); + this.skipSpaces(); + if (this.query[this.offset] != ")") { // TODO: report error: have garbage return ""; } @@ -137,19 +132,17 @@ BooleanQueryTranslator.prototype = { // TODO: report error: missing close paren <)> return ""; }, - translateGroupFilter: function(query, context) { + translateGroupFilter: function() { var field = ""; - for (; context.offset < query.length; context.offset++) { - var character = query[context.offset]; + for (; this.offset < this.query.length; this.offset++) { + var character = this.query[this.offset]; if (/^[\-a-z0-9]$/.test(character)) { field += character; } else if (character == " ") { - this.skipSpaces(query, context); - var expression = this.translateExpressionValueUnsignedInteger(query, - field, - context); - this.skipSpaces(query, context); - if (query[context.offset] != ")") { + this.skipSpaces(); + var expression = this.translateExpressionValueUnsignedInteger(field); + this.skipSpaces(); + if (this.query[this.offset] != ")") { // TODO: report error: have garbage return ""; } @@ -166,77 +159,77 @@ BooleanQueryTranslator.prototype = { // TODO: report error: missing close paren <)> return ""; }, - translateGroupSetOperation: function(query, setOperator, context) { + translateGroupSetOperation: function(setOperator) { var expressions = []; - while (context.offset < query.length) { - this.skipSpaces(query, context); - if (query[context.offset] == ")") { + while (this.offset < this.query.length) { + this.skipSpaces(); + if (this.query[this.offset] == ")") { return "(" + expressions.join(" " + setOperator + " ") + ")"; } else { - expressions.push(this.translateExpression(query, context)); + expressions.push(this.translateExpression()); } } // TODO: report error: missing close paren <)> return ""; }, - translateExpression: function(query, context) { - if (query[context.offset] == "(") { - return this.translateGroup(query, context); + translateExpression: function() { + if (this.query[this.offset] == "(") { + return this.translateGroup(); } - var startOffset = context.offset; + var startOffset = this.offset; var field; - if (/^[a-z0-9]$/.test(query[context.offset])) { + if (/^[a-z0-9]$/.test(this.query[this.offset])) { field = ""; - for (; context.offset < query.length; context.offset++) { - var character = query[context.offset]; + for (; this.offset < this.query.length; this.offset++) { + var character = this.query[this.offset]; if (!/^[\-a-z0-9]$/.test(character)) { break; } field += character; } - if (query[context.offset] == ":") { - context.offset++; + if (this.query[this.offset] == ":") { + this.offset++; } else { var is_unsigned_integer_value = /^[0-9]+$/.test(field); if (is_unsigned_integer_value) { - field = context.defaultField; - context.offset = startOffset; + field = this.defaultField; + this.offset = startOffset; } else { // TODO: report error: field and value separator ":" is missing return ""; } } } else { - field = context.defaultField; + field = this.defaultField; } - if (query[context.offset] == "'") { - return this.translateExpressionValueString(query, field, context); + if (this.query[this.offset] == "'") { + return this.translateExpressionValueString(field); } - if (/^[0-9.]/.test(query[context.offset])) { - return this.translateExpressionValueUnsignedInteger(query, field, context); + if (/^[0-9.]/.test(this.query[this.offset])) { + return this.translateExpressionValueUnsignedInteger(field); } // TODO: report error return ""; }, - translateExpressionValueString: function(query, field, context) { - if (query[context.offset] != "'") { + translateExpressionValueString: function(field) { + if (this.query[this.offset] != "'") { // TODO: report error return ""; } - if (query[context.offset + 1] == "\"") { - return this.translateExpressionValuePhrase(query, field, context); + if (this.query[this.offset + 1] == "\"") { + return this.translateExpressionValuePhrase(field); } - context.offset++; + this.offset++; var values = []; var value = ""; - for (; context.offset < query.length; context.offset++) { - var character = query[context.offset]; + for (; this.offset < this.query.length; this.offset++) { + var character = this.query[this.offset]; if (character == "'") { - context.offset++; + this.offset++; values.push("\"" + value + "\""); var expressions = values.map(function (value) { return field + " @ " + value; @@ -250,8 +243,8 @@ BooleanQueryTranslator.prototype = { value = ""; } } else if (character == "\\") { - context.offset++; - character = query[context.offset]; + this.offset++; + character = this.query[this.offset]; value += character; } else if (character == "\"") { value += "\\\""; @@ -263,32 +256,33 @@ BooleanQueryTranslator.prototype = { // TODO: report error: missing close quote <'> return ""; }, - translateExpressionValuePhrase: function(query, field, context) { - if (!(query[context.offset] == "'" && query[context.offset + 1] == "\"")) { + translateExpressionValuePhrase: function(field) { + if (!(this.query[this.offset] == "'" && + this.query[this.offset + 1] == "\"")) { // TODO: report error return ""; } - context.offset += 2; + this.offset += 2; var value = ""; - for (; context.offset < query.length; context.offset++) { - var character = query[context.offset]; + for (; this.offset < this.query.length; this.offset++) { + var character = this.query[this.offset]; if (character == "'") { // TODO: report error: missing close quote <"> return ""; } if (character == "\\") { - context.offset++; - character = query[context.offset]; + this.offset++; + character = this.query[this.offset]; value += character; } else if (character == "\"") { - context.offset++; - if (query[context.offset] != "'") { + this.offset++; + if (this.query[this.offset] != "'") { // TODO: report error: missing close quote <'> after <"> return ""; } - context.offset++; + this.offset++; return field + " @ " + "\"" + value + "\""; } else { value += character; @@ -298,22 +292,22 @@ BooleanQueryTranslator.prototype = { // TODO: report error: missing close quote <"'> return ""; }, - translateExpressionValueUnsignedInteger: function(query, field, context) { + translateExpressionValueUnsignedInteger: function(field) { var is_range = false; var min = ""; var max = ""; - for (; context.offset < query.length; context.offset++) { - var character = query[context.offset]; + for (; this.offset < this.query.length; this.offset++) { + var character = this.query[this.offset]; if (!/^[0-9]$/.test(character)) { break; } min += character; } - if (query[context.offset] == "." && query[context.offset + 1] == ".") { + if (this.query[this.offset] == "." && this.query[this.offset + 1] == ".") { is_range = true; - context.offset += 2; - for (; context.offset < query.length; context.offset++) { - var character = query[context.offset]; + this.offset += 2; + for (; this.offset < this.query.length; this.offset++) { + var character = this.query[this.offset]; if (!/^[0-9]$/.test(character)) { break; } Modified: test/bq-translator.test.js (+14 -18) =================================================================== --- test/bq-translator.test.js 2012-08-03 21:31:56 +0900 (85c6ec3) +++ test/bq-translator.test.js 2012-08-03 21:43:16 +0900 (0dfba86) @@ -8,19 +8,21 @@ var BooleanQueryTranslator = require('../lib/bq-translator').BooleanQueryTransla function testQuery(label, query, expected) { test('query: ' + label + ': ' + '<' + query + '> -> <' + expected + '>', function() { - var translator = new BooleanQueryTranslator(); - assert.equal(translator.translate(query, "field"), + var translator = new BooleanQueryTranslator(query); + translator.defaultField = "field"; + assert.equal(translator.translate(), expected); }); } function testQueryError(label, query, context, detail) { test('error: query: ' + label + ': ' + '<' + query + '>', function() { - var translator = new BooleanQueryTranslator(); + var translator = new BooleanQueryTranslator(query); + translator.defaultField = "field"; var actualError; assert.throw(function() { try { - translator.translate(query, "field"); + translator.translate(); } catch (error) { actualError = error; throw error; @@ -33,15 +35,12 @@ function testQueryError(label, query, context, detail) { function testGroup(label, group, expectedOffset, expectedScriptGrnExpr) { test('gorup: ' + label + ': ' + '<' + group + '> -> <' + expectedScriptGrnExpr + '>', function() { - var translator = new BooleanQueryTranslator(); - var context = { - defaultField: "field", - offset: 0 - }; - var actualScriptGrnExpr = translator.translateGroup(group, context); + var translator = new BooleanQueryTranslator(group); + translator.defaultField = "field"; + var actualScriptGrnExpr = translator.translateGroup(); assert.deepEqual({ scriptGrnExpr: actualScriptGrnExpr, - offset: context.offset + offset: translator.offset }, { scriptGrnExpr: expectedScriptGrnExpr, @@ -54,16 +53,13 @@ function testExpression(label, expression, expectedOffset, expectedScriptGrnExpr) { test('expression: ' + label + ': ' + '<' + expression + '> -> <' + expectedScriptGrnExpr + '>', function() { - var translator = new BooleanQueryTranslator(); - var context = { - defaultField: "field", - offset: 0 - }; + var translator = new BooleanQueryTranslator(expression); + translator.defaultField = "field"; var actualScriptGrnExpr = - translator.translateExpression(expression, context); + translator.translateExpression(); assert.deepEqual({ scriptGrnExpr: actualScriptGrnExpr, - offset: context.offset + offset: translator.offset }, { scriptGrnExpr: expectedScriptGrnExpr, -------------- next part -------------- HTML$B$NE:IU%U%!%$%k$rJ]4I$7$^$7$?(B...Download