📄 sqlparser.java
字号:
break;
case ')':
parenCnt--;
out[d++] = c; s++;
break;
default:
out[d++] = c; s++;
break;
}
}
String args = String.valueOf(out, argStart, d - argStart).trim();
d = argStart;
mustbe(')', false);
terminator = tc;
skipWhiteSpace();
//
// Process convert scalar function.
// Arguments need to be reversed and the data type
// argument converted to an SQL server type
//
if ("convert".equals(name) && arg2Start < args.length() - 1) {
String arg2 = args.substring(arg2Start + 1).trim().toLowerCase();
String dataType = (String) cvMap.get(arg2);
if (dataType == null) {
// Will get server error if invalid type passed
dataType = arg2;
}
copyLiteral("convert(");
copyLiteral(dataType);
out[d++] = ',';
copyLiteral(args.substring(0, arg2Start));
out[d++] = ')';
return;
}
//
// See if function mapped
//
String fn;
if (connection.getServerType() == Driver.SQLSERVER) {
fn = (String) msFnMap.get(name);
if (fn == null) {
fn = (String) fnMap.get(name);
}
} else {
fn = (String) fnMap.get(name);
}
if (fn == null) {
// Not mapped so assume simple case
copyLiteral(name);
out[d++] = '(';
copyLiteral(args);
out[d++] = ')';
return;
}
//
// Process timestamp interval constants
//
if (args.length() > 8
&& args.substring(0, 8).equalsIgnoreCase("sql_tsi_")) {
args = args.substring(8);
if (args.length() > 11
&& args.substring(0, 11).equalsIgnoreCase("frac_second")) {
args = "millisecond" + args.substring(11);
}
}
//
// Substitute mapped function name and arguments
//
final int len = fn.length();
for (int i = 0; i < len; i++) {
final char c = fn.charAt(i);
if (c == '$') {
// Substitute arguments
copyLiteral(args);
} else {
out[d++] = c;
}
}
}
/**
* Processes the JDBC escape {escape 'X'}.
*
* @throws SQLException
*/
private void likeEscape() throws SQLException {
copyLiteral("escape ");
skipWhiteSpace();
if (in[s] == '\'' || in[s] == '"') {
copyString();
} else {
mustbe('\'', true);
}
skipWhiteSpace();
}
/**
* Processes the JDBC escape sequences.
*
* @throws SQLException
*/
private void escape() throws SQLException {
char tc = terminator;
terminator = '}';
StringBuffer escBuf = new StringBuffer();
s++;
skipWhiteSpace();
if (in[s] == '?') {
copyParam("@return_status", -1);
skipWhiteSpace();
mustbe('=', false);
skipWhiteSpace();
while (Character.isLetter(in[s])) {
escBuf.append(Character.toLowerCase(in[s++]));
}
skipWhiteSpace();
String esc = escBuf.toString();
if ("call".equals(esc)) {
callEscape();
} else {
throw new SQLException(
Messages.get("error.parsesql.syntax",
"call",
String.valueOf(s)),
"22019");
}
} else {
while (Character.isLetter(in[s])) {
escBuf.append(Character.toLowerCase(in[s++]));
}
skipWhiteSpace();
String esc = escBuf.toString();
if ("call".equals(esc)) {
callEscape();
} else if ("t".equals(esc)) {
if (!getDateTimeField(timeMask)) {
throw new SQLException(
Messages.get("error.parsesql.syntax",
"time",
String.valueOf(s)),
"22019");
}
} else if ("d".equals(esc)) {
if (!getDateTimeField(dateMask)) {
throw new SQLException(
Messages.get("error.parsesql.syntax",
"date",
String.valueOf(s)),
"22019");
}
} else if ("ts".equals(esc)) {
if (!getDateTimeField(timestampMask)) {
throw new SQLException(
Messages.get("error.parsesql.syntax",
"timestamp",
String.valueOf(s)),
"22019");
}
} else if ("oj".equals(esc)) {
outerJoinEscape();
} else if ("fn".equals(esc)) {
functionEscape();
} else if ("escape".equals(esc)) {
likeEscape();
} else {
throw new SQLException(
Messages.get("error.parsesql.badesc",
esc,
String.valueOf(s)),
"22019");
}
}
mustbe('}', false);
terminator = tc;
}
/**
* Extracts the first table name following the keyword FROM.
*
* @return the table name as a <code>String</code>
*/
private String getTableName() throws SQLException {
StringBuffer name = new StringBuffer(128);
copyWhiteSpace();
char c = (s < len) ? in[s] : ' ';
if (c == '{') {
// Start of {oj ... } we can assume that there is
// more than one table in select and therefore
// it would not be updateable.
return "";
}
//
// Skip any leading comments before first table name
//
while (c == '/' || c == '-' && s + 1 < len) {
if (c == '/') {
if (in[s + 1] == '*') {
skipMultiComments();
} else {
break;
}
} else {
if (in[s + 1] == '-') {
skipSingleComments();
} else {
break;
}
}
copyWhiteSpace();
c = (s < len) ? in[s] : ' ';
}
if (c == '{') {
// See comment above
return "";
}
//
// Now process table name
//
while (s < len) {
if (c == '[' || c == '"') {
int start = d;
copyString();
name.append(String.valueOf(out, start, d - start));
copyWhiteSpace();
c = (s < len) ? in[s] : ' ';
} else {
int start = d;
c = (s < len) ? in[s++] : ' ';
while ((isIdentifier(c))
&& c != '.'
&& c != ',') {
out[d++] = c;
c = (s < len) ? in[s++] : ' ';
}
name.append(String.valueOf(out, start, d - start));
s--;
copyWhiteSpace();
c = (s < len) ? in[s] : ' ';
}
if (c != '.') {
break;
}
name.append(c);
out[d++] = c; s++;
copyWhiteSpace();
c = (s < len) ? in[s] : ' ';
}
return name.toString();
}
/**
* Parses the SQL statement processing JDBC escapes and parameter markers.
*
* @param extractTable true to return the first table name in the FROM clause of a select
* @return The processed SQL statement, any procedure name, the first
* SQL keyword and (optionally) the first table name as elements 0 1, 2 and 3 of the
* returned <code>String[]</code>.
* @throws SQLException
*/
String[] parse(boolean extractTable) throws SQLException {
boolean isSelect = false;
boolean isModified = false;
boolean isSlowScan = true;
try {
while (s < len) {
final char c = in[s];
switch (c) {
case '{':
escape();
isModified = true;
break;
case '[':
case '"':
case '\'':
copyString();
break;
case '?':
copyParam(null, d);
break;
case '/':
if (s+1 < len && in[s+1] == '*') {
skipMultiComments();
} else {
out[d++] = c; s++;
}
break;
case '-':
if (s+1 < len && in[s+1] == '-') {
skipSingleComments();
} else {
out[d++] = c; s++;
}
break;
default:
if (isSlowScan && Character.isLetter(c)) {
if (keyWord == null) {
keyWord = copyKeyWord();
if ("select".equals(keyWord)) {
isSelect = true;
}
isSlowScan = extractTable && isSelect;
break;
}
if (extractTable && isSelect) {
String sqlWord = copyKeyWord();
if ("from".equals(sqlWord)) {
// Ensure only first 'from' is processed
isSlowScan = false;
tableName = getTableName();
}
break;
}
}
out[d++] = c; s++;
break;
}
}
//
// Impose a reasonable maximum limit on the number of parameters
// unless the connection is sending statements unprepared (i.e. by
// building a plain query) and this is not a procedure call.
//
if (params != null && params.size() > 255
&& connection.getPrepareSql() != TdsCore.UNPREPARED
&& procName != null) {
int limit = 255; // SQL 6.5 and Sybase < 12.50
if (connection.getServerType() == Driver.SYBASE) {
if (connection.getDatabaseMajorVersion() > 12 ||
connection.getDatabaseMajorVersion() == 12 &&
connection.getDatabaseMinorVersion() >= 50) {
limit = 2000; // Actually 2048 but allow some head room
}
} else {
if (connection.getDatabaseMajorVersion() == 7) {
limit = 1000; // Actually 1024
} else
if (connection.getDatabaseMajorVersion() > 7) {
limit = 2000; // Actually 2100
}
}
if (params.size() > limit) {
throw new SQLException(
Messages.get("error.parsesql.toomanyparams",
Integer.toString(limit)),
"22025");
}
}
String result[] = new String[4];
// return sql and procname
result[0] = (isModified) ? new String(out, 0, d) : sql;
result[1] = procName;
result[2] = (keyWord == null) ? "" : keyWord;
result[3] = tableName;
return result;
} catch (IndexOutOfBoundsException e) {
// Should only come here if string is invalid in some way.
throw new SQLException(
Messages.get("error.parsesql.missing",
String.valueOf(terminator)),
"22025");
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -