package org.mrcsparker.ceeql.jdbi;
import org.skife.jdbi.org.antlr.runtime.ANTLRStringStream;
import org.skife.jdbi.org.antlr.runtime.Token;
import org.skife.jdbi.rewriter.colon.ColonStatementLexer;
import org.skife.jdbi.v2.Binding;
import org.skife.jdbi.v2.StatementContext;
import org.skife.jdbi.v2.exceptions.UnableToCreateStatementException;
import org.skife.jdbi.v2.exceptions.UnableToExecuteStatementException;
import org.skife.jdbi.v2.tweak.Argument;
import org.skife.jdbi.v2.tweak.RewrittenStatement;
import org.skife.jdbi.v2.tweak.StatementRewriter;
import com.github.jknack.handlebars.Context;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.WeakHashMap;
import static org.skife.jdbi.rewriter.colon.ColonStatementLexer.DOUBLE_QUOTED_TEXT;
import static org.skife.jdbi.rewriter.colon.ColonStatementLexer.ESCAPED_TEXT;
import static org.skife.jdbi.rewriter.colon.ColonStatementLexer.LITERAL;
import static org.skife.jdbi.rewriter.colon.ColonStatementLexer.NAMED_PARAM;
import static org.skife.jdbi.rewriter.colon.ColonStatementLexer.POSITIONAL_PARAM;
import static org.skife.jdbi.rewriter.colon.ColonStatementLexer.QUOTED_TEXT;
/**
* Based on jdbi StatementRewriter to replace named parameters
*/
public class NamedParameterRewriter
{
public static class NameList {
private List<String> in = new ArrayList<String>();
private List<String> out = new ArrayList<String>();
public NameList() {}
public NameList(String[] names) {
in.addAll(Arrays.asList(names));
}
public String getName() {
String name = null;
if (in != null && !in.isEmpty()) {
name = in.remove(0);
} else {
name = next();
if (out != null) out.add(name);
}
return name;
}
protected String next() {
return "s"+UUID.randomUUID().toString().replace("-", "");
}
public void rewind() {
in.addAll(out);
}
public void reset() {
out.clear();
}
}
public static ParsedStatement parseString(final String sql, Map<String, String> parameters, NameList names, Context itCtx) throws IllegalArgumentException
{
ParsedStatement stmt = new ParsedStatement();
StringBuilder b = new StringBuilder(sql.length());
ColonStatementLexer lexer = new ColonStatementLexer(new ANTLRStringStream(sql));
Token t = lexer.nextToken();
while (t.getType() != ColonStatementLexer.EOF) {
switch (t.getType()) {
case LITERAL:
b.append(t.getText());
break;
case NAMED_PARAM:
String name = t.getText().substring(1, t.getText().length());
if (!parameters.containsKey(name)) {
Object value = itCtx.get(name);
name = names.getName();
parameters.put(name, value.toString());
}
b.append(":"+name);
stmt.addNamedParamAt(name);
//b.append("?");
break;
case QUOTED_TEXT:
b.append(t.getText());
break;
case DOUBLE_QUOTED_TEXT:
b.append(t.getText());
break;
case POSITIONAL_PARAM:
b.append("?");
stmt.addPositionalParamAt();
break;
case ESCAPED_TEXT:
//b.append(t.getText().substring(1)); //TODO: test needed
b.append(t.getText());
break;
default:
break;
}
t = lexer.nextToken();
}
stmt.sql = b.toString();
return stmt;
}
static public class ParsedStatement
{
private String sql;
private boolean positionalOnly = true;
public List<String> params = new ArrayList<String>();
public void addNamedParamAt(String name)
{
positionalOnly = false;
params.add(name);
}
public void addPositionalParamAt()
{
params.add("*");
}
public String getParsedSql()
{
return sql;
}
}
}