doParseSQL method
String
doParseSQL(
- String sql,
- TSQLParseOptions options,
- TParamStyle parameterStyle,
- TParamBinding paramBinding,
- String macroChar,
- TStringRef replaceString,
Implementation
String doParseSQL(
String sql,
TSQLParseOptions options,
TParamStyle parameterStyle,
TParamBinding paramBinding,
String macroChar,
TStringRef replaceString) {
if (options.contains(TSQLParseOption.spoCreate)) clear();
// Parse the SQL and build ParamBinding (original comment kept as-is)
final escapeSlash = options.contains(TSQLParseOption.spoEscapeSlash);
final escapeRepeat = options.contains(TSQLParseOption.spoEscapeRepeat);
var paramCount = 0;
final paramPartStart = <int>[];
final paramPartStop = <int>[];
paramBinding.clear();
var questionMarkParamCount = 0; // number of ? params found in query
replaceString.value = r'$';
if (parameterStyle == TParamStyle.psSimulated) {
while (sql.contains(replaceString.value)) {
replaceString.value = '${replaceString.value}\$';
}
}
final p = TIntRef(0);
// ParamDelim
final Set<String> paramDelim = options.contains(TSQLParseOption.spoUseMacro)
? {macroChar}
: {':', "?"};
// characters that may not appear in a parameter name (SQLDelimiterCharacters + extra symbols)
const extraDelims = {
'=',
"+",
"-",
"*",
"\\",
"/",
"[",
"]",
"|",
"<",
">"
};
while (true) {
while (skipComments(sql, p, escapeSlash, escapeRepeat)) {}
if (p.value < sql.length && paramDelim.contains(sql[p.value])) {
// parameter
var ignorePart = false;
int paramNameStart;
String paramName;
if (sql[p.value] != '?') {
// find parameter name
p.value++;
if (p.value < sql.length &&
(sql[p.value] == ':' ||
sql[p.value] == '=' ||
sql[p.value] == ' ')) {
// ignore ::, since some databases (postgres) uses this as a
// cast (wb 4813) (original comment kept as-is)
ignorePart = true;
p.value++;
paramNameStart = p.value;
paramName = '';
} else if (p.value < sql.length && sql[p.value] == '"') {
// Check if the parameter-name is between quotes
paramNameStart = p.value;
skipQuotesString(sql, p, '"', escapeSlash, escapeRepeat);
// Do not include the quotes in ParamName, but they must be
// included when the parameter is replaced by some
// place-holder. (original comment kept as-is)
paramName = sql.substring(paramNameStart + 1, p.value - 1);
} else {
paramNameStart = p.value;
while (p.value < sql.length &&
!sqlDelimiterCharacters.contains(sql[p.value]) &&
!extraDelims.contains(sql[p.value])) {
p.value++;
}
paramName = sql.substring(paramNameStart, p.value);
}
} else {
p.value++;
paramNameStart = p.value;
paramName = '';
}
if (!ignorePart) {
paramCount++;
int parameterIndex;
if (options.contains(TSQLParseOption.spoCreate)) {
// Check if this is the first occurance of the parameter.
// If so, create the parameter and assign the Parameterindex
final tmpParam = findParam(paramName);
if (tmpParam == null) {
parameterIndex = createParam(
TFieldType.ftUnknown, paramName, TParamType.ptInput)
.index;
} else {
// else only assign the ParameterIndex
parameterIndex = tmpParam.index;
}
} else {
// else find ParameterIndex
if (paramName != '') {
parameterIndex = paramByName(paramName).index;
} else {
parameterIndex = questionMarkParamCount;
questionMarkParamCount++;
}
}
// store ParameterIndex, ParamPart data
// ParamPart.Start includes the leading ':' or '?' character (1-based→0-based)
paramBinding.add(parameterIndex);
paramPartStart.add(paramNameStart > 0 ? paramNameStart - 1 : 0);
paramPartStop.add(p.value);
}
} else if (p.value >= sql.length) {
break; // end of SQL
} else {
p.value++;
}
}
if (paramCount > 0) {
// replace :ParamName by ? for interbase and by $x for
// postgresql/psSimulated (original comment kept as-is)
final newQuery = StringBuffer();
var bufIndex = 0;
for (var i = 0; i < paramPartStart.length; i++) {
newQuery.write(sql.substring(bufIndex, paramPartStart[i]));
switch (parameterStyle) {
case TParamStyle.psInterbase:
newQuery.write("?");
break;
case TParamStyle.psPostgreSQL:
case TParamStyle.psSimulated:
newQuery.write(replaceString.value);
newQuery.write("${paramBinding[i] + 1}");
break;
}
bufIndex = paramPartStop[i];
}
if (bufIndex < sql.length) {
newQuery.write(sql.substring(bufIndex));
}
return newQuery.toString();
}
return sql;
}