📄 sqlparser.java
字号:
}
s--;
return new String(out, start, d - start);
}
/**
* Copies over white space.
*/
private void copyWhiteSpace() {
while (s < in.length && Character.isWhitespace(in[s])) {
out[d++] = in[s++];
}
}
/**
* Checks that the next character is as expected.
*
* @param c The expected character.
* @param copy True if found character should be copied.
* @throws SQLException if expected characeter not found.
*/
private void mustbe(char c, boolean copy)
throws SQLException {
if (in[s] != c) {
throw new SQLException(
Messages.get("error.parsesql.mustbe",
String.valueOf(s),
String.valueOf(c)),
"22019");
}
if (copy) {
out[d++] = in[s++];
} else {
s++;
}
}
/**
* Skips embedded white space.
*/
private void skipWhiteSpace() {
while (Character.isWhitespace(in[s])) {
s++;
}
}
/**
* Skips single-line comments.
*/
private void skipSingleComments() {
while (s < len && in[s] != '\n' && in[s] != '\r') {
// comments should be passed on to the server
out[d++] = in[s++];
}
}
/**
* Skips multi-line comments
*/
private void skipMultiComments() throws SQLException {
int block = 0;
do {
if (s < len - 1) {
if (in[s] == '/' && in[s + 1] == '*') {
block++;
} else if (in[s] == '*' && in[s + 1] == '/') {
block--;
}
// comments should be passed on to the server
out[d++] = in[s++];
} else {
throw new SQLException(
Messages.get("error.parsesql.missing", "*/"),
"22025");
}
} while (block > 0);
out[d++] = in[s++];
}
/**
* Processes the JDBC {call procedure [(?,?,?)]} type escape.
*
* @throws SQLException if an error occurs
*/
private void callEscape() throws SQLException {
// Insert EXECUTE into SQL so that proc can be called as normal SQL
copyLiteral("EXECUTE ");
keyWord = "execute";
// Process procedure name
procName = copyProcName();
skipWhiteSpace();
if (in[s] == '(') { // Optional ( )
s++;
terminator = ')';
skipWhiteSpace();
} else {
terminator = '}';
}
out[d++] = ' ';
// Process any parameters
while (in[s] != terminator) {
String name = null;
if (in[s] == '@') {
// Named parameter
name = copyParamName();
skipWhiteSpace();
mustbe('=', true);
skipWhiteSpace();
if (in[s] == '?') {
copyParam(name, d);
} else {
// Named param has literal value can't call as RPC
procName = "";
}
} else if (in[s] == '?') {
copyParam(name, d);
} else {
// Literal parameter can't call as RPC
procName = "";
}
// Now find terminator or comma
while (in[s] != terminator && in[s] != ',') {
if (in[s] == '{') {
escape();
} else if (in[s] == '\'' || in[s] == '[' || in[s] == '"') {
copyString();
} else {
out[d++] = in[s++];
}
}
if (in[s] == ',') {
out[d++] = in[s++];
}
skipWhiteSpace();
}
if (terminator == ')') {
s++; // Elide
}
terminator = '}';
skipWhiteSpace();
}
/**
* Utility routine to validate date and time escapes.
*
* @param mask The validation mask
* @return True if the escape was valid and processed OK.
*/
private boolean getDateTimeField(byte[] mask) throws SQLException {
skipWhiteSpace();
if (in[s] == '?') {
// Allow {ts ?} type construct
copyParam(null, d);
skipWhiteSpace();
return in[s] == terminator;
}
out[d++] = '\'';
terminator = (in[s] == '\'' || in[s] == '"') ? in[s++] : '}';
skipWhiteSpace();
int ptr = 0;
while (ptr < mask.length) {
char c = in[s++];
if (c == ' ' && out[d - 1] == ' ') {
continue; // Eliminate multiple spaces
}
if (mask[ptr] == '#') {
if (!Character.isDigit(c)) {
return false;
}
} else if (mask[ptr] != c) {
return false;
}
if (c != '-') {
out[d++] = c;
}
ptr++;
}
if (mask.length == 19) { // Timestamp
int digits = 0;
if (in[s] == '.') {
out[d++] = in[s++];
while (Character.isDigit(in[s])) {
if (digits < 3) {
out[d++] = in[s++];
digits++;
} else {
s++;
}
}
} else {
out[d++] = '.';
}
for (; digits < 3; digits++) {
out[d++] = '0';
}
}
skipWhiteSpace();
if (in[s] != terminator) {
return false;
}
if (terminator != '}') {
s++; // Skip terminator
}
skipWhiteSpace();
out[d++] = '\'';
return true;
}
/** Syntax mask for time escape. */
private static final byte[] timeMask = {
'#','#',':','#','#',':','#','#'
};
/** Syntax mask for date escape. */
private static final byte[] dateMask = {
'#','#','#','#','-','#','#','-','#','#'
};
/** Syntax mask for timestamp escape. */
static final byte[] timestampMask = {
'#','#','#','#','-','#','#','-','#','#',' ',
'#','#',':','#','#',':','#','#'
};
/**
* Processes the JDBC escape {oj left outer join etc}.
*
* @throws SQLException
*/
private void outerJoinEscape()
throws SQLException {
while (in[s] != '}') {
final char c = in[s];
switch (c) {
case '\'':
case '"':
case '[':
copyString();
break;
case '{':
// Nested escape!
escape();
break;
case '?':
copyParam(null, d);
break;
default:
out[d++] = c;
s++;
break;
}
}
}
/** Map of jdbc to sybase function names. */
private static HashMap fnMap = new HashMap();
/** Map of jdbc to sql server function names. */
private static HashMap msFnMap = new HashMap();
/** Map of jdbc to server data types for convert */
private static HashMap cvMap = new HashMap();
static {
// Microsoft only functions
msFnMap.put("length", "len($)");
msFnMap.put("truncate", "round($, 1)");
// Common functions
fnMap.put("user", "user_name($)");
fnMap.put("database", "db_name($)");
fnMap.put("ifnull", "isnull($)");
fnMap.put("now", "getdate($)");
fnMap.put("atan2", "atn2($)");
fnMap.put("mod", "($)");
fnMap.put("length", "char_length($)");
fnMap.put("locate", "charindex($)");
fnMap.put("repeat", "replicate($)");
fnMap.put("insert", "stuff($)");
fnMap.put("lcase", "lower($)");
fnMap.put("ucase", "upper($)");
fnMap.put("concat", "($)");
fnMap.put("curdate", "convert(datetime, convert(varchar, getdate(), 112))");
fnMap.put("curtime", "convert(datetime, convert(varchar, getdate(), 108))");
fnMap.put("dayname", "datename(weekday,$)");
fnMap.put("dayofmonth", "datepart(day,$)");
fnMap.put("dayofweek", "((datepart(weekday,$)+@@DATEFIRST-1)%7+1)");
fnMap.put("dayofyear", "datepart(dayofyear,$)");
fnMap.put("hour", "datepart(hour,$)");
fnMap.put("minute", "datepart(minute,$)");
fnMap.put("second", "datepart(second,$)");
fnMap.put("year", "datepart(year,$)");
fnMap.put("quarter", "datepart(quarter,$)");
fnMap.put("month", "datepart(month,$)");
fnMap.put("week", "datepart(week,$)");
fnMap.put("monthname", "datename(month,$)");
fnMap.put("timestampadd", "dateadd($)");
fnMap.put("timestampdiff", "datediff($)");
// convert jdbc to sql types
cvMap.put("binary", "varbinary");
cvMap.put("char", "varchar");
cvMap.put("date", "datetime");
cvMap.put("double", "float");
cvMap.put("longvarbinary", "image");
cvMap.put("longvarchar", "text");
cvMap.put("time", "datetime");
cvMap.put("timestamp", "timestamp");
}
/**
* Processes the JDBC escape {fn function()}.
*
* @throws SQLException
*/
private void functionEscape() throws SQLException {
char tc = terminator;
skipWhiteSpace();
StringBuffer nameBuf = new StringBuffer();
//
// Capture name
//
while (isIdentifier(in[s])) {
nameBuf.append(in[s++]);
}
String name = nameBuf.toString().toLowerCase();
//
// Now collect arguments
//
skipWhiteSpace();
mustbe('(', false);
int parenCnt = 1;
int argStart = d;
int arg2Start = 0;
terminator = ')';
while (in[s] != ')' || parenCnt > 1) {
final char c = in[s];
switch (c) {
case '\'':
case '"':
case '[':
copyString();
break;
case '{':
// Process nested escapes!
escape();
break;
case ',':
if (arg2Start == 0) {
arg2Start = d - argStart;
}
if ("concat".equals(name)) {
out[d++] = '+'; s++;
} else if ("mod".equals(name)) {
out[d++] = '%'; s++;
} else {
out[d++] = c; s++;
}
break;
case '(':
parenCnt++;
out[d++] = c; s++;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -