You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
gnosygnu_xowa/140_dbs/src/gplx/dbs/qrys/Db_stmt_sql.java

192 lines
10 KiB

/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012 gnosygnu@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.dbs.qrys; import gplx.*; import gplx.dbs.*;
import gplx.core.brys.fmtrs.*; import gplx.core.stores.*;
import gplx.dbs.engines.*;
public class Db_stmt_sql implements Db_stmt {// used for formatting SQL statements; not used for actual insert into database
private static final String Key_na = ""; // key is not_available; only called by procs with signature of Val(<type> v);
private final List_adp args = List_adp_.new_();
private final Bry_bfr tmp_bfr = Bry_bfr.new_();
private final Bry_fmtr tmp_fmtr = Bry_fmtr.new_();
public void Ctor_stmt(Db_engine engine, Db_qry qry) {}
public Db_conn Conn() {return conn;} public void Conn_(Db_conn v) {this.conn = v;} Db_conn conn;
public Db_stmt Reset_stmt() {return this;}
public Db_stmt Crt_bool_as_byte(String k, boolean v) {return Add_byte_by_bool(Bool_.Y, k, v);}
public Db_stmt Val_bool_as_byte(String k, boolean v) {return Add_byte_by_bool(Bool_.N, k, v);}
public Db_stmt Val_bool_as_byte(boolean v) {return Add_byte_by_bool(Bool_.N, Key_na, v);}
private Db_stmt Add_byte_by_bool(boolean where, String k, boolean v) {return Add_byte(where, k, v ? Bool_.Y_byte : Bool_.N_byte);}
public Db_stmt Crt_byte(String k, byte v) {return Add_byte(Bool_.Y, k, v);}
public Db_stmt Val_byte(String k, byte v) {return Add_byte(Bool_.N, k, v);}
public Db_stmt Val_byte(byte v) {return Add_byte(Bool_.N, Key_na, v);}
private Db_stmt Add_byte(boolean where, String k, byte v) {
try {Add(k, Byte_.To_str(v));} catch (Exception e) {throw Err_.new_exc(e, "db", "failed to add value", "type", "byte", "val", v);}
return this;
}
public Db_stmt Crt_int(String k, int v) {return Add_int(Bool_.Y, k, v);}
public Db_stmt Val_int_by_bool(String k, boolean v) {return Add_int(Bool_.N, k, v ? 1 : 0);}
public Db_stmt Val_int(String k, int v) {return Add_int(Bool_.N, k, v);}
public Db_stmt Val_int(int v) {return Add_int(Bool_.N, Key_na, v);}
private Db_stmt Add_int(boolean where, String k, int v) {
try {Add(k, Int_.To_str(v));} catch (Exception e) {throw Err_.new_exc(e, "db", "failed to add value", "type", "int", "val", v);}
return this;
}
public Db_stmt Crt_long(String k, long v) {return Add_long(Bool_.Y, k, v);}
public Db_stmt Val_long(String k, long v) {return Add_long(Bool_.N, k, v);}
public Db_stmt Val_long(long v) {return Add_long(Bool_.N, Key_na, v);}
private Db_stmt Add_long(boolean where, String k, long v) {
try {Add(k, Long_.To_str(v));} catch (Exception e) {throw Err_.new_exc(e, "db", "failed to add value", "type", "long", "val", v);}
return this;
}
public Db_stmt Crt_float(String k, float v) {return Add_float(Bool_.Y, k, v);}
public Db_stmt Val_float(String k, float v) {return Add_float(Bool_.N, k, v);}
public Db_stmt Val_float(float v) {return Add_float(Bool_.N, Key_na, v);}
private Db_stmt Add_float(boolean where, String k, float v) {
try {Add(k, Float_.To_str(v));} catch (Exception e) {throw Err_.new_exc(e, "db", "failed to add value", "type", "float", "val", v);}
return this;
}
public Db_stmt Crt_double(String k, double v) {return Add_double(Bool_.Y, k, v);}
public Db_stmt Val_double(String k, double v) {return Add_double(Bool_.N, k, v);}
public Db_stmt Val_double(double v) {return Add_double(Bool_.N, Key_na, v);}
private Db_stmt Add_double(boolean where, String k, double v) {
try {Add(k, Double_.To_str(v));} catch (Exception e) {throw Err_.new_exc(e, "db", "failed to add value", "type", "double", "val", v);}
return this;
}
public Db_stmt Crt_decimal(String k, Decimal_adp v) {return Add_decimal(Bool_.Y, k, v);}
public Db_stmt Val_decimal(String k, Decimal_adp v) {return Add_decimal(Bool_.N, k, v);}
public Db_stmt Val_decimal(Decimal_adp v) {return Add_decimal(Bool_.N, Key_na, v);}
private Db_stmt Add_decimal(boolean where, String k, Decimal_adp v) {
try {Add(k, v.To_str());} catch (Exception e) {throw Err_.new_exc(e, "db", "failed to add value", "type", "decimal", "val", v);}
return this;
}
public Db_stmt Crt_bry(String k, byte[] v) {return Add_bry(Bool_.Y, k, v);}
public Db_stmt Val_bry(String k, byte[] v) {return Add_bry(Bool_.N, k, v);}
public Db_stmt Val_bry(byte[] v) {return Add_bry(Bool_.N, Key_na, v);}
private Db_stmt Add_bry(boolean where, String k, byte[] v) {// HACK: convert to String b/c tdb does not support byte[]
try {Add(k, Val_str_wrap(String_.new_u8(v)));} catch (Exception e) {throw Err_.new_exc(e, "db", "failed to add value", "type", "byte[]", "val", v.length);}
return this;
}
public Db_stmt Crt_bry_as_str(String k, byte[] v) {return Add_bry_as_str(Bool_.Y, k, v);}
public Db_stmt Val_bry_as_str(String k, byte[] v) {return Add_bry_as_str(Bool_.N, k, v);}
public Db_stmt Val_bry_as_str(byte[] v) {return Add_bry_as_str(Bool_.N, Key_na, v);}
private Db_stmt Add_bry_as_str(boolean where, String k, byte[] v) {return Add_str(where, k, String_.new_u8(v));}
public Db_stmt Crt_str(String k, String v) {return Add_str(Bool_.Y, k, v);}
public Db_stmt Val_str(String k, String v) {return Add_str(Bool_.N, k, v);}
public Db_stmt Val_str(String v) {return Add_str(Bool_.N, Key_na, v);}
private Db_stmt Add_str(boolean where, String k, String v) {
try {Add(k, Val_str_wrap(v));} catch (Exception e) {throw Err_.new_exc(e, "db", "failed to add value", "type", "String", "val", v);}
return this;
}
public Db_stmt Crt_date(String k, DateAdp v) {return Add_date(Bool_.Y, k, v);}
public Db_stmt Val_date(String k, DateAdp v) {return Add_date(Bool_.N, k, v);}
private Db_stmt Add_date(boolean where, String k, DateAdp v) {
try {Add(k, Val_str_wrap(v.XtoStr_fmt_iso_8561()));} catch (Exception e) {throw Err_.new_exc(e, "db", "failed to add value", "type", "date", "val", v);}
return this;
}
public Db_stmt Crt_text(String k, String v) {return Add_text(Bool_.Y, k, v);}
public Db_stmt Val_text(String k, String v) {return Add_text(Bool_.N, k, v);}
private Db_stmt Add_text(boolean where, String k, String v) {
try {Add(k, Val_str_wrap(v));} catch (Exception e) {throw Err_.new_exc(e, "db", "failed to add value", "type", "text", "val", v);}
return this;
}
public Db_stmt Val_rdr_(gplx.core.ios.Io_stream_rdr v, long rdr_len) {
try {
Bry_bfr bfr = Bry_bfr.new_();
gplx.core.ios.Io_stream_rdr_.Load_all_to_bfr(bfr, v);
Add(Key_na, bfr.To_str_and_clear());
} catch (Exception e) {throw Err_.new_exc(e, "db", "failed to add value", "type", "rdr", "val", v);}
return this;
}
private String Val_str_wrap(String v) {
return "'" + String_.Replace(v, "'", "\\'") + "'";
}
public boolean Exec_insert() {
try {boolean rv = conn.Exec_qry(Db_qry_sql.dml_(this.Xto_sql())) != 0; return rv;} catch (Exception e) {throw Err_.new_exc(e, "db", "failed to exec prepared statement", "sql", sql_orig);}
}
public int Exec_update() {
try {int rv = conn.Exec_qry(Db_qry_sql.dml_(this.Xto_sql())); return rv;} catch (Exception e) {throw Err_.new_exc(e, "db", "failed to exec prepared statement", "sql", sql_orig);}
}
public int Exec_delete() {
try {int rv = conn.Exec_qry(Db_qry_sql.dml_(this.Xto_sql())); return rv;} catch (Exception e) {throw Err_.new_exc(e, "db", "failed to exec prepared statement", "sql", sql_orig);}
}
public DataRdr Exec_select() {
try {DataRdr rv = conn.Exec_qry_as_old_rdr(Db_qry_sql.rdr_(this.Xto_sql())); return rv;} catch (Exception e) {throw Err_.new_exc(e, "db", "failed to exec prepared statement", "sql", sql_orig);}
}
public Db_rdr Exec_select__rls_auto() {return Db_rdr_.Empty;}
public Db_rdr Exec_select__rls_manual() {return Db_rdr_.Empty;}
public Object Exec_select_val() {
try {Object rv = DataRdr_.Read_1st_row_and_1st_fld(this.Exec_select()); return rv;} catch (Exception e) {throw Err_.new_exc(e, "db", "failed to exec prepared statement", "sql", sql_orig);}
}
public Db_stmt Clear() {
args.Clear();
return this;
}
public void Rls() {this.Clear();}
public void Add(String k, String v) {
if (k == Dbmeta_fld_itm.Key_null) return; // key is explicitly null; ignore; allows version_2+ type definitions
args.Add(v);
}
public String Xto_sql() {
tmp_fmtr.Bld_bfr_many(tmp_bfr, (Object[])args.To_ary_and_clear(Object.class));
return tmp_bfr.To_str_and_clear();
}
public int Args_len() {return args.Count();}
public String Args_get_at(int i) {return (String)args.Get_at(i);}
private String sql_orig;
public Db_qry Qry() {return qry;} private Db_qry qry;
public Db_stmt Parse(Db_qry qry, String sql_str) {
this.qry = qry;
this.sql_orig = sql_str;
Init_fmtr(tmp_bfr, tmp_fmtr, sql_str);
return this;
}
private static void Init_fmtr(Bry_bfr tmp_bfr, Bry_fmtr tmp_fmtr, String sql_str) {
byte[] sql_bry = Bry_.new_u8(sql_str);
int arg_idx = 0; int pos_prv = 0;
tmp_bfr.Clear();
while (true) {
int pos_cur = Bry_find_.Find_fwd(sql_bry, Byte_ascii.Question, pos_prv); if (pos_cur == Bry_find_.Not_found) break;
tmp_bfr.Add_mid(sql_bry, pos_prv, pos_cur);
tmp_bfr.Add_byte(Byte_ascii.Tilde).Add_byte(Byte_ascii.Curly_bgn);
tmp_bfr.Add_int_variable(arg_idx++);
tmp_bfr.Add_byte(Byte_ascii.Curly_end);
pos_prv = pos_cur + 1;
}
tmp_bfr.Add_mid(sql_bry, pos_prv, sql_bry.length);
tmp_fmtr.Fmt_(tmp_bfr.To_bry_and_clear());
}
public static String Xto_str(Bry_bfr tmp_bfr, Bry_fmtr tmp_fmtr, String sql_str, List_adp args) {
Init_fmtr(tmp_bfr, tmp_fmtr, sql_str);
Object[] ary = args.To_obj_ary();
int len = ary.length;
for (int i = 0; i < len; ++i) {
Object obj = ary[i];
String str = "";
if (obj == null)
str = "NULL";
else {
str = Object_.Xto_str_strict_or_null(obj);
if (Type_adp_.Eq(obj.getClass(), String_.Cls_ref_type))
str = "'" + String_.Replace(str, "'", "''") + "'";
}
ary[i] = str;
}
tmp_fmtr.Bld_bfr_many(tmp_bfr, ary);
return tmp_bfr.To_str_and_clear();
}
}