-
Notifications
You must be signed in to change notification settings - Fork 689
Add escape sequence support for string literals (\t, \n, \r, etc.) #2331
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
base: develop
Are you sure you want to change the base?
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1460,9 +1460,43 @@ LogicValue | |
|
|
||
| StringValue | ||
| : STRING | ||
| { $$ = new yy.StringValue({value: $1.substr(1,$1.length-2).replace(/(\\\')/g,"'").replace(/(\'\')/g,"'")}); } | ||
| { | ||
| var str = $1.substr(1,$1.length-2).replace(/(\'\')/g,"'"); | ||
| str = str.replace(/\\(.)/g, function(match, char) { | ||
|
||
| switch(char) { | ||
| case 'n': return '\n'; | ||
| case 't': return '\t'; | ||
| case 'r': return '\r'; | ||
| case 'b': return '\b'; | ||
| case 'f': return '\f'; | ||
| case 'v': return '\v'; | ||
| case '\\': return '\\'; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please check if this is being solved via #2335 |
||
| case "'": return "'"; | ||
| case '"': return '"'; | ||
mathiasrw marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| default: return char; | ||
| } | ||
| }); | ||
| $$ = new yy.StringValue({value: str}); | ||
| } | ||
| | NSTRING | ||
| { $$ = new yy.StringValue({value: $1.substr(2,$1.length-3).replace(/(\\\')/g,"'").replace(/(\'\')/g,"'")}); } | ||
| { | ||
| var str = $1.substr(2,$1.length-3).replace(/(\'\')/g,"'"); | ||
| str = str.replace(/\\(.)/g, function(match, char) { | ||
| switch(char) { | ||
| case 'n': return '\n'; | ||
| case 't': return '\t'; | ||
| case 'r': return '\r'; | ||
| case 'b': return '\b'; | ||
| case 'f': return '\f'; | ||
| case 'v': return '\v'; | ||
| case '\\': return '\\'; | ||
| case "'": return "'"; | ||
| case '"': return '"'; | ||
| default: return char; | ||
| } | ||
| }); | ||
| $$ = new yy.StringValue({value: str}); | ||
| } | ||
| ; | ||
|
|
||
| NullValue | ||
|
|
||
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,74 @@ | ||
| if (typeof exports === 'object') { | ||
| var assert = require('assert'); | ||
| var alasql = require('..'); | ||
| } | ||
|
|
||
| describe('Test 134-B - Escape sequences in strings', function () { | ||
| const test = '134B'; | ||
|
|
||
| before(function () { | ||
| alasql('create database test' + test); | ||
| alasql('use test' + test); | ||
| }); | ||
|
|
||
| after(function () { | ||
| alasql('drop database test' + test); | ||
| }); | ||
|
|
||
| it('A) Tab escape sequence', function () { | ||
| var res = alasql("SELECT 'hello\\tworld' AS result"); | ||
| assert.deepEqual(res, [{result: 'hello\tworld'}]); | ||
| }); | ||
|
|
||
| it('B) Newline escape sequence', function () { | ||
| var res = alasql("SELECT 'line1\\nline2' AS result"); | ||
| assert.deepEqual(res, [{result: 'line1\nline2'}]); | ||
| }); | ||
|
|
||
| it('C) Carriage return escape sequence', function () { | ||
| var res = alasql("SELECT 'text\\rmore' AS result"); | ||
| assert.deepEqual(res, [{result: 'text\rmore'}]); | ||
| }); | ||
|
|
||
| it('D) Backslash escape sequence', function () { | ||
| var res = alasql("SELECT 'back\\\\slash' AS result"); | ||
| assert.deepEqual(res, [{result: 'back\\slash'}]); | ||
| }); | ||
|
|
||
| it('E) Form feed escape sequence', function () { | ||
| var res = alasql("SELECT 'page\\fbreak' AS result"); | ||
| assert.deepEqual(res, [{result: 'page\fbreak'}]); | ||
| }); | ||
|
|
||
| it('F) Backspace escape sequence', function () { | ||
| var res = alasql("SELECT 'back\\bspace' AS result"); | ||
| assert.deepEqual(res, [{result: 'back\bspace'}]); | ||
| }); | ||
|
|
||
| it('G) Double quote escape sequence', function () { | ||
| var res = alasql('SELECT "quote\\"here" AS result'); | ||
| assert.deepEqual(res, [{result: 'quote"here'}]); | ||
| }); | ||
|
|
||
| it('H) Mixed escape sequences', function () { | ||
| var res = alasql("SELECT 'Line 1\\nLine 2\\tTabbed\\rCarriage' AS result"); | ||
| assert.deepEqual(res, [{result: 'Line 1\nLine 2\tTabbed\rCarriage'}]); | ||
| }); | ||
|
|
||
| it('I) Escape sequence in WHERE clause', function () { | ||
| alasql('CREATE TABLE test_escapes (id INT, text STRING)'); | ||
| alasql("INSERT INTO test_escapes VALUES (1, 'hello\\tworld')"); | ||
| alasql("INSERT INTO test_escapes VALUES (2, 'no tabs here')"); | ||
|
|
||
| var res = alasql("SELECT * FROM test_escapes WHERE text = 'hello\\tworld'"); | ||
| assert.deepEqual(res, [{id: 1, text: 'hello\tworld'}]); | ||
| }); | ||
|
|
||
| it('J) Single quote still works', function () { | ||
| var res = alasql("SELECT 'Cote d\\'Ivoir' AS result"); | ||
| assert.deepEqual(res, [{result: "Cote d'Ivoir"}]); | ||
|
|
||
| var res2 = alasql("SELECT 'Cote d''Ivoir' AS result"); | ||
| assert.deepEqual(res2, [{result: "Cote d'Ivoir"}]); | ||
| }); | ||
| }); |
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.
@copilot
What is we have a string of data that contains \n, will it then get converted?
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.
Yes, this is the correct behavior. When data contains actual newline characters (after SQL parsing converts
\nto a newline),escapeq()converts them back to\nwhen generating JavaScript code. This ensures the generated JS code is syntactically valid.Flow:
'hello\nworld'→ Parser converts to actual newline → Stored in memory ashello<LF>worldescapeq()converts back to\n→ Generated code:"hello\nworld"Without
escapeq(), strings with newlines/quotes would produce invalid JavaScript syntax.