package center.db;
import ru.vassaev.core.exception.SysException;
import java.sql.SQLException;
import ru.vassaev.core.util.Strings;
import ru.vassaev.core.db.Manager;
import ru.vassaev.core.db.Types;
import ru.vassaev.core.db.RsField;
import ru.vassaev.core.db.RsParam;
import java.sql.PreparedStatement;
import java.util.ArrayList;
import java.util.Map;
import java.util.TreeMap;
import java.util.Iterator;
import java.sql.Connection;
/**
* Класс Statement.
* Правила использования:
* 1. new Statement(con)
* 2. выполнить prepare для запроса с параметрами, предварённые "::"
* 3. установить все параметры
* 4. получить PreparedStatement с помощью getStatement()
* 5. выполнить PreparedStatement
* 6. сбросить все параметры с помощью clearParams()
* 7. --- Вернуться к пункту 3, если необходимо
* 8. выполнить close()
* @author Vassaev A.V.
* @version 1.0
*/
public class Statement {
protected Connection con;
protected Types tp = null;
protected String idf = "::";
public Statement(Connection con) {
this.con = con;
tp = Manager.getTypes(con);
}
public Statement(Connection con, String idf) {
this.con = con;
if ((idf != null) && (idf.length() > 0)) {
this.idf = idf;
}
tp = Manager.getTypes(con);
}
protected class ParamInfo {
public RsParam prm = null;
public String NAME = null;
public ArrayList<Integer> links = new ArrayList<Integer>();
public Object lastValue = null;
}
protected RsField[] flds = null;
protected RsParam[] prms = null;
// Список параметров
protected ArrayList<ParamInfo> prmsi = new ArrayList<ParamInfo>();
protected String sql = null;
protected PreparedStatement st = null;
// Список параметров по именам
protected Map<String, ParamInfo> prmsh = new TreeMap<String, ParamInfo>();
private boolean isClose = true;
public synchronized void prepare(String query)
throws SysException {
if (!isClose) {
throw new SysException("The statement is not closed");
}
int i = 0;
int l = query.length();
StringBuffer sql = new StringBuffer();
int c = 0;
int len = 0;
while (i < l) {
int j = query.indexOf(idf, i);
if (j >= 0) {
sql.append(query.substring(i, j));
i = j + idf.length();
len = Strings.chooseIdentifier(query, i);
if (len > 0) {
i += len;
String name = query.substring(i - len, i);
ParamInfo pi = prmsh.get(name);
if (pi == null) {
pi = new ParamInfo();
pi.NAME = name;
prmsh.put(name, pi);
}
c++;
pi.links.add(new Integer(c));
prmsi.add(pi);
sql.append('?');
} else {
sql.append(idf);
}
} else {
sql.append(query.substring(i));
i = l;
}
}
this.sql = sql.toString();
try {
st = con.prepareStatement(this.sql);
} catch (SQLException ex1) {
throw new SysException(ex1);
}
try {
prms = tp.getParams(st);
} catch (Throwable ex) {
prms = new RsParam[prmsi.size()];
}
isClose = false;
}
public String getQueryText() {
return sql;
}
public PreparedStatement getStatement() {
return st;
}
public boolean isParamExist(String name) {
return (prmsh.get(name) != null);
}
public ArrayList<String> getParamNames() {
Iterator<String> enm = prmsh.keySet().iterator();
ArrayList<String> r = new ArrayList<String>();
while(enm.hasNext())
r.add(enm.next());
return r;
}
public void setParam(String name, Object value, int type)
throws SysException, SQLException {
ParamInfo pi = (ParamInfo) prmsh.get(name);
if (pi == null)
return;
for (int i = pi.links.size() - 1; i >= 0; i--) {
int j = pi.links.get(i).intValue();
if (value == null) {
st.setNull(j, (pi.prm == null) ? type : pi.prm.TYPE);
} else {
st.setObject(j, value);
}
}
pi.lastValue = value;
}
public Object getParam(String name) throws SysException {
ParamInfo pi = (ParamInfo) prmsh.get(name);
if (pi == null)
return null;
return pi.lastValue;
}
public Types getTypes() {
return tp;
}
public void clearParams() throws SysException {
try {
st.clearBatch();
st.clearWarnings();
st.clearParameters();
} catch (SQLException ex) {
throw new SysException(ex);
}
}
public void close() throws SysException {
try {
st.close();
} catch (SQLException ex) {
throw new SysException(ex);
}
isClose = true;
}
}