mirror of
https://github.com/alibaba/druid.git
synced 2023-03-04 19:17:16 +00:00
add testcase & bug fixed for sql-wall
This commit is contained in:
@@ -1,491 +1,489 @@
|
||||
/*
|
||||
* Copyright 1999-2011 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.alibaba.druid.sql.dialect.mysql.parser;
|
||||
|
||||
import static com.alibaba.druid.sql.parser.CharTypes.isFirstIdentifierChar;
|
||||
import static com.alibaba.druid.sql.parser.CharTypes.isIdentifierChar;
|
||||
import static com.alibaba.druid.sql.parser.LayoutCharacters.EOI;
|
||||
import static com.alibaba.druid.sql.parser.Token.LITERAL_CHARS;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import com.alibaba.druid.sql.parser.Keywords;
|
||||
import com.alibaba.druid.sql.parser.Lexer;
|
||||
import com.alibaba.druid.sql.parser.NotAllowCommentException;
|
||||
import com.alibaba.druid.sql.parser.ParserException;
|
||||
import com.alibaba.druid.sql.parser.Token;
|
||||
|
||||
public class MySqlLexer extends Lexer {
|
||||
|
||||
public final static Keywords DEFAULT_MYSQL_KEYWORDS;
|
||||
|
||||
static {
|
||||
Map<String, Token> map = new HashMap<String, Token>();
|
||||
|
||||
map.putAll(Keywords.DEFAULT_KEYWORDS.getKeywords());
|
||||
|
||||
map.put("DUAL", Token.DUAL);
|
||||
map.put("FALSE", Token.FALSE);
|
||||
map.put("IDENTIFIED", Token.IDENTIFIED);
|
||||
map.put("IF", Token.IF);
|
||||
map.put("KILL", Token.KILL);
|
||||
|
||||
map.put("LIMIT", Token.LIMIT);
|
||||
map.put("TRUE", Token.TRUE);
|
||||
map.put("BINARY", Token.BINARY);
|
||||
map.put("SHOW", Token.SHOW);
|
||||
map.put("CACHE", Token.CACHE);
|
||||
map.put("ANALYZE", Token.ANALYZE);
|
||||
map.put("OPTIMIZE", Token.OPTIMIZE);
|
||||
|
||||
DEFAULT_MYSQL_KEYWORDS = new Keywords(map);
|
||||
}
|
||||
|
||||
public MySqlLexer(char[] input, int inputLength, boolean skipComment){
|
||||
super(input, inputLength, skipComment);
|
||||
super.keywods = DEFAULT_MYSQL_KEYWORDS;
|
||||
}
|
||||
|
||||
public MySqlLexer(String input){
|
||||
super(input);
|
||||
super.keywods = DEFAULT_MYSQL_KEYWORDS;
|
||||
}
|
||||
|
||||
public void scanSharp() {
|
||||
if (ch != '#') {
|
||||
throw new ParserException("illegal stat");
|
||||
}
|
||||
|
||||
if (charAt(pos + 1) == '{') {
|
||||
scanVariable();
|
||||
return;
|
||||
}
|
||||
|
||||
Token lastToken = this.token;
|
||||
|
||||
scanChar();
|
||||
mark = pos;
|
||||
bufPos = 0;
|
||||
for (;;) {
|
||||
if (ch == '\r') {
|
||||
if (charAt(pos + 1) == '\n') {
|
||||
bufPos += 2;
|
||||
scanChar();
|
||||
break;
|
||||
}
|
||||
bufPos++;
|
||||
break;
|
||||
} else if (ch == EOI) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (ch == '\n') {
|
||||
scanChar();
|
||||
bufPos++;
|
||||
break;
|
||||
}
|
||||
|
||||
scanChar();
|
||||
bufPos++;
|
||||
}
|
||||
|
||||
stringVal = subString(mark, bufPos);
|
||||
token = Token.LINE_COMMENT;
|
||||
|
||||
if (commentHandler != null && commentHandler.handle(lastToken, stringVal)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isAllowComment()) {
|
||||
throw new NotAllowCommentException();
|
||||
}
|
||||
}
|
||||
|
||||
public void scanVariable() {
|
||||
if (ch != '@' && ch != ':' && ch != '#' && ch != '$') {
|
||||
throw new ParserException("illegal variable");
|
||||
}
|
||||
|
||||
mark = pos;
|
||||
bufPos = 1;
|
||||
|
||||
if (charAt(pos + 1) == '@') {
|
||||
ch = charAt(++pos);
|
||||
bufPos++;
|
||||
}
|
||||
|
||||
if (charAt(pos + 1) == '`') {
|
||||
++pos;
|
||||
++bufPos;
|
||||
char ch;
|
||||
for (;;) {
|
||||
ch = charAt(++pos);
|
||||
|
||||
if (ch == '`') {
|
||||
bufPos++;
|
||||
ch = charAt(++pos);
|
||||
break;
|
||||
} else if (ch == EOI) {
|
||||
throw new ParserException("illegal identifier");
|
||||
}
|
||||
|
||||
bufPos++;
|
||||
continue;
|
||||
}
|
||||
|
||||
this.ch = charAt(pos);
|
||||
|
||||
stringVal = subString(mark, bufPos);
|
||||
token = Token.VARIANT;
|
||||
} else if (charAt(pos + 1) == '{') {
|
||||
++pos;
|
||||
++bufPos;
|
||||
char ch;
|
||||
for (;;) {
|
||||
ch = charAt(++pos);
|
||||
|
||||
if (ch == '}') {
|
||||
bufPos++;
|
||||
ch = charAt(++pos);
|
||||
break;
|
||||
} else if (ch == EOI) {
|
||||
throw new ParserException("illegal identifier");
|
||||
}
|
||||
|
||||
bufPos++;
|
||||
continue;
|
||||
}
|
||||
|
||||
this.ch = charAt(pos);
|
||||
|
||||
stringVal = subString(mark, bufPos);
|
||||
token = Token.VARIANT;
|
||||
} else {
|
||||
for (;;) {
|
||||
ch = charAt(++pos);
|
||||
|
||||
if (!isIdentifierChar(ch)) {
|
||||
break;
|
||||
}
|
||||
|
||||
bufPos++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
this.ch = charAt(pos);
|
||||
|
||||
stringVal = subString(mark, bufPos);
|
||||
token = Token.VARIANT;
|
||||
}
|
||||
|
||||
public void scanIdentifier() {
|
||||
final char first = ch;
|
||||
|
||||
if (ch == '`') {
|
||||
|
||||
mark = pos;
|
||||
bufPos = 1;
|
||||
char ch;
|
||||
for (;;) {
|
||||
ch = charAt(++pos);
|
||||
|
||||
if (ch == '`') {
|
||||
bufPos++;
|
||||
ch = charAt(++pos);
|
||||
break;
|
||||
} else if (ch == EOI) {
|
||||
throw new ParserException("illegal identifier");
|
||||
}
|
||||
|
||||
bufPos++;
|
||||
continue;
|
||||
}
|
||||
|
||||
this.ch = charAt(pos);
|
||||
|
||||
stringVal = subString(mark, bufPos);
|
||||
Token tok = keywods.getKeyword(stringVal);
|
||||
if (tok != null) {
|
||||
token = tok;
|
||||
} else {
|
||||
token = Token.IDENTIFIER;
|
||||
}
|
||||
} else {
|
||||
|
||||
final boolean firstFlag = isFirstIdentifierChar(first);
|
||||
if (!firstFlag) {
|
||||
throw new ParserException("illegal identifier");
|
||||
}
|
||||
|
||||
mark = pos;
|
||||
bufPos = 1;
|
||||
char ch;
|
||||
for (;;) {
|
||||
ch = charAt(++pos);
|
||||
|
||||
if (!isIdentifierChar(ch)) {
|
||||
break;
|
||||
}
|
||||
|
||||
bufPos++;
|
||||
continue;
|
||||
}
|
||||
|
||||
this.ch = charAt(pos);
|
||||
|
||||
stringVal = addSymbol();
|
||||
Token tok = keywods.getKeyword(stringVal);
|
||||
if (tok != null) {
|
||||
token = tok;
|
||||
} else {
|
||||
token = Token.IDENTIFIER;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected final void scanString() {
|
||||
{
|
||||
boolean hasSpecial = false;
|
||||
int startIndex = pos + 1;
|
||||
int endIndex = -1; // text.indexOf('\'', startIndex);
|
||||
for (int i = startIndex; i < text.length(); ++i) {
|
||||
final char ch = text.charAt(i);
|
||||
if (ch == '\\') {
|
||||
hasSpecial = true;
|
||||
continue;
|
||||
}
|
||||
if (ch == '\'') {
|
||||
endIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (endIndex == -1) {
|
||||
throw new ParserException("unclosed str");
|
||||
}
|
||||
|
||||
String stringVal = subString(startIndex, endIndex - startIndex);
|
||||
// hasSpecial = stringVal.indexOf('\\') != -1;
|
||||
|
||||
if (!hasSpecial) {
|
||||
this.stringVal = stringVal;
|
||||
int pos = endIndex + 1;
|
||||
char ch = charAt(pos);
|
||||
if (ch != '\'') {
|
||||
this.pos = pos;
|
||||
this.ch = ch;
|
||||
token = LITERAL_CHARS;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mark = pos;
|
||||
boolean hasSpecial = false;
|
||||
for (;;) {
|
||||
if (isEOF()) {
|
||||
lexError("unclosed.str.lit");
|
||||
return;
|
||||
}
|
||||
|
||||
ch = charAt(++pos);
|
||||
|
||||
if (ch == '\\') {
|
||||
scanChar();
|
||||
if (!hasSpecial) {
|
||||
initBuff(bufPos);
|
||||
arraycopy(mark + 1, buf, 0, bufPos);
|
||||
hasSpecial = true;
|
||||
}
|
||||
|
||||
switch (ch) {
|
||||
case '\0':
|
||||
putChar('\0');
|
||||
break;
|
||||
case '\'':
|
||||
putChar('\'');
|
||||
break;
|
||||
case '"':
|
||||
putChar('"');
|
||||
break;
|
||||
case 'b':
|
||||
putChar('\b');
|
||||
break;
|
||||
case 'n':
|
||||
putChar('\n');
|
||||
break;
|
||||
case 'r':
|
||||
putChar('\r');
|
||||
break;
|
||||
case 't':
|
||||
putChar('\t');
|
||||
break;
|
||||
case '\\':
|
||||
putChar('\\');
|
||||
break;
|
||||
case 'Z':
|
||||
putChar((char) 0x1A); // ctrl + Z
|
||||
break;
|
||||
default:
|
||||
putChar(ch);
|
||||
break;
|
||||
}
|
||||
scanChar();
|
||||
}
|
||||
|
||||
if (ch == '\'') {
|
||||
scanChar();
|
||||
if (ch != '\'') {
|
||||
token = LITERAL_CHARS;
|
||||
break;
|
||||
} else {
|
||||
initBuff(bufPos);
|
||||
arraycopy(mark + 1, buf, 0, bufPos);
|
||||
hasSpecial = true;
|
||||
putChar('\'');
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasSpecial) {
|
||||
bufPos++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (bufPos == buf.length) {
|
||||
putChar(ch);
|
||||
} else {
|
||||
buf[bufPos++] = ch;
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasSpecial) {
|
||||
stringVal = "";
|
||||
stringVal = subString(mark + 1, bufPos);
|
||||
} else {
|
||||
stringVal = new String(buf, 0, bufPos);
|
||||
}
|
||||
}
|
||||
|
||||
public void scanComment() {
|
||||
Token lastToken = this.token;
|
||||
|
||||
if (ch != '/' && ch != '-') {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
mark = pos;
|
||||
bufPos = 0;
|
||||
scanChar();
|
||||
|
||||
// /*+ */
|
||||
if (ch == '*') {
|
||||
scanChar();
|
||||
bufPos++;
|
||||
|
||||
while (ch == ' ') {
|
||||
scanChar();
|
||||
bufPos++;
|
||||
}
|
||||
|
||||
boolean isHint = false;
|
||||
int startHintSp = bufPos + 1;
|
||||
if (ch == '!') {
|
||||
isHint = true;
|
||||
scanChar();
|
||||
bufPos++;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
if (ch == EOI) {
|
||||
this.token = Token.ERROR;
|
||||
return;
|
||||
}
|
||||
if (ch == '*' && charAt(pos + 1) == '/') {
|
||||
bufPos += 3;
|
||||
scanChar();
|
||||
scanChar();
|
||||
break;
|
||||
}
|
||||
|
||||
scanChar();
|
||||
bufPos++;
|
||||
}
|
||||
|
||||
if (isHint) {
|
||||
stringVal = subString(mark + startHintSp, (bufPos - startHintSp) - 2);
|
||||
token = Token.HINT;
|
||||
} else {
|
||||
stringVal = subString(mark, bufPos);
|
||||
token = Token.MULTI_LINE_COMMENT;
|
||||
}
|
||||
|
||||
if (token != Token.HINT) {
|
||||
if (commentHandler != null && commentHandler.handle(lastToken, stringVal)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isAllowComment()) {
|
||||
throw new NotAllowCommentException();
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
if (ch == '/' || ch == '-') {
|
||||
scanChar();
|
||||
bufPos++;
|
||||
|
||||
for (;;) {
|
||||
if (ch == '\r') {
|
||||
if (charAt(pos + 1) == '\n') {
|
||||
bufPos += 2;
|
||||
scanChar();
|
||||
break;
|
||||
}
|
||||
bufPos++;
|
||||
break;
|
||||
} else if (ch == EOI) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (ch == '\n') {
|
||||
scanChar();
|
||||
bufPos++;
|
||||
break;
|
||||
}
|
||||
|
||||
scanChar();
|
||||
bufPos++;
|
||||
}
|
||||
|
||||
stringVal = subString(mark, bufPos + 1);
|
||||
token = Token.LINE_COMMENT;
|
||||
|
||||
if (commentHandler != null && commentHandler.handle(lastToken, stringVal)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isAllowComment()) {
|
||||
throw new NotAllowCommentException();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Copyright 1999-2011 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.alibaba.druid.sql.dialect.mysql.parser;
|
||||
|
||||
import static com.alibaba.druid.sql.parser.CharTypes.isFirstIdentifierChar;
|
||||
import static com.alibaba.druid.sql.parser.CharTypes.isIdentifierChar;
|
||||
import static com.alibaba.druid.sql.parser.LayoutCharacters.EOI;
|
||||
import static com.alibaba.druid.sql.parser.Token.LITERAL_CHARS;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import com.alibaba.druid.sql.parser.Keywords;
|
||||
import com.alibaba.druid.sql.parser.Lexer;
|
||||
import com.alibaba.druid.sql.parser.NotAllowCommentException;
|
||||
import com.alibaba.druid.sql.parser.ParserException;
|
||||
import com.alibaba.druid.sql.parser.Token;
|
||||
|
||||
public class MySqlLexer extends Lexer {
|
||||
|
||||
public final static Keywords DEFAULT_MYSQL_KEYWORDS;
|
||||
|
||||
static {
|
||||
Map<String, Token> map = new HashMap<String, Token>();
|
||||
|
||||
map.putAll(Keywords.DEFAULT_KEYWORDS.getKeywords());
|
||||
|
||||
map.put("DUAL", Token.DUAL);
|
||||
map.put("FALSE", Token.FALSE);
|
||||
map.put("IDENTIFIED", Token.IDENTIFIED);
|
||||
map.put("IF", Token.IF);
|
||||
map.put("KILL", Token.KILL);
|
||||
|
||||
map.put("LIMIT", Token.LIMIT);
|
||||
map.put("TRUE", Token.TRUE);
|
||||
map.put("BINARY", Token.BINARY);
|
||||
map.put("SHOW", Token.SHOW);
|
||||
map.put("CACHE", Token.CACHE);
|
||||
map.put("ANALYZE", Token.ANALYZE);
|
||||
map.put("OPTIMIZE", Token.OPTIMIZE);
|
||||
|
||||
DEFAULT_MYSQL_KEYWORDS = new Keywords(map);
|
||||
}
|
||||
|
||||
public MySqlLexer(char[] input, int inputLength, boolean skipComment){
|
||||
super(input, inputLength, skipComment);
|
||||
super.keywods = DEFAULT_MYSQL_KEYWORDS;
|
||||
}
|
||||
|
||||
public MySqlLexer(String input){
|
||||
super(input);
|
||||
super.keywods = DEFAULT_MYSQL_KEYWORDS;
|
||||
}
|
||||
|
||||
public void scanSharp() {
|
||||
if (ch != '#') {
|
||||
throw new ParserException("illegal stat");
|
||||
}
|
||||
|
||||
if (charAt(pos + 1) == '{') {
|
||||
scanVariable();
|
||||
return;
|
||||
}
|
||||
|
||||
Token lastToken = this.token;
|
||||
|
||||
scanChar();
|
||||
mark = pos;
|
||||
bufPos = 0;
|
||||
for (;;) {
|
||||
if (ch == '\r') {
|
||||
if (charAt(pos + 1) == '\n') {
|
||||
bufPos += 2;
|
||||
scanChar();
|
||||
break;
|
||||
}
|
||||
bufPos++;
|
||||
break;
|
||||
} else if (ch == EOI) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (ch == '\n') {
|
||||
scanChar();
|
||||
bufPos++;
|
||||
break;
|
||||
}
|
||||
|
||||
scanChar();
|
||||
bufPos++;
|
||||
}
|
||||
|
||||
stringVal = subString(mark, bufPos);
|
||||
token = Token.LINE_COMMENT;
|
||||
|
||||
if (commentHandler != null && commentHandler.handle(lastToken, stringVal)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isAllowComment()) {
|
||||
throw new NotAllowCommentException();
|
||||
}
|
||||
}
|
||||
|
||||
public void scanVariable() {
|
||||
if (ch != '@' && ch != ':' && ch != '#' && ch != '$') {
|
||||
throw new ParserException("illegal variable");
|
||||
}
|
||||
|
||||
mark = pos;
|
||||
bufPos = 1;
|
||||
|
||||
if (charAt(pos + 1) == '@') {
|
||||
ch = charAt(++pos);
|
||||
bufPos++;
|
||||
}
|
||||
|
||||
if (charAt(pos + 1) == '`') {
|
||||
++pos;
|
||||
++bufPos;
|
||||
char ch;
|
||||
for (;;) {
|
||||
ch = charAt(++pos);
|
||||
|
||||
if (ch == '`') {
|
||||
bufPos++;
|
||||
ch = charAt(++pos);
|
||||
break;
|
||||
} else if (ch == EOI) {
|
||||
throw new ParserException("illegal identifier");
|
||||
}
|
||||
|
||||
bufPos++;
|
||||
continue;
|
||||
}
|
||||
|
||||
this.ch = charAt(pos);
|
||||
|
||||
stringVal = subString(mark, bufPos);
|
||||
token = Token.VARIANT;
|
||||
} else if (charAt(pos + 1) == '{') {
|
||||
++pos;
|
||||
++bufPos;
|
||||
char ch;
|
||||
for (;;) {
|
||||
ch = charAt(++pos);
|
||||
|
||||
if (ch == '}') {
|
||||
bufPos++;
|
||||
ch = charAt(++pos);
|
||||
break;
|
||||
} else if (ch == EOI) {
|
||||
throw new ParserException("illegal identifier");
|
||||
}
|
||||
|
||||
bufPos++;
|
||||
continue;
|
||||
}
|
||||
|
||||
this.ch = charAt(pos);
|
||||
|
||||
stringVal = subString(mark, bufPos);
|
||||
token = Token.VARIANT;
|
||||
} else {
|
||||
for (;;) {
|
||||
ch = charAt(++pos);
|
||||
|
||||
if (!isIdentifierChar(ch)) {
|
||||
break;
|
||||
}
|
||||
|
||||
bufPos++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
this.ch = charAt(pos);
|
||||
|
||||
stringVal = subString(mark, bufPos);
|
||||
token = Token.VARIANT;
|
||||
}
|
||||
|
||||
public void scanIdentifier() {
|
||||
final char first = ch;
|
||||
|
||||
if (ch == '`') {
|
||||
|
||||
mark = pos;
|
||||
bufPos = 1;
|
||||
char ch;
|
||||
for (;;) {
|
||||
ch = charAt(++pos);
|
||||
|
||||
if (ch == '`') {
|
||||
bufPos++;
|
||||
ch = charAt(++pos);
|
||||
break;
|
||||
} else if (ch == EOI) {
|
||||
throw new ParserException("illegal identifier");
|
||||
}
|
||||
|
||||
bufPos++;
|
||||
continue;
|
||||
}
|
||||
|
||||
this.ch = charAt(pos);
|
||||
|
||||
stringVal = subString(mark, bufPos);
|
||||
Token tok = keywods.getKeyword(stringVal);
|
||||
if (tok != null) {
|
||||
token = tok;
|
||||
} else {
|
||||
token = Token.IDENTIFIER;
|
||||
}
|
||||
} else {
|
||||
|
||||
final boolean firstFlag = isFirstIdentifierChar(first);
|
||||
if (!firstFlag) {
|
||||
throw new ParserException("illegal identifier");
|
||||
}
|
||||
|
||||
mark = pos;
|
||||
bufPos = 1;
|
||||
char ch;
|
||||
for (;;) {
|
||||
ch = charAt(++pos);
|
||||
|
||||
if (!isIdentifierChar(ch)) {
|
||||
break;
|
||||
}
|
||||
|
||||
bufPos++;
|
||||
continue;
|
||||
}
|
||||
|
||||
this.ch = charAt(pos);
|
||||
|
||||
stringVal = addSymbol();
|
||||
Token tok = keywods.getKeyword(stringVal);
|
||||
if (tok != null) {
|
||||
token = tok;
|
||||
} else {
|
||||
token = Token.IDENTIFIER;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected final void scanString() {
|
||||
{
|
||||
boolean hasSpecial = false;
|
||||
int startIndex = pos + 1;
|
||||
int endIndex = -1; // text.indexOf('\'', startIndex);
|
||||
for (int i = startIndex; i < text.length(); ++i) {
|
||||
final char ch = text.charAt(i);
|
||||
if (ch == '\\') {
|
||||
hasSpecial = true;
|
||||
continue;
|
||||
}
|
||||
if (ch == '\'') {
|
||||
endIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (endIndex == -1) {
|
||||
throw new ParserException("unclosed str");
|
||||
}
|
||||
|
||||
String stringVal = subString(startIndex, endIndex - startIndex);
|
||||
// hasSpecial = stringVal.indexOf('\\') != -1;
|
||||
|
||||
if (!hasSpecial) {
|
||||
this.stringVal = stringVal;
|
||||
int pos = endIndex + 1;
|
||||
char ch = charAt(pos);
|
||||
if (ch != '\'') {
|
||||
this.pos = pos;
|
||||
this.ch = ch;
|
||||
token = LITERAL_CHARS;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mark = pos;
|
||||
boolean hasSpecial = false;
|
||||
for (;;) {
|
||||
if (isEOF()) {
|
||||
lexError("unclosed.str.lit");
|
||||
return;
|
||||
}
|
||||
|
||||
ch = charAt(++pos);
|
||||
|
||||
if (ch == '\\') {
|
||||
scanChar();
|
||||
if (!hasSpecial) {
|
||||
initBuff(bufPos);
|
||||
arraycopy(mark + 1, buf, 0, bufPos);
|
||||
hasSpecial = true;
|
||||
}
|
||||
|
||||
switch (ch) {
|
||||
case '\0':
|
||||
putChar('\0');
|
||||
break;
|
||||
case '\'':
|
||||
putChar('\'');
|
||||
break;
|
||||
case '"':
|
||||
putChar('"');
|
||||
break;
|
||||
case 'b':
|
||||
putChar('\b');
|
||||
break;
|
||||
case 'n':
|
||||
putChar('\n');
|
||||
break;
|
||||
case 'r':
|
||||
putChar('\r');
|
||||
break;
|
||||
case 't':
|
||||
putChar('\t');
|
||||
break;
|
||||
case '\\':
|
||||
putChar('\\');
|
||||
break;
|
||||
case 'Z':
|
||||
putChar((char) 0x1A); // ctrl + Z
|
||||
break;
|
||||
default:
|
||||
putChar(ch);
|
||||
break;
|
||||
}
|
||||
scanChar();
|
||||
}
|
||||
|
||||
if (ch == '\'') {
|
||||
scanChar();
|
||||
if (ch != '\'') {
|
||||
token = LITERAL_CHARS;
|
||||
break;
|
||||
} else {
|
||||
initBuff(bufPos);
|
||||
arraycopy(mark + 1, buf, 0, bufPos);
|
||||
hasSpecial = true;
|
||||
putChar('\'');
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasSpecial) {
|
||||
bufPos++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (bufPos == buf.length) {
|
||||
putChar(ch);
|
||||
} else {
|
||||
buf[bufPos++] = ch;
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasSpecial) {
|
||||
stringVal = "";
|
||||
stringVal = subString(mark + 1, bufPos);
|
||||
} else {
|
||||
stringVal = new String(buf, 0, bufPos);
|
||||
}
|
||||
}
|
||||
|
||||
public void scanComment() {
|
||||
Token lastToken = this.token;
|
||||
|
||||
if (ch != '/' && ch != '-') {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
mark = pos;
|
||||
bufPos = 0;
|
||||
scanChar();
|
||||
|
||||
// /*+ */
|
||||
if (ch == '*') {
|
||||
scanChar();
|
||||
bufPos++;
|
||||
|
||||
while (ch == ' ') {
|
||||
scanChar();
|
||||
bufPos++;
|
||||
}
|
||||
|
||||
boolean isHint = false;
|
||||
int startHintSp = bufPos + 1;
|
||||
if (ch == '!') {
|
||||
isHint = true;
|
||||
scanChar();
|
||||
bufPos++;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
if (ch == EOI) {
|
||||
this.token = Token.ERROR;
|
||||
return;
|
||||
}
|
||||
if (ch == '*' && charAt(pos + 1) == '/') {
|
||||
bufPos += 3;
|
||||
scanChar();
|
||||
scanChar();
|
||||
break;
|
||||
}
|
||||
|
||||
scanChar();
|
||||
bufPos++;
|
||||
}
|
||||
|
||||
if (isHint) {
|
||||
stringVal = subString(mark + startHintSp, (bufPos - startHintSp) - 2);
|
||||
token = Token.HINT;
|
||||
} else {
|
||||
stringVal = subString(mark, bufPos);
|
||||
token = Token.MULTI_LINE_COMMENT;
|
||||
}
|
||||
|
||||
if (commentHandler != null && commentHandler.handle(lastToken, stringVal)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isAllowComment()) {
|
||||
throw new NotAllowCommentException();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
if (ch == '/' || ch == '-') {
|
||||
scanChar();
|
||||
bufPos++;
|
||||
|
||||
for (;;) {
|
||||
if (ch == '\r') {
|
||||
if (charAt(pos + 1) == '\n') {
|
||||
bufPos += 2;
|
||||
scanChar();
|
||||
break;
|
||||
}
|
||||
bufPos++;
|
||||
break;
|
||||
} else if (ch == EOI) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (ch == '\n') {
|
||||
scanChar();
|
||||
bufPos++;
|
||||
break;
|
||||
}
|
||||
|
||||
scanChar();
|
||||
bufPos++;
|
||||
}
|
||||
|
||||
stringVal = subString(mark, bufPos + 1);
|
||||
token = Token.LINE_COMMENT;
|
||||
|
||||
if (commentHandler != null && commentHandler.handle(lastToken, stringVal)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isAllowComment()) {
|
||||
throw new NotAllowCommentException();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright 1999-2011 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.alibaba.druid.bvt.filter.wall;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.junit.Assert;
|
||||
|
||||
import com.alibaba.druid.wall.WallProvider;
|
||||
import com.alibaba.druid.wall.spi.MySqlWallProvider;
|
||||
|
||||
/**
|
||||
* SQLServerWallTest
|
||||
*
|
||||
* @author RaymondXiu
|
||||
* @version 1.0, 2012-3-18
|
||||
* @see
|
||||
*/
|
||||
public class MySqlWallTest95 extends TestCase {
|
||||
|
||||
public void test_false() throws Exception {
|
||||
WallProvider provider = new MySqlWallProvider();
|
||||
provider.getConfig().setCommentAllow(false);
|
||||
|
||||
Assert.assertFalse(provider.checkValid(//
|
||||
"select * from test /*!40101fff*/"));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright 1999-2011 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.alibaba.druid.bvt.sql.mysql;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Assert;
|
||||
|
||||
import com.alibaba.druid.sql.MysqlTest;
|
||||
import com.alibaba.druid.sql.SQLUtils;
|
||||
import com.alibaba.druid.sql.ast.SQLStatement;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSelect;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSelectStatement;
|
||||
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectQueryBlock;
|
||||
import com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;
|
||||
import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;
|
||||
import com.alibaba.druid.stat.TableStat;
|
||||
|
||||
public class MySqlSelectTest_13 extends MysqlTest {
|
||||
|
||||
public void test_0() throws Exception {
|
||||
String sql = "select * from test /*!40101fff*/";
|
||||
|
||||
MySqlStatementParser parser = new MySqlStatementParser(sql);
|
||||
List<SQLStatement> statementList = parser.parseStatementList();
|
||||
SQLStatement stmt = statementList.get(0);
|
||||
|
||||
SQLSelectStatement selectStmt = (SQLSelectStatement) stmt;
|
||||
|
||||
SQLSelect select = selectStmt.getSelect();
|
||||
Assert.assertNotNull(select.getQuery());
|
||||
MySqlSelectQueryBlock queryBlock = (MySqlSelectQueryBlock) select.getQuery();
|
||||
Assert.assertNull(queryBlock.getOrderBy());
|
||||
|
||||
print(statementList);
|
||||
|
||||
Assert.assertEquals(1, statementList.size());
|
||||
|
||||
MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();
|
||||
stmt.accept(visitor);
|
||||
|
||||
Assert.assertEquals(1, visitor.getTables().size());
|
||||
Assert.assertEquals(1, visitor.getColumns().size());
|
||||
Assert.assertEquals(0, visitor.getConditions().size());
|
||||
Assert.assertEquals(0, visitor.getOrderByColumns().size());
|
||||
|
||||
Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("test")));
|
||||
|
||||
String output = SQLUtils.toMySqlString(stmt);
|
||||
Assert.assertEquals("SELECT *" //
|
||||
+ "\nFROM test", //
|
||||
output);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user