Skip to content
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

Newline in batch CREATE FUNCTION causes lexical error in OrientDB #444

Open
MarttiR opened this issue Feb 25, 2021 · 1 comment
Open

Newline in batch CREATE FUNCTION causes lexical error in OrientDB #444

MarttiR opened this issue Feb 25, 2021 · 1 comment

Comments

@MarttiR
Copy link

MarttiR commented Feb 25, 2021

OrientJS version: 3.0.11

When using CREATE FUNCTION in session.batch(), having a newline in the function body causes a lexical error in OrientDB.

The same CREATE FUNCTION statements work from Functions Management in Studio, although that way the functions get saved without any newlines.

Working example with everything on one line:

await session.batch(`
CREATE FUNCTION newlineTest
"var foo = 'test ok'; return foo;"
IDEMPOTENT TRUE
LANGUAGE JAVASCRIPT
`).all();

But if the code is split into multiple lines...

await session.batch(`
CREATE FUNCTION newlineTest
"var foo = 'test ok';
return foo;"
IDEMPOTENT TRUE
LANGUAGE JAVASCRIPT
`).all();

... it produces an error:

{"name":"OrientDB.ConnectionError [10]","code":10,"message":"Cannot select the server","data":{}}

Stack trace from OrientDB logs:

Uncaught exception in thread OrientDB (/172.19.0.4:2424) <- BinaryClient (/172.19.0.1:45546)
com.orientechnologies.orient.core.sql.parser.TokenMgrError: Lexical error at line 4, column 28.  Encountered: "\n" (10), after : "\"var foo = \'test ok\';"
	at com.orientechnologies.orient.core.sql.parser.OrientSqlTokenManager.getNextToken(OrientSqlTokenManager.java:5460)
	at com.orientechnologies.orient.core.sql.parser.OrientSql.jj_scan_token(OrientSql.java:39075)
	at com.orientechnologies.orient.core.sql.parser.OrientSql.jj_3R_592(OrientSql.java:33962)
	at com.orientechnologies.orient.core.sql.parser.OrientSql.jj_3R_81(OrientSql.java:30002)
	at com.orientechnologies.orient.core.sql.parser.OrientSql.jj_3_16(OrientSql.java:32575)
	at com.orientechnologies.orient.core.sql.parser.OrientSql.jj_3_49(OrientSql.java:32759)
	at com.orientechnologies.orient.core.sql.parser.OrientSql.jj_3R_71(OrientSql.java:32931)
	at com.orientechnologies.orient.core.sql.parser.OrientSql.jj_3R_232(OrientSql.java:32997)
	at com.orientechnologies.orient.core.sql.parser.OrientSql.jj_3R_69(OrientSql.java:33018)
	at com.orientechnologies.orient.core.sql.parser.OrientSql.jj_3_3(OrientSql.java:33987)
	at com.orientechnologies.orient.core.sql.parser.OrientSql.jj_2_3(OrientSql.java:23786)
	at com.orientechnologies.orient.core.sql.parser.OrientSql.parseScript(OrientSql.java:307)
	at com.orientechnologies.orient.core.sql.OSQLEngine.parseScript(OSQLEngine.java:91)
	at com.orientechnologies.orient.core.sql.OSQLEngine.parseScript(OSQLEngine.java:85)
	at com.orientechnologies.orient.core.command.OSqlScriptExecutor.execute(OSqlScriptExecutor.java:58)
	at com.orientechnologies.orient.core.db.document.ODatabaseDocumentEmbedded.execute(ODatabaseDocumentEmbedded.java:784)
	at com.orientechnologies.orient.server.OConnectionBinaryExecutor.executeQuery(OConnectionBinaryExecutor.java:1494)
	at com.orientechnologies.orient.client.remote.message.OQueryRequest.execute(OQueryRequest.java:143)
	at com.orientechnologies.orient.server.network.protocol.binary.ONetworkProtocolBinary.sessionRequest(ONetworkProtocolBinary.java:355)
	at com.orientechnologies.orient.server.network.protocol.binary.ONetworkProtocolBinary.execute(ONetworkProtocolBinary.java:239)
	at com.orientechnologies.common.thread.OSoftThread.run(OSoftThread.java:67)

Workaround

As a workaround, the newlines can be escaped, but this can be a burden for larger scripts:

await session.batch(`
CREATE FUNCTION newlineTest
"var foo = 'test ok'; \
return foo;"
IDEMPOTENT TRUE
LANGUAGE JAVASCRIPT
`).all();

These examples use JavaScript functions, but the problem is the same when creating functions with LANGUAGE SQL.

@MarttiR
Copy link
Author

MarttiR commented Mar 1, 2021

A significantly better workaround is to not use the CREATE FUNCTION statement, but instead construct an INSERT statement. This is also how Function Management in Studio inserts functions.

Make sure to escape backslashes, pipes and double quotes from the code.

const statement = `INSERT INTO OFunction CONTENT {
  "name": "someFunction",
  "code": "${someFunctionCodeString.replace(/\\|"/g, (m) => '\\'+m)}",
  "parameters": ["param1","param2"],
  "idempotent": true,
  "language": "JAVASCRIPT"
};`;

As an idea for future development: the above is done so functions can be kept in their own .js and .sql files, from which jest-docblock parses @idempotent and @param pragmas; the filename and extension are used for function name and language.

Having everything about the function in one file is a nice pattern for organizing custom functions, and it would be great if OrientJS included a function manager that did this out-of-the-box.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant