-
Notifications
You must be signed in to change notification settings - Fork 392
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Placeholder replacement #14
Conversation
I documented params cfg to be a object, but actually it can be either Array or Object.
this.QUOTED_VARIABLE_REGEX = this.createVariableRegex(cfg.variableTypes, this.createStringPattern(cfg.stringTypes)); | ||
this.INDEXED_PLACEHOLDER_REGEX = this.createPlaceholderRegex(cfg.indexedPlaceholderTypes); | ||
this.PLAIN_NAMED_PLACEHOLDER_REGEX = this.createPlaceholderRegex(cfg.namedPlaceholderTypes, "[a-zA-Z0-9._$]+"); | ||
this.STRING_NAMED_PLACEHOLDER_REGEX = this.createPlaceholderRegex( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't really like the name PLAIN_NAMED
. Perhaps better IDENT_NAMED
to emphasize that the name is an identifier.
Speaking of identifiers though, the regex [a-zA-Z0-9._$]+
isn't fully covered by tests - we don't test for the special characters .
, _
and $
. I wonder, do we even really need to support .
and $
.
type: sqlTokenTypes.VARIABLE, | ||
regex: this.QUOTED_VARIABLE_REGEX | ||
type: sqlTokenTypes.PLACEHOLDER, | ||
regex: this.INDEXED_PLACEHOLDER_REGEX | ||
}); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could generalize these three methods - the only difference between them is the regex.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure if we want to do it now when we have two different placeholder types. WDYT @nene ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added a different suggestion which might need a different generalization of the same thing.
" third,\n" + | ||
" first;\n" | ||
); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should order other tests also similarly, so that all tests for @variables
are grouped together like the above tests for $variables
.
0: "first", | ||
1: "second", | ||
2: "third" | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should also have a test that uses plain array instead of object with numeric keys.
if (!this.params) { | ||
return placeholder; | ||
} | ||
const matches = placeholder.match(/\w+(\s+\w+)*/); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't really understand why this regex is the way it is.
I understand that the goal is to detect whether it's a named placeholder. However it doesn't quite work - for example when I have a placeholder that does not consist of just spaces and word characters:
SELECT @'$^&*'
It might be simpler to differentiate between named and indexed placeholders inside tokenizer.
Another thing to consider is escape sequences inside strings:
SELECT @"hello \" world"
# Conflicts: # src/core/Formatter.js
@nene covered your requested changes. |
if (matches) { | ||
return this.params[matches[0]]; | ||
if (key) { | ||
return this.params[key]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We really have three placeholder token types: STRING, INDENT, INDEXED. Currently the INDEXED and INDENT are thrown together (although they're really quite different). By having three distinct types, we could express the three different choices in much clearer way:
switch(type) {
case INDEXED:
case STRING:
case IDENT:
}
Also, I think parsing the contents of the string and indent placeholders should really belong to Tokenizer. The Formatter should not care about the specific syntax that placeholders have. It's also common practice for Lexer to provide both a raw value and some computed value of a token like string. In that scenario we actually won't need 3 token types as STRING and INDENT can be represented with one.
Finally I still think that we should take at least some minimal care about escaping. As the Lexer allows escape sequences like \"
in strings, the parameter replacement should also support them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, we should add some additional tests for the quoted placeholders, something like testing:
SELECT :"^*& weird \" var "
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added one test @nene
type: sqlTokenTypes.VARIABLE, | ||
regex: this.QUOTED_VARIABLE_REGEX | ||
type: sqlTokenTypes.PLACEHOLDER, | ||
regex: this.INDEXED_PLACEHOLDER_REGEX | ||
}); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added a different suggestion which might need a different generalization of the same thing.
I did my best to resolve @nene requested changes. |
@@ -208,6 +208,10 @@ export default class Tokenizer { | |||
return token; | |||
} | |||
|
|||
getEscapedPlaceholderKey({key, stringChar}) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think a better name would be: quoteChar
sqlFormatter.format("SELECT ? FROM table1", { | ||
params: ["bar"] | ||
})); | ||
``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should use a more real-life example. One normally uses placeholders in conditions of WHERE clause like:
SELECT * FROM tbl WHERE foo = ?
I created two different placeholder token regexes (based on if placeholder has a name or not), but there is only one token type: PLACEHOLDER.
I haven't updated README.md yet, lets see what is your opinion on current solution.
Info about N1QL parameterized queries http://developer.couchbase.com/documentation/server/current/sdk/n1ql-query.html