# This patch file was generated by NetBeans IDE # Following Index: paths are relative to: /home/matthias/NetBeansProjects/core-main # This patch can be applied using context Tools: Patch action on respective folder. # It uses platform neutral UTF-8 encoding and \n newlines. # Above lines and this line are ignored by the patching process. Index: db.sql.editor/src/org/netbeans/modules/db/sql/lexer/SQLLexer.java --- db.sql.editor/src/org/netbeans/modules/db/sql/lexer/SQLLexer.java Base (BASE) +++ db.sql.editor/src/org/netbeans/modules/db/sql/lexer/SQLLexer.java Locally Modified (Based On LOCAL) @@ -168,7 +168,19 @@ state = State.ISA_BACK_SLASH_IN_STRING; break; case '\'': // NOI18N + state = State.ISA_QUOTE_IN_STRING; + break; + } + break; + + case ISA_QUOTE_IN_STRING: + switch (actChar) { + case '\'': + state = State.ISI_STRING; + break; + default: state = State.INIT; + input.backup(1); return factory.createToken(SQLTokenId.STRING); } break; @@ -184,7 +196,12 @@ if (startQuoteChar != -1) { if (!isEndIdentifierQuoteChar(startQuoteChar, actChar)) { break; + } else { + if (actChar == '"') { + state = State.ISA_QUOTE_IN_IDENTIFIER; + break; } + } } else { if (Character.isLetterOrDigit(actChar) || actChar == '_' || actChar == '#') { break; @@ -196,6 +213,19 @@ startQuoteChar = -1; return factory.createToken(testKeyword(input.readText())); + case ISA_QUOTE_IN_IDENTIFIER: + switch (actChar) { + case '"': + state = State.ISI_IDENTIFIER; + break; + default: + state = State.INIT; + startQuoteChar = -1; + input.backup(1); + return factory.createToken(testKeyword(input.readText())); + } + break; + // If we are after a slash (/). case ISA_SLASH: switch (actChar) { @@ -309,13 +339,24 @@ SQLTokenId id = null; PartType part = PartType.COMPLETE; switch (state) { + case ISA_QUOTE_IN_STRING: + id = SQLTokenId.STRING; + break; + + case ISA_QUOTE_IN_IDENTIFIER: + id = SQLTokenId.IDENTIFIER; + break; + case ISI_WHITESPACE: id = SQLTokenId.WHITESPACE; break; case ISI_IDENTIFIER: - startQuoteChar = -1; + if(startQuoteChar == -1) { id = testKeyword(input.readText()); + } else { + id = SQLTokenId.INCOMPLETE_IDENTIFIER; + } break; case ISI_LINE_COMMENT: @@ -397,7 +438,7 @@ } public static boolean isEndIdentifierQuoteChar(int start, int end) { - return end == getMatchingQuote(start); + return isStartIdentifierQuoteChar(start) && end == getMatchingQuote(start); } private static SQLTokenId testKeyword(CharSequence value) { @@ -425,6 +466,8 @@ ISI_INT, // integer number ISI_DOUBLE, // double number ISA_DOT, // after '.' - ISA_BACK_SLASH_IN_STRING // after \ in string + ISA_BACK_SLASH_IN_STRING, // after \ in string + ISA_QUOTE_IN_STRING, // encountered quote in string - could be sql99 escape + ISA_QUOTE_IN_IDENTIFIER // encountered quote in identifier - could be sql99 escape } } Index: db.sql.editor/src/org/netbeans/modules/db/sql/lexer/SQLTokenId.java --- db.sql.editor/src/org/netbeans/modules/db/sql/lexer/SQLTokenId.java Base (BASE) +++ db.sql.editor/src/org/netbeans/modules/db/sql/lexer/SQLTokenId.java Locally Modified (Based On LOCAL) @@ -66,6 +66,7 @@ BLOCK_COMMENT("sql-block-comment"), // NOI18N STRING("sql-string-literal"), // NOI18N INCOMPLETE_STRING("sql-errors"), // NOI18N + INCOMPLETE_IDENTIFIER("sql-errors"), // NOI18N IDENTIFIER("sql-identifier"), // NOI18N OPERATOR("sql-operator"), // NOI18N LPAREN("sql-operator"), // NOI18N Index: db.sql.editor/test/unit/src/org/netbeans/modules/db/sql/lexer/SQLLexerTest.java --- db.sql.editor/test/unit/src/org/netbeans/modules/db/sql/lexer/SQLLexerTest.java Base (BASE) +++ db.sql.editor/test/unit/src/org/netbeans/modules/db/sql/lexer/SQLLexerTest.java Locally Modified (Based On LOCAL) @@ -80,6 +80,47 @@ SQLTokenId.WHITESPACE); } + public void testSimpleSQL99Quoting() throws Exception { + TokenSequence seq = getTokenSequence("select -/ from 'a''' + 1, dto"); + assertTokens(seq, SQLTokenId.KEYWORD, SQLTokenId.WHITESPACE, SQLTokenId.OPERATOR, + SQLTokenId.OPERATOR, SQLTokenId.WHITESPACE, SQLTokenId.KEYWORD, + SQLTokenId.WHITESPACE, SQLTokenId.STRING, SQLTokenId.WHITESPACE, + SQLTokenId.OPERATOR, SQLTokenId.WHITESPACE, SQLTokenId.INT_LITERAL, + SQLTokenId.COMMA, SQLTokenId.WHITESPACE, SQLTokenId.IDENTIFIER, + SQLTokenId.WHITESPACE); + + } + + public void testQuotedIdentifiersSQL99Quote() throws Exception { + TokenSequence seq = getTokenSequence("select \"\"\"derby\", `mysql`, [mssql], `quo + ted`"); + assertTokens(seq, SQLTokenId.KEYWORD, SQLTokenId.WHITESPACE, SQLTokenId.IDENTIFIER, + SQLTokenId.COMMA, SQLTokenId.WHITESPACE, SQLTokenId.IDENTIFIER, + SQLTokenId.COMMA, SQLTokenId.WHITESPACE, SQLTokenId.IDENTIFIER, + SQLTokenId.COMMA, SQLTokenId.WHITESPACE, SQLTokenId.IDENTIFIER, + SQLTokenId.WHITESPACE); + } + + public void testIncompleteIdentifier() throws Exception { + TokenSequence seq = getTokenSequence("select \"\"\"derby\", `mysql`, [mssql], `quo + ted"); + assertTokens(seq, SQLTokenId.KEYWORD, SQLTokenId.WHITESPACE, SQLTokenId.IDENTIFIER, + SQLTokenId.COMMA, SQLTokenId.WHITESPACE, SQLTokenId.IDENTIFIER, + SQLTokenId.COMMA, SQLTokenId.WHITESPACE, SQLTokenId.IDENTIFIER, + SQLTokenId.COMMA, SQLTokenId.WHITESPACE, SQLTokenId.INCOMPLETE_IDENTIFIER); + seq = getTokenSequence("select \"\"\"derby\", `mysql`, [mssql"); + assertTokens(seq, SQLTokenId.KEYWORD, SQLTokenId.WHITESPACE, SQLTokenId.IDENTIFIER, + SQLTokenId.COMMA, SQLTokenId.WHITESPACE, SQLTokenId.IDENTIFIER, + SQLTokenId.COMMA, SQLTokenId.WHITESPACE, SQLTokenId.INCOMPLETE_IDENTIFIER); + seq = getTokenSequence("select \"\"\"derby\", `mysql`, [mssql]"); + assertTokens(seq, SQLTokenId.KEYWORD, SQLTokenId.WHITESPACE, SQLTokenId.IDENTIFIER, + SQLTokenId.COMMA, SQLTokenId.WHITESPACE, SQLTokenId.IDENTIFIER, + SQLTokenId.COMMA, SQLTokenId.WHITESPACE, SQLTokenId.IDENTIFIER, + SQLTokenId.WHITESPACE); + seq = getTokenSequence("select \"\"\"derby"); + assertTokens(seq, SQLTokenId.KEYWORD, SQLTokenId.WHITESPACE, + SQLTokenId.INCOMPLETE_IDENTIFIER); + + } + public void testComments() throws Exception { TokenSequence seq = getTokenSequence("-- line comment\n# mysql comment\n/* block \ncomment*/\n#notComment"); assertTokens(seq, SQLTokenId.LINE_COMMENT, SQLTokenId.LINE_COMMENT,