1
0
mirror of https://github.com/gnosygnu/xowa.git synced 2026-03-02 03:49:30 +00:00
This commit is contained in:
gnosygnu
2015-07-12 21:10:02 -04:00
commit 794b5a232f
3099 changed files with 238212 additions and 0 deletions

View File

@@ -0,0 +1,43 @@
/*
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.engines; import gplx.*; import gplx.dbs.*;
public interface Db_engine {
String Tid();
Db_conn_info Conn_info();
Db_engine New_clone(Db_conn_info url);
Db_rdr New_rdr__rls_manual (Object rdr_obj, String sql); // Object o:ResultSet if desktop; Cursor if android
Db_rdr New_rdr__rls_auto (Db_stmt stmt, Object rdr_obj, String sql); // Object o:ResultSet if desktop; Cursor if android
Db_stmt New_stmt_prep(Db_qry qry);
Object New_stmt_prep_as_obj(String sql);
DataRdr New_rdr(java.sql.ResultSet rdr, String sql);
void Txn_bgn(String name);
void Txn_end();
void Txn_cxl();
void Txn_sav();
void Conn_open();
void Conn_term();
Object Exec_as_obj(Db_qry qry);
void Ddl_create_tbl(Db_meta_tbl meta);
void Ddl_create_idx(Gfo_usr_dlg usr_dlg, Db_meta_idx... ary);
void Ddl_append_fld(String tbl, Db_meta_fld fld);
void Ddl_delete_tbl(String tbl);
void Env_db_attach(String alias, Io_url db_url);
void Env_db_detach(String alias);
boolean Meta_tbl_exists(String tbl);
boolean Meta_fld_exists(String tbl, String fld);
}

View File

@@ -0,0 +1,109 @@
/*
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.engines; import gplx.*; import gplx.dbs.*;
import java.sql.*;
import gplx.dbs.engines.*; import gplx.dbs.qrys.*; import gplx.dbs.sqls.*;
public abstract class Db_engine_sql_base implements Db_engine {
@gplx.Internal protected void Ctor(Db_conn_info conn_info) {this.conn_info = conn_info;}
public abstract String Tid();
public Db_conn_info Conn_info() {return conn_info;} protected Db_conn_info conn_info;
public abstract Db_engine New_clone(Db_conn_info conn_info);
public Db_rdr New_rdr__rls_manual(Object rdr_obj, String sql) {return New_rdr(null, rdr_obj, sql);}
public Db_rdr New_rdr__rls_auto(Db_stmt stmt, Object rdr_obj, String sql) {return New_rdr(stmt, rdr_obj, sql);}
@gplx.Virtual public Db_rdr New_rdr_clone() {return new Db_rdr__basic();}
public Db_stmt New_stmt_prep(Db_qry qry) {return new Db_stmt_cmd(this, qry);}
@gplx.Virtual public void Txn_bgn(String name) {Exec_as_obj(Db_qry_sql.xtn_("BEGIN TRANSACTION;"));}
@gplx.Virtual public void Txn_end() {Exec_as_obj(Db_qry_sql.xtn_("COMMIT TRANSACTION;"));}
@gplx.Virtual public void Txn_cxl() {Exec_as_obj(Db_qry_sql.xtn_("ROLLBACK TRANSACTION;"));}
@gplx.Virtual public void Txn_sav() {this.Txn_end(); this.Txn_bgn("");}
public Object Exec_as_obj(Db_qry qry) {
if (qry.Tid() == Db_qry_.Tid_flush) return null; // ignore flush (delete-db) statements
String sql = this.SqlWtr().Xto_str(qry, false); // DBG: Tfds.Write(sql);
return qry.Exec_is_rdr() ? (Object)this.Exec_as_rdr(sql) : this.Exec_as_int(sql);
}
protected int Exec_as_int(String sql) {
try {
Statement cmd = New_stmt_exec(sql);
return cmd.executeUpdate(sql);
}
catch (Exception e) {throw Exc_.new_exc(e, "db", "db.engine:exec failed", "url", conn_info.Xto_api(), "sql", sql);}
}
private DataRdr Exec_as_rdr(String sql) {
try {
Statement cmd = New_stmt_exec(sql);
cmd.execute(sql);
ResultSet rdr = cmd.getResultSet();
return New_rdr(rdr, sql);
}
catch (Exception e) {throw Exc_.new_exc(e, "db", "db.engine:rdr failed", "url", conn_info.Xto_api(), "sql", sql);}
}
public void Ddl_create_tbl(Db_meta_tbl tbl) {Exec_as_int(tbl.To_sql_create());}
public void Ddl_create_idx(Gfo_usr_dlg usr_dlg, Db_meta_idx... ary) {
int len = ary.length;
for (int i = 0; i < len; ++i) {
Db_meta_idx idx = ary[i];
usr_dlg.Plog_many("", "", "creating database index (please wait); db=~{0} idx=~{1}", conn_info.Database(), idx.Name());
Exec_as_int(idx.To_sql_create());
}
}
public void Ddl_append_fld(String tbl, Db_meta_fld fld) {
Gfo_usr_dlg_.I.Plog_many("", "", "adding column to table: db=~{0} tbl=~{1} fld=~{2}", conn_info.Database(), tbl, fld.Name());
try {
Exec_as_int(Db_sqlbldr__sqlite.I.Bld_alter_tbl_add(tbl, fld));
Gfo_usr_dlg_.I.Plog_many("", "", "column added to table: db=~{0} tbl=~{1} fld=~{2}", conn_info.Database(), tbl, fld.Name());
}
catch (Exception e) { // catch error if column already added to table
Gfo_usr_dlg_.I.Warn_many("", "", "column not added to table: db=~{0} tbl=~{1} fld=~{2} err=~{3}", conn_info.Database(), tbl, fld.Name(), Err_.Message_gplx(e));
}
}
public void Ddl_delete_tbl(String tbl) {Exec_as_int(Db_sqlbldr__sqlite.I.Bld_drop_tbl(tbl));}
@gplx.Virtual public void Env_db_attach(String alias, Io_url db_url) {}
@gplx.Virtual public void Env_db_detach(String alias) {}
@gplx.Virtual public boolean Meta_tbl_exists(String tbl) {return false;}
@gplx.Virtual public boolean Meta_fld_exists(String tbl, String fld) {return false;}
@gplx.Virtual public DataRdr New_rdr(ResultSet rdr, String sql) {return gplx.stores.Db_data_rdr_.new_(rdr, sql);}
@gplx.Virtual public Sql_qry_wtr SqlWtr() {return Sql_qry_wtr_.new_ansi();}
private Db_rdr New_rdr(Db_stmt stmt, Object rdr, String sql) {
Db_rdr__basic rv = (Db_rdr__basic)New_rdr_clone();
rv.Ctor(stmt, (ResultSet)rdr, sql);
return rv;
}
@gplx.Internal protected abstract Connection Conn_new();
protected Connection connection;
public void Conn_open() {connection = Conn_new();}
public void Conn_term() {
if (connection == null) return; // connection never opened; just exit
try {connection.close();}
catch (Exception e) {throw Exc_.new_exc(e, "db", "Conn_term failed", "url", conn_info.Xto_raw());}
connection = null;
}
public Object New_stmt_prep_as_obj(String sql) {
if (connection == null) connection = Conn_new(); // auto-open connection
try {return connection.prepareStatement(sql);}
catch (Exception e) {throw Exc_.new_exc(e, "db", "New_stmt_prep failed", "sql", sql);}
}
private Statement New_stmt_exec(String sql) {
if (connection == null) connection = Conn_new(); // auto-open connection
try {return connection.createStatement();}
catch (Exception e) {throw Exc_.new_exc(e, "db", "New_stmt_exec failed", "sql", sql);}
}
protected Connection Conn_make_by_url(String url, String uid, String pwd) {
try {return DriverManager.getConnection(url, uid, pwd);}
catch (SQLException e) {throw Exc_.new_exc(e, "db", "connection open failed", "info", Conn_info().Xto_raw());}
}
}

View File

@@ -0,0 +1,33 @@
/*
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.engines.mems; import gplx.*; import gplx.dbs.*; import gplx.dbs.engines.*;
public class Db_conn_info__mem extends Db_conn_info__base {
@Override public String Tid() {return Tid_const;} public static final String Tid_const = "mem";
@Override public Db_conn_info New_self(String raw, GfoMsg m) {
Db_conn_info__mem rv = new Db_conn_info__mem();
rv.Ctor("", m.ReadStr("database"), raw, raw);
return rv;
}
public static Db_conn_info new_(String database) {
return Db_conn_info_.parse_(Bld_raw
( "gplx_key", Tid_const
, "database", database
));
}
public static final Db_conn_info__mem I = new Db_conn_info__mem(); Db_conn_info__mem() {}
}

View File

@@ -0,0 +1,56 @@
/*
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.engines.mems; import gplx.*; import gplx.dbs.*; import gplx.dbs.engines.*;
public class Db_engine__mem implements Db_engine {
private final Hash_adp tbl_hash = Hash_adp_.new_();
Db_engine__mem(Db_conn_info conn_info) {this.conn_info = conn_info;}
public String Tid() {return Db_conn_info__mem.Tid_const;}
public Db_conn_info Conn_info() {return conn_info;} private Db_conn_info conn_info;
public Db_engine New_clone(Db_conn_info conn_info) {return new Db_engine__mem(conn_info);}
public Db_stmt New_stmt_prep(Db_qry qry) {return new Db_stmt__mem(this, qry);}
public Mem_tbl Tbls_get(String name) {return (Mem_tbl)tbl_hash.Get_by(name);}
public void Txn_bgn(String name) {++txn_count;} private int txn_count = 0;
public void Txn_end() {--txn_count;}
public void Txn_cxl() {--txn_count;}
public void Txn_sav() {this.Txn_end(); this.Txn_bgn("");}
public Object Exec_as_obj(Db_qry qry) {throw Exc_.new_unimplemented();}
public void Conn_open() {}
public void Conn_term() {
if (txn_count != 0) throw Exc_.new_("Conn_term.txns still open", "txn_count", txn_count);
}
public Db_rdr New_rdr__rls_manual(Object rdr_obj, String sql) {throw Exc_.new_unimplemented();}
public Db_rdr New_rdr__rls_auto(Db_stmt stmt, Object rdr_obj, String sql) {throw Exc_.new_unimplemented();}
public DataRdr New_rdr(java.sql.ResultSet rdr, String sql) {throw Exc_.new_unimplemented();}
public Object New_stmt_prep_as_obj(String sql) {throw Exc_.new_unimplemented();}
public void Ddl_create_tbl(Db_meta_tbl meta) {
Mem_tbl mem_tbl = new Mem_tbl(meta);
tbl_hash.Add_if_dupe_use_nth(meta.Name(), mem_tbl);
}
public void Ddl_create_idx(Gfo_usr_dlg usr_dlg, Db_meta_idx... ary) {} // TODO: implement unique index
public void Ddl_append_fld(String tbl, Db_meta_fld fld) {}
public void Ddl_delete_tbl(String tbl) {}
public void Env_db_attach(String alias, Io_url db_url) {}
public void Env_db_detach(String alias) {}
public boolean Meta_tbl_exists(String tbl) {return tbl_hash.Has(tbl);}
public boolean Meta_fld_exists(String tbl, String fld) {
Mem_tbl mem_tbl = (Mem_tbl)tbl_hash.Get_by(tbl); if (mem_tbl == null) return false;
return mem_tbl.Meta().Flds_has(fld);
}
// public boolean Meta_fld_exists(String name) {return tbl_hash.Has(name);}
public static final Db_engine__mem _ = new Db_engine__mem(); Db_engine__mem() {}
}

View File

@@ -0,0 +1,44 @@
/*
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.engines.mems; import gplx.*; import gplx.dbs.*; import gplx.dbs.engines.*;
public class Db_rdr__mem implements Db_rdr {
private final Mem_row[] rows; private int row_idx = -1; private final int rows_len;
private Mem_row row;
public Db_rdr__mem(String[] cols, Mem_row[] rows) {
this.rows = rows; this.rows_len = rows.length;
}
public boolean Move_next() {
boolean rv = ++row_idx < rows_len;
if (rv)
row = rows[row_idx];
return rv;
}
public byte[] Read_bry(String k) {return (byte[])row.Get_by(k);}
public String Read_str(String k) {return (String)row.Get_by(k);}
public byte[] Read_bry_by_str(String k) {return Bry_.new_u8_safe((String)row.Get_by(k));} // NOTE: null b/c db can have NULL
@gplx.Virtual public void Save_bry_in_parts(Io_url url, String tbl, String fld, String crt_key, Object crt_val) {throw Exc_.new_unimplemented();}
public DateAdp Read_date_by_str(String k) {return DateAdp_.parse_iso8561((String)row.Get_by(k));}
public byte Read_byte(String k) {return Byte_.cast_(row.Get_by(k));}
public int Read_int(String k) {return Int_.cast_(row.Get_by(k));}
public long Read_long(String k) {return Long_.cast_(row.Get_by(k));}
public float Read_float(String k) {return Float_.cast_(row.Get_by(k));}
public double Read_double(String k) {return Double_.cast_(row.Get_by(k));}
public boolean Read_bool_by_byte(String k) {return Byte_.cast_(row.Get_by(k)) == 1;}
public Object Read_obj(String k) {return row.Get_by(k);}
public void Rls() {}
}

View File

@@ -0,0 +1,140 @@
/*
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.engines.mems; import gplx.*; import gplx.dbs.*; import gplx.dbs.engines.*;
public class Db_stmt__mem implements Db_stmt {
private static final String Key_na = ""; // key is not_available; only called by procs with signature of Val(<type> v);
private final Ordered_hash val_list = Ordered_hash_.new_();
public Db_stmt__mem(Db_engine__mem engine, Db_qry qry) {Ctor_stmt(engine, qry);} private Db_engine__mem engine;
public void Ctor_stmt(Db_engine engine, Db_qry qry) {this.engine = (Db_engine__mem)engine; this.qry = qry;}
public Hash_adp Crts() {return crt_hash;} private final Hash_adp crt_hash = Hash_adp_.new_();
public int Args_len() {return val_list.Count();}
public Object Args_get_at(int i) {return val_list.Get_at(i);}
public Object Args_get_by(String k) {return val_list.Get_by(k);}
public Db_qry Qry() {return qry;} private Db_qry qry;
public Db_stmt Reset_stmt() {return this;}
public Db_stmt Clear() {
val_list.Clear();
crt_hash.Clear();
return this;
}
public void Rls() {this.Clear();}
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, where, v);} catch (Exception e) {throw Exc_.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(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, where, v);} catch (Exception e) {throw Exc_.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, where, v);} catch (Exception e) {throw Exc_.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, where, v);} catch (Exception e) {throw Exc_.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, where, v);} catch (Exception e) {throw Exc_.new_exc(e, "db", "failed to add value", "type", "double", "val", v);}
return this;
}
public Db_stmt Crt_decimal(String k, DecimalAdp v) {return Add_decimal(Bool_.Y, k, v);}
public Db_stmt Val_decimal(String k, DecimalAdp v) {return Add_decimal(Bool_.N, k, v);}
public Db_stmt Val_decimal(DecimalAdp v) {return Add_decimal(Bool_.N, Key_na, v);}
private Db_stmt Add_decimal(boolean where, String k, DecimalAdp v) {
try {Add(k, where, v);} catch (Exception e) {throw Exc_.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) {
try {Add(k, where, v);} catch (Exception e) {throw Exc_.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, where, v);} catch (Exception e) {throw Exc_.new_exc(e, "db", "failed to add value", "type", "String", "val", v);}
return this;
}
public Db_stmt Val_rdr_(gplx.ios.Io_stream_rdr v, long rdr_len) {
try {
Bry_bfr bfr = Bry_bfr.new_();
gplx.ios.Io_stream_rdr_.Load_all_to_bfr(bfr, v);
Add("", Bool_.N, bfr.Xto_str_and_clear());
} catch (Exception e) {throw Exc_.new_exc(e, "db", "failed to add value", "type", "rdr", "val", v);}
return this;
}
public boolean Exec_insert() {
Mem_tbl tbl = engine.Tbls_get(qry.Base_table());
if (tbl == null) throw Exc_.new_("must call Create_tbl", "tbl", qry.Base_table());
return tbl.Insert(this) == 1;
}
public int Exec_update() {
Mem_tbl tbl = engine.Tbls_get(qry.Base_table());
return tbl.Update(this);
}
public int Exec_delete() {
Mem_tbl tbl = engine.Tbls_get(qry.Base_table());
return tbl.Delete(this);
}
public DataRdr Exec_select() {throw Exc_.new_unimplemented();}
public Db_rdr Exec_select__rls_auto() {return this.Exec_select__rls_manual();}
public Db_rdr Exec_select__rls_manual() {
Mem_tbl tbl = engine.Tbls_get(qry.Base_table());
return tbl.Select(this);
}
public Object Exec_select_val() {throw Exc_.new_unimplemented();}
private void Add(String k, boolean where, Object v) {
if (k == Db_meta_fld.Key_null) return; // key is explicitly null; ignore; allows schema_2+ type definitions
val_list.Add_if_dupe_use_1st(k, v); // NOTE: only add if new; WHERE with IN will call Add many times; fld_ttl IN ('A.png', 'B.png');
if (where) {
List_adp list = (List_adp)crt_hash.Get_by(k);
if (list == null) {
list = List_adp_.new_();
crt_hash.Add(k, list);
}
list.Add(v);
}
}
}

View File

@@ -0,0 +1,24 @@
/*
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.engines.mems; import gplx.*; import gplx.dbs.*; import gplx.dbs.engines.*;
public class Mem_qry_set {
private final List_adp rows = List_adp_.new_();
public int Len() {return rows.Count();}
public Mem_row Get_at(int i) {return (Mem_row)rows.Get_at(i);}
public void Add(Mem_row row) {rows.Add(row);}
}

View File

@@ -0,0 +1,30 @@
/*
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.engines.mems; import gplx.*; import gplx.dbs.*; import gplx.dbs.engines.*;
public class Mem_row implements GfoInvkAble {
private final Ordered_hash hash = Ordered_hash_.new_();
public Object Get_by(String key) {return hash.Get_by(key);}
public Object Get_at(int i) {return hash.Get_at(i);}
public void Set_by(String key, Object val) {hash.Add_if_dupe_use_nth(key, val);}
public void Add(String key, Object val) {hash.Add(key, val);}
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
Object rv = Get_by(k);
if (rv == null) return GfoInvkAble_.Rv_unhandled;
return rv;
}
}

View File

@@ -0,0 +1,95 @@
/*
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.engines.mems; import gplx.*; import gplx.dbs.*; import gplx.dbs.engines.*;
import gplx.core.primitives.*; import gplx.core.criterias.*; import gplx.dbs.qrys.*;
public class Mem_tbl {
private final List_adp rows = List_adp_.new_(); private final List_adp where_rows = List_adp_.new_();
private final Hash_adp autonum_hash = Hash_adp_.new_();
public Mem_tbl(Db_meta_tbl meta) {this.meta = meta;}
public Db_meta_tbl Meta() {return meta;} private final Db_meta_tbl meta;
public int Insert(Db_stmt__mem stmt) {
Mem_row itm = new Mem_row();
Db_meta_fld[] flds = meta.Flds();
int len = flds.length;
for (int i = 0; i < len; ++i) {
Db_meta_fld fld = flds[i];
String fld_name = fld.Name();
Object val = fld.Autonum() ? Autonum_calc(fld_name) : stmt.Args_get_by(fld_name);
itm.Set_by(fld_name, val);
}
rows.Add(itm);
return 1;
}
private int Autonum_calc(String name) {
Int_obj_ref autonum_itm = (Int_obj_ref)autonum_hash.Get_by(name);
if (autonum_itm == null) {
autonum_itm = Int_obj_ref.new_(0);
autonum_hash.Add(name, autonum_itm);
}
return autonum_itm.Val_add();
}
public int Update(Db_stmt__mem stmt) {
Db_qry_update qry = (Db_qry_update)stmt.Qry();
qry.Where().Val_from_args(stmt.Crts());
Select_rows_where(where_rows, stmt, qry.Where());
int where_rows_len = where_rows.Count();
String[] update_cols = qry.Cols_for_update(); int update_cols_len = update_cols.length;
for (int i = 0; i < where_rows_len; ++i) {
Mem_row itm = (Mem_row)where_rows.Get_at(i);
for (int j = 0; j < update_cols_len; ++j)
itm.Set_by(update_cols[j], stmt.Args_get_at(j));
}
return where_rows_len;
}
public int Delete(Db_stmt__mem stmt) {
Db_qry_delete qry = (Db_qry_delete)stmt.Qry();
qry.Where().Val_from_args(stmt.Crts());
Select_rows_where(where_rows, stmt, qry.Where());
int where_rows_len = where_rows.Count();
for (int i = 0; i < where_rows_len; ++i) {
Mem_row itm = (Mem_row)where_rows.Get_at(i);
rows.Del(itm);
}
return where_rows_len;
}
public Db_rdr Select(Db_stmt__mem stmt) {
String[] select = null; Criteria where = null;
Db_qry__select_in_tbl qry = Db_qry__select_in_tbl.as_(stmt.Qry());
if (qry == null) {
Db_qry__select_cmd qry2 = (Db_qry__select_cmd)stmt.Qry();
select = qry2.Cols_ary();
where = qry2.Where();
}
else {
select = qry.Select_flds();
where = qry.Where();
}
where.Val_from_args(stmt.Crts());
Select_rows_where(where_rows, stmt, where);
return new Db_rdr__mem(select, (Mem_row[])where_rows.To_ary_and_clear(Mem_row.class));
}
private void Select_rows_where(List_adp rv, Db_stmt__mem stmt, Criteria crt) {
rv.Clear();
int rows_len = rows.Count();
for (int i = 0; i < rows_len; ++i) {
Mem_row itm = (Mem_row)rows.Get_at(i);
if (crt.Matches(itm))
rv.Add(itm);
}
}
}

View File

@@ -0,0 +1,41 @@
/*
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.engines.mysql; import gplx.*; import gplx.dbs.*; import gplx.dbs.engines.*;
public class Mysql_conn_info extends Db_conn_info__base {
@Override public String Tid() {return Tid_const;} public static final String Tid_const = "mysql";
public String Uid() {return uid;} private String uid;
public String Pwd() {return pwd;} private String pwd;
public static Db_conn_info new_(String server, String database, String uid, String pwd) {
return Db_conn_info_.parse_(Bld_raw
( "gplx_key", Tid_const
, "server", server
, "database", database
, "uid", uid
, "pwd", pwd
, "charset", "utf8"
));
}
@Override public Db_conn_info New_self(String raw, GfoMsg m) {
Mysql_conn_info rv = new Mysql_conn_info();
rv.Ctor(m.ReadStr("server"), m.ReadStr("database"), raw, BldApi(m, KeyVal_.new_("charset", "utf8")));
rv.uid = m.ReadStr("uid");
rv.pwd = m.ReadStr("pwd");
return rv;
}
public static final Mysql_conn_info _ = new Mysql_conn_info(); Mysql_conn_info() {}
}

View File

@@ -0,0 +1,48 @@
/*
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.engines.mysql; import gplx.*; import gplx.dbs.*; import gplx.dbs.engines.*;
import gplx.stores.*; import gplx.dbs.engines.*; import gplx.dbs.sqls.*;
import java.sql.*;
public class Mysql_engine extends Db_engine_sql_base {
@Override public String Tid() {return Mysql_conn_info.Tid_const;}
@Override public Sql_qry_wtr SqlWtr() {return Sql_qry_wtr_.new_escape_backslash();}
@Override public Db_engine New_clone(Db_conn_info connectInfo) {
Mysql_engine rv = new Mysql_engine();
rv.Ctor(connectInfo);
return rv;
}
@Override public DataRdr New_rdr(ResultSet rdr, String commandText) {return Mysql_rdr.new_(rdr, commandText);}
@gplx.Internal @Override protected Connection Conn_new() {
Mysql_conn_info conn_info_as_mysql = (Mysql_conn_info)conn_info;
return Conn_make_by_url("jdbc:mysql://localhost/" + conn_info_as_mysql.Database() + "?characterEncoding=UTF8", conn_info_as_mysql.Uid(), conn_info_as_mysql.Pwd());
}
public static final Mysql_engine _ = new Mysql_engine(); Mysql_engine() {}
}
class Mysql_rdr extends Db_data_rdr {
//PATCH:MYSQL:byte actually returned as int by Jdbc ResultSet (or MYSQL impmentation); convert to byte
@Override public byte ReadByte(String key) {return ReadByteOr(key, Byte.MAX_VALUE);}
@Override public byte ReadByteOr(String key, byte or) {
Object val = Read(key);
return val == null ? or : ((Integer)val).byteValue();
}
public static Mysql_rdr new_(ResultSet rdr, String commandText) {
Mysql_rdr rv = new Mysql_rdr();
rv.ctor_db_data_rdr(rdr, commandText);
return rv;
} Mysql_rdr() {}
}

View File

@@ -0,0 +1,23 @@
/*
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.engines.nulls; import gplx.*; import gplx.dbs.*; import gplx.dbs.engines.*;
public class Noop_conn_info extends Db_conn_info__base {
@Override public String Tid() {return Tid_const;} public static final String Tid_const = "null_db";
@Override public Db_conn_info New_self(String raw, GfoMsg m) {return this;}
public static final Noop_conn_info I = new Noop_conn_info(); Noop_conn_info() {this.Ctor("", "", "gplx_key=null_db", "");}
}

View File

@@ -0,0 +1,44 @@
/*
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.engines.nulls; import gplx.*; import gplx.dbs.*; import gplx.dbs.engines.*;
public class Noop_engine implements Db_engine {
public String Tid() {return Noop_conn_info.Tid_const;}
public Db_conn_info Conn_info() {return Db_conn_info_.Null;}
public void Conn_open() {}
public void Conn_term() {}
public Db_engine New_clone(Db_conn_info url) {return this;}
public Db_rdr New_rdr__rls_manual (Object rdr_obj, String sql) {return Db_rdr_.Empty;}
public Db_rdr New_rdr__rls_auto (Db_stmt stmt, Object rdr_obj, String sql) {return Db_rdr_.Empty;}
public Db_stmt New_stmt_prep(Db_qry qry) {return Db_stmt_.Null;}
public Object New_stmt_prep_as_obj(String sql) {throw Exc_.new_unimplemented();}
public DataRdr New_rdr(java.sql.ResultSet rdr, String sql) {return DataRdr_.Null;}
public void Txn_bgn(String name) {}
public void Txn_end() {}
public void Txn_cxl() {}
public void Txn_sav() {}
public Object Exec_as_obj(Db_qry cmd) {return cmd.Exec_is_rdr() ? (Object)DataRdr_.Null : -1;}
public void Ddl_create_tbl(Db_meta_tbl meta) {}
public void Ddl_create_idx(Gfo_usr_dlg usr_dlg, Db_meta_idx... ary) {}
public void Ddl_append_fld(String tbl, Db_meta_fld fld) {}
public void Ddl_delete_tbl(String tbl) {}
public void Env_db_attach(String alias, Io_url db_url) {}
public void Env_db_detach(String alias) {}
public boolean Meta_tbl_exists(String tbl) {return false;}
public boolean Meta_fld_exists(String tbl, String fld) {return false;}
public static final Noop_engine _ = new Noop_engine(); Noop_engine() {}
}

View File

@@ -0,0 +1,42 @@
/*
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.engines.postgres; import gplx.*; import gplx.dbs.*; import gplx.dbs.engines.*;
public class Postgres_conn_info extends Db_conn_info__base {
@Override public String Tid() {return Tid_const;} public static final String Tid_const = "postgresql";
public String Uid() {return uid;} private String uid;
public String Pwd() {return pwd;} private String pwd;
public static Db_conn_info new_(String server, String database, String uid, String pwd) {
return Db_conn_info_.parse_(Bld_raw
( "gplx_key", Tid_const
, "server", server
, "database", database
, "port", "5432"
, "user id", uid
, "password", pwd
, "encoding", "unicode" // needed for 1.1 conn; otherwise, ascii
));
}
@Override public Db_conn_info New_self(String raw, GfoMsg m) {
Postgres_conn_info rv = new Postgres_conn_info();
rv.Ctor(m.ReadStr("server"), m.ReadStr("database"), raw, BldApi(m, KeyVal_.new_("encoding", "unicode")));
rv.uid = m.ReadStr("user id");
rv.pwd = m.ReadStr("password");
return rv;
}
public static final Postgres_conn_info _ = new Postgres_conn_info(); Postgres_conn_info() {}
}

View File

@@ -0,0 +1,35 @@
/*
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.engines.postgres; import gplx.*; import gplx.dbs.*; import gplx.dbs.engines.*;
import gplx.stores.*; import gplx.dbs.engines.*; import gplx.dbs.sqls.*;
import java.sql.*;
public class Postgres_engine extends Db_engine_sql_base {
@Override public String Tid() {return Postgres_conn_info.Tid_const;}
@Override public Sql_qry_wtr SqlWtr() {return Sql_qry_wtr_.new_escape_backslash();}
@Override public Db_engine New_clone(Db_conn_info connectInfo) {
Postgres_engine rv = new Postgres_engine();
rv.Ctor(connectInfo);
return rv;
}
@Override public DataRdr New_rdr(ResultSet rdr, String commandText) {return Db_data_rdr_.new_(rdr, commandText);}
@gplx.Internal @Override protected Connection Conn_new() {
Postgres_conn_info conn_info_as_postgres = (Postgres_conn_info)conn_info;
return Conn_make_by_url("jdbc:" + conn_info_as_postgres.Tid() + "://localhost/" + conn_info_as_postgres.Database(), conn_info_as_postgres.Uid(), conn_info_as_postgres.Pwd());
}
public static final Postgres_engine _ = new Postgres_engine(); Postgres_engine() {}
}

View File

@@ -0,0 +1,47 @@
/*
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.engines.sqlite; import gplx.*; import gplx.dbs.*; import gplx.dbs.engines.*;
public class Sqlite_conn_info extends Db_conn_info__base {
@Override public String Tid() {return Tid_const;} public static final String Tid_const = "sqlite";
public Io_url Url() {return url;} private Io_url url;
@Override public Db_conn_info New_self(String raw, GfoMsg m) {
Sqlite_conn_info rv = new Sqlite_conn_info();
String url = m.ReadStr("data source");
rv.url = Io_url_.new_any_(url);
rv.Ctor("", url, raw, BldApi(m, KeyVal_.new_("version", "3")));
rv.database = rv.url.NameOnly();
return rv;
}
public static Db_conn_info load_(Io_url url) {
return Db_conn_info_.parse_(Bld_raw
( "gplx_key" , Tid_const
, "data source" , url.Xto_api()
, "version" , "3"
));
}
public static Db_conn_info make_(Io_url url) {
Io_mgr.I.CreateDirIfAbsent(url.OwnerDir());
return Db_conn_info_.parse_(Bld_raw
( "gplx_key" , Tid_const
, "data source" , url.Xto_api()
, "version" , "3"
));
}
public static final Sqlite_conn_info _ = new Sqlite_conn_info(); Sqlite_conn_info() {}
}

View File

@@ -0,0 +1,130 @@
/*
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.engines.sqlite; import gplx.*; import gplx.dbs.*; import gplx.dbs.engines.*;
import java.sql.*;
import gplx.stores.*; import gplx.dbs.engines.*; import gplx.dbs.engines.sqlite.*;
import gplx.dbs.qrys.*;
public class Sqlite_engine extends Db_engine_sql_base {
private final Sqlite_txn_mgr txn_mgr; private final Sqlite_schema_mgr schema_mgr;
Sqlite_engine() {
this.txn_mgr = new Sqlite_txn_mgr(this);
this.schema_mgr = new Sqlite_schema_mgr(this);
}
@Override public String Tid() {return Sqlite_conn_info.Tid_const;}
@Override public Db_engine New_clone(Db_conn_info connectInfo) {
Sqlite_engine rv = new Sqlite_engine();
rv.Ctor(connectInfo);
return rv;
}
@Override public DataRdr New_rdr(ResultSet rdr, String commandText) {return Sqlite_rdr.new_(rdr, commandText);}
@Override public Db_rdr New_rdr_clone() {return new Db_rdr__sqlite();}
@Override public void Env_db_attach(String alias, Io_url db_url) {Exec_as_int(String_.Format("ATTACH '{0}' AS {1};", db_url.Raw(), alias));}
@Override public void Env_db_detach(String alias) {Exec_as_int(String_.Format("DETACH {0};", alias));}
@Override public void Txn_bgn(String name) {txn_mgr.Txn_bgn(name);}
@Override public void Txn_end() {txn_mgr.Txn_end();}
@Override public void Txn_cxl() {txn_mgr.Txn_cxl();}
@Override public void Txn_sav() {txn_mgr.Txn_sav();}
@Override public boolean Meta_tbl_exists(String tbl) {return schema_mgr.Tbl_exists(tbl);}
@Override public boolean Meta_fld_exists(String tbl, String fld) {return schema_mgr.Fld_exists(tbl, fld);}
static boolean loaded = false;
@gplx.Internal @Override protected Connection Conn_new() {
if (!loaded) {
try {
Class.forName("org.sqlite.JDBC");
}
catch (ClassNotFoundException e) {throw Exc_.new_exc(e, "db", "could not load sqlite jdbc driver");}
loaded = true;
}
Sqlite_conn_info conn_info_as_sqlite = (Sqlite_conn_info)conn_info;
Connection rv = Conn_make_by_url("jdbc:sqlite://" + String_.Replace(conn_info_as_sqlite.Url().Raw(), "\\", "/"), "", "");
return rv;
}
public static final Sqlite_engine _ = new Sqlite_engine();
}
class Db_rdr__sqlite extends Db_rdr__basic { @Override public byte Read_byte(String k) {try {return (byte)Int_.cast_(rdr.getObject(k));} catch (Exception e) {throw Exc_.new_exc(e, "db", "read failed", "k", k, "type", Byte_.Cls_val_name);}}
@Override public boolean Read_bool_by_byte(String k) {
try {
int val = rdr.getInt(k);
return val == 1;
} catch (Exception e) {throw Exc_.new_exc(e, "db", "read failed", "i", k, "type", Bool_.Cls_val_name);}
}
@Override public long Read_long(String k) {
try {
long val = rdr.getLong(k);
Number n = (Number)val;
return n.longValue();
} catch (Exception e) {throw Exc_.new_exc(e, "db", "read failed", "i", k, "type", Long_.Cls_val_name);}
}
@Override public float Read_float(String k) {
try {
Double val = (Double)rdr.getDouble(k);
return val == null ? Float.NaN : val.floatValue();
} catch (Exception e) {throw Exc_.new_exc(e, "db", "read failed:", "i", k, "type", Float_.Cls_val_name);}
}
@Override public DateAdp Read_date_by_str(String k) {
try {
String val = rdr.getString(k);
return val == null ? null : DateAdp_.parse_fmt(val, "yyyyMMdd_HHmmss");
} catch (Exception e) {throw Exc_.new_exc(e, "db", "read failed", "i", k, "type", DateAdp_.Cls_ref_type);}
}
// @Override public DecimalAdp ReadDecimalOr(String key, DecimalAdp or) {
// Object val = Read(key);
// Double d = ((Double)val);
// return val == null ? null : DecimalAdp_.double_(d);
// }
}
class Sqlite_rdr extends Db_data_rdr { @Override public float ReadFloat(String key) {return ReadFloatOr(key, Float.NaN);}
@Override public float ReadFloatOr(String key, float or) {
Object val = Read(key);
Double d = ((Double)val);
return val == null ? or : d.floatValue();
}
@Override public DecimalAdp ReadDecimal(String key) {return ReadDecimalOr(key, null);}
@Override public DecimalAdp ReadDecimalOr(String key, DecimalAdp or) {
Object val = Read(key);
Double d = ((Double)val);
return val == null ? or : DecimalAdp_.double_(d);
}
@Override public DateAdp ReadDate(String key) {return ReadDateOr(key, null);}
@Override public DateAdp ReadDateOr(String key, DateAdp or) {
Object val = Read(key);
return val == null ? or : DateAdp_.parse_fmt((String)val, "M/dd/yyyy hh:mm tt");
}
@Override public boolean ReadBool(String key) {return ReadBoolOr(key, false);}
@Override public boolean ReadBoolOr(String key, boolean or) {
Object val = Read(key);
return val == null ? or : Int_.cast_(val) == 1;
}
@Override public byte ReadByte(String key) {return ReadByteOr(key, Byte_.Zero);}
@Override public byte ReadByteOr(String key, byte or) {
Object val = Read(key);
return val == null ? or : (byte)Int_.cast_(val);
}
@Override public long ReadLong(String key) {return ReadLongOr(key, Long_.MinValue);}
@Override public long ReadLongOr(String key, long or) {
Object val = Read(key);
if (val == null) return or;
Number n = (Number)val;
return n.longValue();
}
public static Sqlite_rdr new_(ResultSet rdr, String commandText) {
Sqlite_rdr rv = new Sqlite_rdr();
rv.ctor_db_data_rdr(rdr, commandText);
return rv;
} Sqlite_rdr() {}
}

View File

@@ -0,0 +1,92 @@
/*
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.engines.sqlite; import gplx.*; import gplx.dbs.*; import gplx.dbs.engines.*;
import gplx.core.primitives.*; import gplx.dbs.qrys.*; import gplx.dbs.utls.*; import gplx.dbs.engines.*; import gplx.dbs.engines.sqlite.*;
public class Sqlite_engine_ {
public static void Db_attach(Db_conn p, String alias, String url) {
String s = String_.Format("ATTACH '{0}' AS {1};", url, alias);
Db_qry qry = Db_qry_sql.xtn_(s);
p.Exec_qry(qry);
}
public static void Db_detach(Db_conn p, String alias) {
String s = String_.Format("DETACH '{0}';", alias);
Db_qry qry = Db_qry_sql.xtn_(s);
p.Exec_qry(qry);
}
public static void Tbl_create_and_delete(Db_conn p, String tbl_name, String tbl_sql) {
Tbl_delete(p, tbl_name);
Db_qry qry = Db_qry_sql.ddl_(tbl_sql);
p.Exec_qry(qry);
}
public static void Tbl_create(Db_conn p, String tbl_name, String tbl_sql) {
Db_qry qry = Db_qry_sql.ddl_(tbl_sql);
p.Exec_qry(qry);
}
public static void Tbl_delete_many(Db_conn p, String... tbls) {
int len = tbls.length;
for (int i = 0; i < len; i++)
Tbl_delete(p, tbls[i]);
}
public static void Tbl_delete(Db_conn p, String tbl) {
Db_qry qry = Db_qry_sql.ddl_("DROP TABLE IF EXISTS " + tbl + ";");
p.Exec_qry(qry);
}
public static void Tbl_rename(Db_conn p, String src, String trg) {
Db_qry qry = Db_qry_sql.ddl_(String_.Format("ALTER TABLE {0} RENAME TO {1};", src, trg));
p.Exec_qry(qry);
}
public static void Pragma_page_size(Db_conn p, int val) {
Db_qry qry = Db_qry_sql.ddl_("PRAGMA page_size = " + Int_.Xto_str(val) + ";");
p.Exec_qry(qry);
}
public static void Idx_create(Gfo_usr_dlg usr_dlg, Db_conn conn, String tbl, Db_meta_idx[] idx_ary) {
int len = idx_ary.length;
for (int i = 0; i < len; ++i) {
Db_meta_idx idx = idx_ary[i];
String idx_sql = idx.To_sql_create();
usr_dlg.Plog_many("", "", "creating index: ~{0} ~{1}", tbl, idx_sql);
conn.Exec_qry(Db_qry_sql.ddl_(idx.To_sql_create()));
usr_dlg.Log_many("", "", "index created: ~{0} ~{1}", tbl, idx_sql);
}
}
public static void Idx_create(Db_conn p, Db_idx_itm... idxs) {Idx_create(Gfo_usr_dlg_.Noop, p, "", idxs);}
public static void Idx_create(Gfo_usr_dlg usr_dlg, Db_conn p, String file_id, Db_idx_itm... idxs) {
int len = idxs.length;
for (int i = 0; i < len; i++) {
String index = idxs[i].Xto_sql();
usr_dlg.Plog_many("", "", "creating index: ~{0} ~{1}", file_id, index);
p.Exec_qry(Db_qry_sql.ddl_(index));
usr_dlg.Log_many("", "", "index created: ~{0} ~{1}", file_id, index);
}
}
public static Db_conn Conn_load_or_make_(Io_url url, Bool_obj_ref created) {
boolean exists = Io_mgr.I.ExistsFil(url);
created.Val_(!exists);
Db_conn_info connect = exists ? Sqlite_conn_info.load_(url) : Sqlite_conn_info.make_(url);
Db_conn p = Db_conn_pool.I.Get_or_new(connect);
if (!exists)
Pragma_page_size(p, 4096);
return p;
}
public static final int Stmt_arg_max = 999; // 999 is max number of variables allowed by sqlite
public static final boolean Supports_read_binary_stream = false;
public static final boolean Supports_indexed_by = true;
public static String X_date_to_str(DateAdp v) {return v == Date_null ? "" : v.XtoStr_fmt_iso_8561();}
public static final DateAdp Date_null = null;
public static final byte Wildcard_byte = Byte_ascii.Hash;
}

View File

@@ -0,0 +1,66 @@
/*
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.engines.sqlite; import gplx.*; import gplx.dbs.*; import gplx.dbs.engines.*;
import gplx.dbs.qrys.*;
import gplx.dbs.metas.*; import gplx.dbs.metas.parsers.*;
public class Sqlite_schema_mgr {
private final Db_engine engine; private boolean init = true;
public Sqlite_schema_mgr(Db_engine engine) {this.engine = engine;}
public Meta_tbl_mgr Tbl_mgr() {return tbl_mgr;} private final Meta_tbl_mgr tbl_mgr = new Meta_tbl_mgr();
public Meta_idx_mgr Idx_mgr() {return idx_mgr;} private final Meta_idx_mgr idx_mgr = new Meta_idx_mgr();
public boolean Tbl_exists(String name) {
if (init) Init(engine);
return tbl_mgr.Has(name);
}
public boolean Fld_exists(String tbl, String fld) {
if (init) Init(engine);
Meta_tbl_itm tbl_itm = tbl_mgr.Get_by(tbl);
return (tbl_itm == null) ? false : tbl_itm.Flds().Has(fld);
}
private void Init(Db_engine engine) {
init = false;
Gfo_usr_dlg_.I.Log_many("", "", "db.schema.load.bgn: conn=~{0}", engine.Conn_info().Xto_api());
Meta_parser__tbl tbl_parser = new Meta_parser__tbl();
Db_qry__select_in_tbl qry = Db_qry__select_in_tbl.new_("sqlite_master", String_.Ary_empty, String_.Ary("type", "name", "sql"), Db_qry__select_in_tbl.Order_by_null);
Db_rdr rdr = engine.New_stmt_prep(qry).Exec_select__rls_auto();
try {
while (rdr.Move_next()) {
String type_str = rdr.Read_str("type");
String name = rdr.Read_str("name");
String sql = rdr.Read_str("sql");
int type_int = Meta_itm_tid.Xto_int(type_str);
switch (type_int) {
case Meta_itm_tid.Tid_table:
if (String_.Eq(name, "sqlite_sequence")) continue; // ignore b/c of non-orthodox syntax; EX: "CREATE TABLE sqlite_sequence(name, seq)";
// Meta_tbl_itm tbl_itm = new Meta_tbl_itm(tbl_name, tbl_sql);
Meta_tbl_itm tbl_itm = tbl_parser.Parse(Bry_.new_u8(sql));
tbl_mgr.Add(tbl_itm);
break;
case Meta_itm_tid.Tid_index:
Meta_idx_itm idx_itm = new Meta_idx_itm(name, sql);
idx_mgr.Add(idx_itm);
break;
default:
Gfo_usr_dlg_.I.Log_many("", "", "db.schema.unknown type: conn=~{0} type=~{1} name=~{2} sql=~{3}", engine.Conn_info().Xto_api(), type_str, name, sql);
break;
}
}
} finally {rdr.Rls();}
Gfo_usr_dlg_.I.Log_many("", "", "db.schema.load.end");
}
}

View File

@@ -0,0 +1,70 @@
/*
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.engines.sqlite; import gplx.*; import gplx.dbs.*; import gplx.dbs.engines.*;
import gplx.dbs.qrys.*;
public class Sqlite_txn_mgr {
private final List_adp txn_list = List_adp_.new_();
public Sqlite_txn_mgr(Db_engine engine) {this.engine = engine;} private final Db_engine engine;
private boolean pragma_needed = Bool_.Y, txn_started = Bool_.N; // NOTE: txns only support 1 level; SQLite fails when nesting transactions; DATE:2015-03-11
public void Txn_bgn(String name) {
if (String_.Len_eq_0(name)) name = "unnamed";
if (pragma_needed) {
pragma_needed = false;
engine.Exec_as_obj(Db_qry_sql.xtn_("PRAGMA synchronous = OFF;"));
}
// Execute(Db_qry_sql.xtn_("PRAGMA ENCODING=\"UTF-8\";"));
// Execute(Db_qry_sql.xtn_("PRAGMA journal_mode = OFF;")); // will cause out of memory
// Execute(Db_qry_sql.xtn_("PRAGMA journal_mode = MEMORY;"));
// Execute(Db_qry_sql.xtn_("PRAGMA temp_store = MEMORY;"));
// Execute(Db_qry_sql.xtn_("PRAGMA locking_mode = EXCLUSIVE;"));
// Execute(Db_qry_sql.xtn_("PRAGMA cache_size=4000;")); // too many will also cause out of memory
if (txn_started) {
engine.Exec_as_obj(Db_qry_sql.xtn_(String_.Format("SAVEPOINT {0};", name)));
}
else {
txn_started = true;
engine.Exec_as_obj(Db_qry_sql.xtn_("BEGIN TRANSACTION;"));
}
txn_list.Add(name);
}
public void Txn_end() {
if (txn_list.Count() == 0) {Gfo_usr_dlg_.I.Warn_many("", "", "no txns in stack;"); return;}
String txn_last = (String)List_adp_.Pop_last(txn_list);
if (txn_list.Count() == 0) {// no txns left; commit it
engine.Exec_as_obj(Db_qry_sql.xtn_("COMMIT TRANSACTION;"));
txn_started = false;
}
else
engine.Exec_as_obj(Db_qry_sql.xtn_(String_.Format("RELEASE SAVEPOINT {0};", txn_last)));
}
public void Txn_cxl() {
if (txn_list.Count() == 0) {Gfo_usr_dlg_.I.Warn_many("", "", "no txns in stack;"); return;}
String txn_last = (String)List_adp_.Pop_last(txn_list);
if (txn_list.Count() == 0) {// no txns left; rollback
engine.Exec_as_obj(Db_qry_sql.xtn_("ROLLBACK TRANSACTION;"));
txn_started = false;
}
else
engine.Exec_as_obj(Db_qry_sql.xtn_(String_.Format("ROLBACK TRANSACTION TO SAVEPOINT {0};", txn_last)));
}
public void Txn_sav() {
if (txn_list.Count() == 0) {Gfo_usr_dlg_.I.Warn_many("", "", "no txns in stack;"); return;}
String name = (String)txn_list.Get_at(txn_list.Count() - 1);
this.Txn_end(); this.Txn_bgn(name);
}
}

View File

@@ -0,0 +1,32 @@
/*
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.engines.tdbs; import gplx.*; import gplx.dbs.*; import gplx.dbs.engines.*;
import org.junit.*;
public class TdbConnectInfo_tst {
@Test public void Full() {
Db_conn_info connectInfo = Db_conn_info_.parse_("gplx_key=tdb;url=C:\\dir\\xmpl.tdb;format=dsv;");
tst_Parse(connectInfo, Io_url_.new_any_("C:\\dir\\xmpl.tdb"), "dsv");
}
@Test public void DefaultFormat() {
Db_conn_info connectInfo = Db_conn_info_.parse_("gplx_key=tdb;url=C:\\dir\\xmpl.tdb"); // dsv Format inferred
tst_Parse(connectInfo, Io_url_.new_any_("C:\\dir\\xmpl.tdb"), "dsv");
}
void tst_Parse(Db_conn_info connectInfo, Io_url url, String format) {
Tfds.Eq(((Tdb_conn_info)connectInfo).Url(), url);
}
}

View File

@@ -0,0 +1,47 @@
/*
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.engines.tdbs; import gplx.*; import gplx.dbs.*; import gplx.dbs.engines.*;
public class TdbDatabase {
public String Name() {return name;} public void Name_set(String v) {name = v;} private String name = "xmpl";
public Io_url DbUrl() {return dbInfo;} Io_url dbInfo;
public TdbFileList Files() {return files;} TdbFileList files;
public TdbTableList Tables() {return tables;} TdbTableList tables;
@gplx.Internal protected boolean IsNew() {return isNew;} @gplx.Internal protected void IsNew_set(boolean v) {isNew = v;} private boolean isNew;
@gplx.Internal protected TdbFile MakeFile(Io_url url) {
TdbFile rv = TdbFile.new_(FileId_next++, url);
files.Add(rv);
return rv;
}
@gplx.Internal protected TdbTable MakeTbl(String name, int fileId) {
TdbFile file = files.Get_by_or_fail(fileId);
TdbTable rv = TdbTable.new_(TableId_next++, name, file);
tables.Add(rv);
return rv;
}
public static TdbDatabase new_(Io_url dbInfo) {TdbDatabase rv = new TdbDatabase(); rv.ctor(dbInfo); return rv;}
void ctor(Io_url dbInfo) {
this.dbInfo = dbInfo;
TdbFile mainFile = TdbFile.new_(TdbFile.MainFileId, dbInfo);
files = TdbFileList.new_(dbInfo, mainFile);
tables = TdbTableList.new_(dbInfo);
}
int FileId_next = TdbFile.MainFileId + 1;
int TableId_next = 1;
// public static Io_url UrlOf(Db_conn_info url) {return Io_url_.new_any_(url.ServerName());}
}

View File

@@ -0,0 +1,49 @@
/*
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.engines.tdbs; import gplx.*; import gplx.dbs.*; import gplx.dbs.engines.*;
class TdbDbLoadMgr {
public TdbDatabase LoadTbls(Io_url dbInfo) {
TdbDatabase db = TdbDatabase.new_(dbInfo);
if (!Io_mgr.I.ExistsFil(dbInfo)) {
db.IsNew_set(true);
return db;
}
DataRdr rdr = MakeDataRdr(dbInfo);
LoadTblsByRdr(db, rdr);
return db;
}
public void LoadTbl(TdbDatabase db, TdbTable tbl) {
DataRdr rootRdr = MakeDataRdr(tbl.File().Path());
LoadTblsByRdr(db, rootRdr);
}
void LoadTblsByRdr(TdbDatabase db, DataRdr rootRdr) {
DataRdr rdr = rootRdr.Subs();
while (rdr.MoveNextPeer()) {
String name = rdr.NameOfNode();
if (String_.Eq(name, TdbFileList.StoreTblName)) db.Files().DataObj_Rdr(rdr);
else if (String_.Eq(name, TdbTableList.StoreTableName)) db.Tables().DataObj_Rdr(rdr, db.Files());
else db.Tables().Get_by_or_fail(rdr.NameOfNode()).DataObj_Rdr(rdr);
}
if (db.Files().Count() == 0) throw Exc_.new_("fatal error: db has no files", "connectInfo", db.DbUrl());
}
DataRdr MakeDataRdr(Io_url fil) {
String text = Io_mgr.I.LoadFilStr(fil);
return TdbStores.rdr_(text);
}
public static TdbDbLoadMgr new_() {return new TdbDbLoadMgr();} TdbDbLoadMgr() {}
}

View File

@@ -0,0 +1,101 @@
/*
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.engines.tdbs; import gplx.*; import gplx.dbs.*; import gplx.dbs.engines.*;
import org.junit.*;
import gplx.stores.*; /*DsvDataRdr*/ import gplx.stores.dsvs.*; /*DsvDataWtr*/
public class TdbDbLoadMgr_tst {
@Before public void setup() {
Io_url dbInfo = Io_url_.mem_fil_("mem/dir/db0.dsv");
db = TdbDatabase.new_(dbInfo);
wtr = DsvDataWtr_.new_();
}
TdbDatabase db; TdbDbLoadMgr loadMgr = TdbDbLoadMgr.new_(); TdbDbSaveMgr saveMgr = TdbDbSaveMgr.new_();
DataRdr rdr; DataWtr wtr;
@Test public void ReadDbFiles() {
String raw = String_.Concat_lines_crlf
( "=======DIF======================, ,\" \",//"
, "_files, ,\" \",#"
, "==DEF==DIF======================, ,\" \",//"
, "int," + StringClassXtn.Key_const + "," + StringClassXtn.Key_const + ", ,\" \",$"
, "id,url,format, ,\" \",@"
, "==DATA=DIF======================, ,\" \",//"
, "1,mem/dir/db0.dsv,dsv"
, "2,C:\\file.dsv,dsv"
);
rdr = rdr_(raw);
db.Files().DataObj_Rdr(rdr);
Tfds.Eq(db.Files().Count(), 2);
TdbFile file2 = db.Files().Get_by_or_fail(2);
Tfds.Eq(file2.Path().Raw(), "C:\\file.dsv");
db.Files().DataObj_Wtr(wtr);
Tfds.Eq(wtr.XtoStr(), raw);
}
@Test public void ReadDbTbls() {
String raw = String_.Concat_lines_crlf
( "=======DIF======================, ,\" \",//"
, "_tables, ,\" \",#"
, "==DEF==DIF======================, ,\" \",//"
, "int," + StringClassXtn.Key_const + ",int, ,\" \",$"
, "id,name,file_id, ,\" \",@"
, "==DATA=DIF======================, ,\" \",//"
, "1,tbl1,1"
);
rdr = rdr_(raw);
db.Tables().DataObj_Rdr(rdr, db.Files());
Tfds.Eq(db.Tables().Count(), 1);
TdbTable table = db.Tables().Get_by_or_fail("tbl1");
Tfds.Eq(table.Name(), "tbl1");
Tfds.Eq(table.File().Id(), 1);
db.Tables().DataObj_Wtr(wtr);
Tfds.Eq(wtr.XtoStr(), raw);
}
@Test public void ReadTbl() {
String raw = String_.Concat_lines_crlf
( "=======DIF======================, ,\" \",//"
, "tbl0, ,\" \",#"
, "==DEF==DIF======================, ,\" \",//"
, "int," + StringClassXtn.Key_const + ", ,\" \",$"
, "id,name, ,\" \",@"
, "==DATA=DIF======================, ,\" \",//"
, "0,me"
);
rdr = rdr_(raw);
db.MakeTbl("tbl0", TdbFile.MainFileId);
db.Tables().Get_by_or_fail(rdr.NameOfNode()).DataObj_Rdr(rdr);
Tfds.Eq(db.Tables().Count(), 1);
TdbTable tbl = db.Tables().Get_by_or_fail("tbl0");
Tfds.Eq(tbl.Rows().Count(), 1);
GfoNde row = tbl.Rows().FetchAt_asGfoNde(0);
Tfds.Eq(row.Read("id"), 0);
Tfds.Eq(row.Read("name"), "me");
tbl.DataObj_Wtr(wtr);
Tfds.Eq(wtr.XtoStr(), raw);
}
DataRdr rdr_(String raw) {
DataRdr rdr = DsvDataRdr_.dsv_(raw);
rdr.MoveNextPeer(); // must move next as cur is not set and ReadProcs assume cur is set
return rdr;
}
}

View File

@@ -0,0 +1,63 @@
/*
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.engines.tdbs; import gplx.*; import gplx.dbs.*; import gplx.dbs.engines.*;
class TdbDbSaveMgr {
public void SaveDb(TdbDatabase db) {
for (Object filObj : db.Files()) {
TdbFile fil = (TdbFile)filObj;
SaveFile(db, fil);
}
}
public void SaveFile(TdbDatabase db, TdbFile fil) {
List_adp tbls = FetchTablesWithSamePath(db, fil.Path());
boolean isSaveNeeded = db.IsNew();
for (Object tblObj : tbls) {
TdbTable tbl = (TdbTable)tblObj;
if (tbl.IsDirty()) {
isSaveNeeded = true;
break;
}
}
if (isSaveNeeded) {
SaveTblsToFile(db, fil, tbls);
db.IsNew_set(false);
}
}
void SaveTblsToFile(TdbDatabase db, TdbFile fil, List_adp tbls) {
DataWtr wtr = TdbStores.wtr_();
if (fil.Id() == TdbFile.MainFileId) { // if MainFile, save critical Files and Tables data
db.Files().DataObj_Wtr(wtr);
db.Tables().DataObj_Wtr(wtr);
}
for (Object tblObj : tbls) {
TdbTable tbl = (TdbTable)tblObj;
tbl.DataObj_Wtr(wtr);
}
Io_mgr.I.SaveFilStr(fil.Path(), wtr.XtoStr());
}
List_adp FetchTablesWithSamePath(TdbDatabase db, Io_url filPath) {
List_adp list = List_adp_.new_();
for (Object tblObj : db.Tables()) {
TdbTable tbl = (TdbTable)tblObj;
if (tbl.File().Path().Eq (filPath))
list.Add(tbl);
}
return list;
}
public static TdbDbSaveMgr new_() {return new TdbDbSaveMgr();} TdbDbSaveMgr() {}
}

View File

@@ -0,0 +1,77 @@
/*
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.engines.tdbs; import gplx.*; import gplx.dbs.*; import gplx.dbs.engines.*;
import org.junit.*;
import gplx.stores.dsvs.*; /*DsvDataWtr*/
public class TdbDbSaveMgr_tst {
@Before public void setup() {
Io_url dbInfo = Io_url_.mem_fil_("mem/dir/db0.dsv");
db = TdbDatabase.new_(dbInfo);
wtr.Clear();
} TdbDatabase db; TdbDbSaveMgr saveMgr = TdbDbSaveMgr.new_(); DataWtr wtr = DsvDataWtr_.new_();
@Test public void WriteDbFils() {
String expd = String_.Concat_lines_crlf
( ""
, ""
, "================================, ,\" \",//"
, "_files, ,\" \",#"
, "================================, ,\" \",//"
, "int," + StringClassXtn.Key_const + "," + StringClassXtn.Key_const + ", ,\" \",$"
, "id,url,format, ,\" \",@"
, "================================, ,\" \",//"
, "1,mem/dir/db0.dsv,dsv"
);
db.Files().DataObj_Wtr(wtr);
String actl = wtr.XtoStr();
Tfds.Eq(expd, actl);
}
@Test public void WriteDbTbls() {
String expd = String_.Concat_lines_crlf
( ""
, ""
, "================================, ,\" \",//"
, "_tables, ,\" \",#"
, "================================, ,\" \",//"
, "int," + StringClassXtn.Key_const + ",int, ,\" \",$"
, "id,name,file_id, ,\" \",@"
, "================================, ,\" \",//"
);
db.Tables().DataObj_Wtr(wtr);
String actl = wtr.XtoStr();
Tfds.Eq(expd, actl);
}
@Test public void WriteTbl() {
String expd = String_.Concat_lines_crlf
( ""
, ""
, "================================, ,\" \",//"
, "tbl, ,\" \",#"
, "================================, ,\" \",//"
, "int," + StringClassXtn.Key_const + ", ,\" \",$"
, "id,name, ,\" \",@"
, "================================, ,\" \",//"
);
TdbTable tbl = db.MakeTbl("tbl", TdbFile.MainFileId);
tbl.Flds().Add("id", IntClassXtn._);
tbl.Flds().Add("name", StringClassXtn._);
tbl.DataObj_Wtr(wtr);
String actl = wtr.XtoStr();
Tfds.Eq(expd, actl);
}
}

View File

@@ -0,0 +1,47 @@
/*
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.engines.tdbs; import gplx.*; import gplx.dbs.*; import gplx.dbs.engines.*;
import gplx.core.criterias.*; import gplx.lists.*; /*GfoNde*/ import gplx.dbs.qrys.*;
class TdbDeleteWkr implements Db_qryWkr {
public Object Exec(Db_engine engineObj, Db_qry cmdObj) {
TdbEngine engine = TdbEngine.cast_(engineObj); Db_qry_delete cmd = (Db_qry_delete)cmdObj;
TdbTable tbl = engine.FetchTbl(cmd.Base_table());
List_adp deleted = List_adp_.new_();
int rv = 0;
if (cmd.Where() == Db_qry_.WhereAll) {
rv = tbl.Rows().Count();
tbl.Rows().Clear();
}
else {
Criteria crt = cmd.Where();
for (int i = 0; i < tbl.Rows().Count(); i++) {
GfoNde row = tbl.Rows().FetchAt_asGfoNde(i);
if (crt.Matches(row))
deleted.Add(row);
}
for (int i = 0; i < deleted.Count(); i++) {
GfoNde row = (GfoNde)deleted.Get_at(i);
tbl.Rows().Del(row);
rv++;
}
}
if (rv > 0) tbl.IsDirty_set(true);
return rv;
}
public static TdbDeleteWkr new_() {TdbDeleteWkr rv = new TdbDeleteWkr(); return rv;}
}

View File

@@ -0,0 +1,90 @@
/*
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.engines.tdbs; import gplx.*; import gplx.dbs.*; import gplx.dbs.engines.*;
import gplx.dbs.qrys.*; import gplx.dbs.sqls.*;
public class TdbEngine implements Db_engine {
public String Tid() {return Tdb_conn_info.Tid_const;}
public Db_conn_info Conn_info() {return conn_info;} private Db_conn_info conn_info;
public TdbDatabase Db() {return db;} TdbDatabase db;
public void Conn_open() {
Tdb_conn_info tdb_url = (Tdb_conn_info)conn_info;
String url_str = tdb_url.Server();
db = loadMgr.LoadTbls(Io_url_.new_any_(url_str));
}
public void Conn_term() {}
public void Txn_bgn(String name) {}
public void Txn_end() {}
public void Txn_cxl() {}
public void Txn_sav() {}
public Db_engine New_clone(Db_conn_info conn_info) {
TdbEngine rv = new TdbEngine();
rv.CtorTdbEngine(conn_info);
rv.Conn_open();
return rv;
}
public Object Exec_as_obj(Db_qry qry) {
Db_qryWkr wkr = (Db_qryWkr)wkrs.Get_by_or_fail(qry.Tid());
return wkr.Exec(this, qry);
}
public Db_stmt New_stmt_prep(Db_qry qry) {return new Db_stmt_sql().Parse(qry, Sql_qry_wtr_.I.Xto_str(qry, true));}
public Object New_stmt_prep_as_obj(String sql) {throw Exc_.new_unimplemented();}
public Db_rdr New_rdr__rls_manual(Object rdr_obj, String sql) {return Db_rdr_.Empty;}
public Db_rdr New_rdr__rls_auto(Db_stmt stmt, Object rdr_obj, String sql) {return Db_rdr_.Empty;}
public DataRdr New_rdr(java.sql.ResultSet rdr, String sql) {return DataRdr_.Null;}
public TdbTable FetchTbl(String name) {
TdbTable tbl = db.Tables().Get_by_or_fail(name);
if (!tbl.IsLoaded()) loadMgr.LoadTbl(db, tbl);
return tbl;
}
public void FlushAll() {
saveMgr.SaveDb(db);
}
public void FlushTbl(TdbTable tbl) {
saveMgr.SaveFile(db, tbl.File());
}
public void Ddl_create_tbl(Db_meta_tbl meta) {throw Exc_.new_unimplemented();}
public void Ddl_create_idx(Gfo_usr_dlg usr_dlg, Db_meta_idx... ary) {throw Exc_.new_unimplemented();}
public void Ddl_append_fld(String tbl, Db_meta_fld fld) {throw Exc_.new_unimplemented();}
public void Ddl_delete_tbl(String tbl) {}
public void Env_db_attach(String alias, Io_url db_url) {}
public void Env_db_detach(String alias) {}
public boolean Meta_tbl_exists(String name) {return false;}
public boolean Meta_fld_exists(String tbl, String fld) {return false;}
Hash_adp wkrs = Hash_adp_.new_(); TdbDbLoadMgr loadMgr = TdbDbLoadMgr.new_(); TdbDbSaveMgr saveMgr = TdbDbSaveMgr.new_();
public static final TdbEngine _ = new TdbEngine();
void CtorTdbEngine(Db_conn_info conn_info) {
this.conn_info = conn_info;
wkrs.Add(Db_qry_.Tid_select, TdbSelectWkr._);
wkrs.Add(Db_qry_.Tid_insert, TdbInsertWkr.new_());
wkrs.Add(Db_qry_.Tid_update, TdbUpdateWkr.new_());
wkrs.Add(Db_qry_.Tid_delete, TdbDeleteWkr.new_());
wkrs.Add(Db_qry_.Tid_flush, TdbFlushWkr.new_());
}
public static TdbEngine as_(Object obj) {return obj instanceof TdbEngine ? (TdbEngine)obj : null;}
public static TdbEngine cast_(Object obj) {try {return (TdbEngine)obj;} catch(Exception exc) {throw Exc_.new_type_mismatch_w_exc(exc, TdbEngine.class, obj);}}
}
interface Db_qryWkr {
Object Exec(Db_engine engine, Db_qry cmd);
}
class Db_qryWkr_ {
public static final Db_qryWkr Null = new Db_qryWrk_null();
}
class Db_qryWrk_null implements Db_qryWkr {
public Object Exec(Db_engine engine, Db_qry cmd) {return null;}
}

View File

@@ -0,0 +1,31 @@
/*
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.engines.tdbs; import gplx.*; import gplx.dbs.*; import gplx.dbs.engines.*;
public class TdbFile {
public int Id() {return id;} int id;
public Io_url Path() {return url;} Io_url url;
public static TdbFile new_(int id, Io_url url) {
TdbFile rv = new TdbFile();
rv.id = id; rv.url = url;
return rv;
}
public static final int MainFileId = 1;
public static TdbFile as_(Object obj) {return obj instanceof TdbFile ? (TdbFile)obj : null;}
public static TdbFile cast_(Object obj) {try {return (TdbFile)obj;} catch(Exception exc) {throw Exc_.new_type_mismatch_w_exc(exc, TdbFile.class, obj);}}
}

View File

@@ -0,0 +1,63 @@
/*
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.engines.tdbs; import gplx.*; import gplx.dbs.*; import gplx.dbs.engines.*;
import gplx.lists.*; /*Ordered_hash_base*/ import gplx.stores.dsvs.*; /*DsvStoreLayout*/
public class TdbFileList extends Ordered_hash_base {
public TdbFile Get_by_or_fail(int id) {return TdbFile.as_(FetchOrFail_base(id));}
public void Add(TdbFile src) {Add_base(src.Id(), src);}
Io_url dbInfo;
public static TdbFileList new_(Io_url dbInfo, TdbFile mainFile) {
TdbFileList rv = new TdbFileList();
rv.dbInfo = dbInfo;
rv.Add(mainFile);
rv.layout = DsvStoreLayout.dsv_full_();
return rv;
} TdbFileList() {}
@gplx.Internal protected void DataObj_Wtr(DataWtr wtr) {
wtr.InitWtr(DsvStoreLayout.Key_const, layout);
wtr.WriteTableBgn(StoreTblName, FldList);
for (Object filObj : this) {
TdbFile fil = (TdbFile)filObj;
wtr.WriteLeafBgn("fil");
wtr.WriteData(Fld_id, fil.Id());
wtr.WriteData(Fld_path, fil.Path());
wtr.WriteData("format", "dsv");
wtr.WriteLeafEnd();
}
wtr.WriteNodeEnd();
}
@gplx.Internal protected void DataObj_Rdr(DataRdr rdr) {
layout = TdbStores.FetchLayout(rdr);
this.Clear();
DataRdr subRdr = rdr.Subs();
while (subRdr.MoveNextPeer()) {
int id = subRdr.ReadInt(Fld_id);
String url = subRdr.ReadStrOr(Fld_path, dbInfo.Raw());
TdbFile file = (id == TdbFile.MainFileId)
? TdbFile.new_(TdbFile.MainFileId, dbInfo) // not redundant; prevents error of MainFile in different url/format than connectInfo
: TdbFile.new_(id, Io_url_.new_any_(url));
this.Add(file);
}
}
DsvStoreLayout layout;
public static final String StoreTblName = "_files";
static final String Fld_id = "id"; static final String Fld_path = "url";
static final GfoFldList FldList = GfoFldList_.new_().Add(Fld_id, IntClassXtn._).Add(Fld_path, StringClassXtn._).Add("format", StringClassXtn._);
}

View File

@@ -0,0 +1,34 @@
/*
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.engines.tdbs; import gplx.*; import gplx.dbs.*; import gplx.dbs.engines.*;
import gplx.lists.*; /*GfoNde*/ import gplx.dbs.qrys.*;
class TdbFlushWkr implements Db_qryWkr {
public Object Exec(Db_engine engineObj, Db_qry cmdObj) {
TdbEngine engine = TdbEngine.cast_(engineObj); Db_qry_flush cmd = Db_qry_flush.cast_(cmdObj);
if (Array_.Len(cmd.TableNames()) == 0)
engine.FlushAll();
else {
for (String tblName : cmd.TableNames()) {
TdbTable tbl = engine.FetchTbl(tblName);
if (tbl.IsDirty()) engine.FlushTbl(tbl);
}
}
return 1;
}
public static TdbFlushWkr new_() {TdbFlushWkr rv = new TdbFlushWkr(); return rv;}
}

View File

@@ -0,0 +1,119 @@
/*
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.engines.tdbs; import gplx.*; import gplx.dbs.*; import gplx.dbs.engines.*;
import org.junit.*;
import gplx.ios.*; /*IoMgrFxt*/ import gplx.dbs.qrys.*;
public class TdbFlush_tst {
@Before public void setup() {
Io_mgr.I.InitEngine_mem();
engine = fx_engine.run_MakeEngine(dbPath);
}
TdbEngine engine; Io_url dbPath = Io_url_.mem_fil_("mem/dir/db0.dsv"); DateAdp time = DateAdp_.parse_gplx("2001-01-01");
TdbEngineFxt fx_engine = TdbEngineFxt.new_(); IoMgrFxt fx_io = IoMgrFxt.new_();
@Test public void FlushNewDb() {
fx_engine.tst_FilesCount(engine, 1);
fx_engine.tst_File(engine, 0, TdbFile.MainFileId, Io_url_.mem_fil_("mem/dir/db0.dsv"), "dsv");
fx_io.tst_Exists(false, dbPath);
engine.FlushAll();
fx_io.tst_Exists(true, dbPath);
}
@Test public void IgnoreFlushedDb() {
engine.FlushAll();
fx_io.tst_Exists(true, dbPath);
fx_io.run_UpdateFilModifiedTime(dbPath, time);
engine.FlushAll();
fx_io.tst_QueryFilModified(true, dbPath, time);
}
@Test public void FlushNewTbl() {
engine.FlushAll();
fx_engine.run_MakeTbl(engine, "tbl0", TdbFile.MainFileId);
fx_io.run_UpdateFilModifiedTime(dbPath, time);
engine.FlushAll();
fx_io.tst_QueryFilModified(false, dbPath, time);
}
@Test public void IgnoreFlushedTbl() {
fx_engine.run_MakeTbl(engine, "tbl0", TdbFile.MainFileId);
engine.FlushAll();
fx_io.run_UpdateFilModifiedTime(dbPath, time);
engine.FlushAll();
fx_io.tst_QueryFilModified(true, dbPath, time);
}
@Test public void FlushDirtyTbl() {
fx_engine.run_MakeTbl(engine, "tbl0", TdbFile.MainFileId);
engine.FlushAll();
fx_io.run_UpdateFilModifiedTime(dbPath, time);
fx_engine.run_InsertRow(engine, "tbl0", 1);
engine.FlushAll();
fx_io.tst_QueryFilModified(false, dbPath, time);
}
@Test public void FlushDirtyFilOnly() {
Io_url dbPathOther = Io_url_.mem_fil_("mem/dir/db1.dsv");
TdbFile filOther = fx_engine.run_MakeFile(engine, dbPathOther); Tfds.Eq(false, Object_.Eq(filOther.Id(), TdbFile.MainFileId));
fx_engine.run_MakeTbl(engine, "tbl0", TdbFile.MainFileId); fx_engine.run_MakeTbl(engine, "tbl1", filOther.Id());
engine.FlushAll();
fx_io.run_UpdateFilModifiedTime(dbPath, time); fx_io.run_UpdateFilModifiedTime(dbPathOther, time);
fx_engine.run_InsertRow(engine, "tbl1", 1);
engine.FlushAll();
fx_io.tst_QueryFilModified(true, dbPath, time);
fx_io.tst_QueryFilModified(false, dbPathOther, time);
}
}
class TdbEngineFxt {
public TdbEngine run_MakeEngine(Io_url url) {
Db_conn_info connectInfo = Db_conn_info_.tdb_(url);
TdbEngine engine = (TdbEngine)TdbEngine._.New_clone(connectInfo);
engine.Conn_open();
return engine;
}
public TdbFile run_MakeFile(TdbEngine engine, Io_url url) {return engine.Db().MakeFile(url);}
public TdbTable run_MakeTbl(TdbEngine engine, String tblName, int srcId) {
TdbTable rv = engine.Db().MakeTbl(tblName, srcId);
rv.Flds().Add("id", IntClassXtn._);
return rv;
}
public void run_InsertRow(TdbEngine engine, String tblName, int idVal) {
Db_qry_insert cmd = new Db_qry_insert(tblName);
cmd.Arg_("id", idVal);
engine.Exec_as_obj(cmd);
}
public void tst_FilesCount(TdbEngine engine, int count) {Tfds.Eq(engine.Db().Files().Count(), count);}
public void tst_File(TdbEngine engine, int index, int id, Io_url url, String format) {
TdbFile src = engine.Db().Files().Get_by_or_fail(id);
Tfds.Eq(src.Path().Raw(), url.Raw());
}
public static TdbEngineFxt new_() {return new TdbEngineFxt();} TdbEngineFxt() {}
}
class IoMgrFxt {
public void run_UpdateFilModifiedTime(Io_url url, DateAdp val) {Io_mgr.I.UpdateFilModifiedTime(url, val);}
public void tst_QueryFilModified(boolean expdMatch, Io_url url, DateAdp expt) {
IoItmFil filItem = Io_mgr.I.QueryFil(url);
DateAdp actl = filItem.ModifiedTime();
boolean actlMatch = String_.Eq(expt.XtoStr_gplx(), actl.XtoStr_gplx());
Tfds.Eq(expdMatch, actlMatch, expt.XtoStr_gplx() + (expdMatch ? "!=" : "==") + actl.XtoStr_gplx());
}
public void tst_Exists(boolean expd, Io_url url) {Tfds.Eq(expd, Io_mgr.I.ExistsFil(url));}
public static IoMgrFxt new_() {return new IoMgrFxt();} IoMgrFxt() {}
}

View File

@@ -0,0 +1,59 @@
/*
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.engines.tdbs; import gplx.*; import gplx.dbs.*; import gplx.dbs.engines.*;
import gplx.lists.*; import gplx.dbs.qrys.*; import gplx.dbs.sqls.*;
class TdbInsertWkr implements Db_qryWkr {
public Object Exec(Db_engine engineObj, Db_qry cmdObj) {
TdbEngine engine = TdbEngine.cast_(engineObj); Db_qry_insert cmd = (Db_qry_insert)cmdObj;
TdbTable tbl = engine.FetchTbl(cmd.Base_table());
tbl.IsDirty_set(true);
return cmd.Select() == null
? InsertRowsByVals(engine, tbl, cmd)
: InsertRowsBySelect(engine, tbl, cmd);
}
int InsertRowsBySelect(TdbEngine engine, TdbTable tbl, Db_qry_insert insert) {
int count = 0;
DataRdr rdr = (DataRdr)TdbSelectWkr._.Exec(engine, insert.Select());
Sql_select_fld_list insertFlds = insert.Cols(); int insertFldsCount = insertFlds.Count();
GfoFldList selectFldsForNewRow = null;
try {selectFldsForNewRow = insertFlds.XtoGfoFldLst(tbl);}
catch (Exception e) {throw Exc_.new_exc(e, "db", "failed to generate flds for new row");}
if (insertFldsCount > selectFldsForNewRow.Count()) throw Exc_.new_("insert flds cannot exceed selectFlds", "insertFlds", insertFlds.XtoStr(), "selectFlds", selectFldsForNewRow.XtoStr());
while (rdr.MoveNextPeer()) {
count++;
GfoNde row = GfoNde_.vals_(selectFldsForNewRow, new Object[insertFldsCount]);
for (int i = 0; i < insertFldsCount; i++) {
row.WriteAt(i, rdr.ReadAt(i)); // NOTE: SELECT and INSERT flds are in same order; ex: INSERT INTO (a, b) SELECT (b, a)
}
tbl.Rows().Add(row);
}
return count;
}
int InsertRowsByVals(TdbEngine engine, TdbTable tbl, Db_qry_insert insert) {
GfoNde row = GfoNde_.vals_(tbl.Flds(), new Object[tbl.Flds().Count()]);
for (int i = 0; i < insert.Args().Count(); i++) {
KeyVal kv = insert.Args().Get_at(i);
Db_arg arg = (Db_arg)kv.Val();
row.Write(kv.Key(), arg.Val());
}
tbl.Rows().Add(row);
return 1;
}
public static TdbInsertWkr new_() {TdbInsertWkr rv = new TdbInsertWkr(); return rv;}
}

View File

@@ -0,0 +1,99 @@
/*
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.engines.tdbs; import gplx.*; import gplx.dbs.*; import gplx.dbs.engines.*;
import gplx.core.criterias.*; import gplx.dbs.qrys.*; import gplx.dbs.sqls.*;
import gplx.lists.*; /*ComparerAble*/ import gplx.stores.*; /*GfoNdeRdr*/
class TdbSelectWkr implements Db_qryWkr {
public Object Exec(Db_engine engineObj, Db_qry cmdObj) {
TdbEngine engine = TdbEngine.cast_(engineObj); Db_qry__select_cmd cmd = (Db_qry__select_cmd)cmdObj;
if (cmd.From().Tbls().Count() > 1) throw Exc_.new_w_type("gplx.tdbs", "joins not supported for tdbs", "sql", cmd.Xto_sql());
TdbTable tbl = engine.FetchTbl(cmd.From().BaseTable().TblName());
GfoNdeList rv = (cmd.Where() == Db_qry_.WhereAll && cmd.Limit() == Db_qry__select_cmd.Limit_disabled) ? rv = tbl.Rows() : FilterRecords(tbl, cmd.Where(), cmd.Limit());
if (cmd.GroupBy() != null)
rv = TdbGroupByWkr.GroupByExec(cmd, rv, tbl);
if (cmd.OrderBy() != null) { // don't use null pattern here; if null ORDER BY, then don't call .Sort on GfoNdeList
ComparerAble comparer = Sql_order_by_sorter.new_((Sql_order_by_itm[])cmd.OrderBy().Flds().To_ary(Sql_order_by_itm.class));
rv.Sort_by(comparer);
}
return GfoNdeRdr_.peers_(rv, false);
}
GfoNdeList FilterRecords(TdbTable tbl, Criteria crt, int limit) {
GfoNdeList rv = GfoNdeList_.new_();
int count = 0;
for (int i = 0; i < tbl.Rows().Count(); i++) {
GfoNde row = (GfoNde)tbl.Rows().FetchAt_asGfoNde(i);
if (crt.Matches(row)) rv.Add(row);
++count;
if (count == limit) break;
}
return rv;
}
public static final TdbSelectWkr _ = new TdbSelectWkr(); TdbSelectWkr() {}
}
class TdbGroupByWkr {
public static GfoNdeList GroupByExec(Db_qry__select_cmd select, GfoNdeList selectRows, TdbTable tbl) {
GfoNdeList rv = GfoNdeList_.new_();
Ordered_hash groupByHash = Ordered_hash_.new_();
List_adp groupByFlds = select.GroupBy().Flds();
GfoFldList selectFldsForNewRow = select.Cols().Flds().XtoGfoFldLst(tbl);
Sql_select_fld_list selectFlds = select.Cols().Flds();
for (int rowIdx = 0; rowIdx < selectRows.Count(); rowIdx++) {
GfoNde selectRow = selectRows.FetchAt_asGfoNde(rowIdx);
GfoNde groupByRow = FindOrNew(selectFldsForNewRow, groupByFlds, selectRow, groupByHash, rv);
for (int i = 0; i < selectFlds.Count(); i++) {
Sql_select_fld_base selectFld = selectFlds.Get_at(i);
Object val = groupByRow.Read(selectFld.Alias()); // groupByRow is keyed by Alias; EX: Count(Id) AS CountOf
groupByRow.WriteAt(i, selectFld.GroupBy_eval(val, selectRow.Read(selectFld.Fld()), selectFld.ValType()));
}
}
return rv;
}
static GfoNde FindOrNew(GfoFldList selectFldsForNewRow, List_adp groupByFlds, GfoNde selectRow, Ordered_hash groupByRows, GfoNdeList rslt) {
int len = groupByFlds.Count();
Ordered_hash curHash = groupByRows;
GfoNde rv = null;
for (int i = 0; i < len; i++) {
String fld = (String)groupByFlds.Get_at(i);
boolean last = i == len - 1;
Object val = selectRow.Read(fld);
Object o = curHash.Get_by(val);
if (last) {
if (o == null) {
Object[] valAry = new Object[selectFldsForNewRow.Count()];
rv = GfoNde_.vals_(selectFldsForNewRow, valAry);
curHash.Add(val, rv);
rslt.Add(rv);
}
else
rv = GfoNde_.as_(o);
}
else {
if (o == null) {
Ordered_hash nextHash = Ordered_hash_.new_();
curHash.Add(val, nextHash);
curHash = nextHash;
}
else {
curHash = (Ordered_hash)o;
}
}
}
return rv;
}
}

View File

@@ -0,0 +1,32 @@
/*
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.engines.tdbs; import gplx.*; import gplx.dbs.*; import gplx.dbs.engines.*;
import gplx.stores.*;
import gplx.stores.xmls.*; /*XmlDataRdr*/
import gplx.stores.dsvs.*; /*DsvDataWtr*/
import gplx.lists.*; /*GfoNdeRdr*/
class TdbStores {
public static final String Dsv = "dsv";
public static final String Xml = "xml";
public static DataRdr rdr_(String text) {return DsvDataRdr_.dsv_(text);}
public static DataWtr wtr_() {return DsvDataWtr_.new_();}
@gplx.Internal protected static DsvStoreLayout FetchLayout(DataRdr rdr) {
GfoNdeRdr ndeRdr = GfoNdeRdr_.as_(rdr); if (ndeRdr == null) return null; // can happen for non-Dsv Rdrs (ex: Xml)
return DsvStoreLayout.as_(ndeRdr.UnderNde().EnvVars().Get_by(DsvStoreLayout.Key_const));
}
}

View File

@@ -0,0 +1,65 @@
/*
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.engines.tdbs; import gplx.*; import gplx.dbs.*; import gplx.dbs.engines.*;
import gplx.*; /*GfoNdeList*/ import gplx.stores.*; import gplx.stores.dsvs.*; /*DsvStoreLayout*/
public class TdbTable {
public int Id() {return id;} int id;
public String Name() {return name;} private String name;
public GfoFldList Flds() {return flds;} GfoFldList flds = GfoFldList_.new_();
public GfoNdeList Rows() {return rows;} GfoNdeList rows = GfoNdeList_.new_();
@gplx.Internal protected TdbFile File() {return file;} TdbFile file;
@gplx.Internal protected boolean IsLoaded() {return isLoaded;} private boolean isLoaded = true;
@gplx.Internal protected boolean IsDirty() {return isDirty;} public void IsDirty_set(boolean v) {isDirty = v;} private boolean isDirty = false;
public static TdbTable new_(int id, String name, TdbFile file) {TdbTable rv = new TdbTable(); rv.ctor(id, name, file); rv.isDirty = true; return rv;} TdbTable() {}
public static TdbTable load_(int id, String name, TdbFile file) {TdbTable rv = new TdbTable(); rv.ctor(id, name, file); rv.isLoaded = false; return rv;}
void ctor(int id, String name, TdbFile file) {
this.id = id; this.name = name; this.file = file;
layout = DsvStoreLayout.dsv_full_();
}
@gplx.Internal protected void DataObj_Wtr(DataWtr wtr) {
wtr.InitWtr(DsvStoreLayout.Key_const, layout);
wtr.WriteTableBgn(name, flds);
for (int rowIdx = 0; rowIdx < rows.Count(); rowIdx++) {
GfoNde drow = rows.FetchAt_asGfoNde(rowIdx);
wtr.WriteLeafBgn("row");
for (int i = 0; i < drow.Flds().Count(); i++)
wtr.WriteData(drow.Flds().Get_at(i).Key(), drow.ReadAt(i));
wtr.WriteLeafEnd();
}
wtr.WriteNodeEnd();
isDirty = false;
}
@gplx.Internal protected void DataObj_Rdr(DataRdr rdr) {
layout = TdbStores.FetchLayout(rdr);
GfoNdeRdr ndeRdr = GfoNdeRdr_.as_(rdr );
if (ndeRdr != null) {
if (ndeRdr.UnderNde() == null) throw Exc_.new_("ndeRdr.UnderNde is null", "name", rdr.NameOfNode());
rows = ndeRdr.UnderNde().Subs();
flds = ndeRdr.UnderNde().SubFlds();
}
else { // XmlRdr needs to load each row again...
throw Exc_.new_invalid_op("TableLoad not implemented").Args_add("rdrType", ClassAdp_.NameOf_obj(rdr), "rdrName", rdr.NameOfNode());
}
isLoaded = true;
}
DsvStoreLayout layout;
public static TdbTable as_(Object obj) {return obj instanceof TdbTable ? (TdbTable)obj : null;}
public static TdbTable cast_(Object obj) {try {return (TdbTable)obj;} catch(Exception exc) {throw Exc_.new_type_mismatch_w_exc(exc, TdbTable.class, obj);}}
}

View File

@@ -0,0 +1,63 @@
/*
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.engines.tdbs; import gplx.*; import gplx.dbs.*; import gplx.dbs.engines.*;
import gplx.lists.*; /*Ordered_hash_base*/ import gplx.stores.dsvs.*; /*DsvStoreLayout*/
public class TdbTableList extends Ordered_hash_base {
public TdbTable Get_by(String name) {return TdbTable.as_(Fetch_base(name));}
public TdbTable Get_by_or_fail(String name) {
TdbTable rv = TdbTable.as_(Get_by(name)); if (rv == null) throw Exc_.new_("could not find table; database file may not exist", "table", name);
return rv;
}
public void Add(TdbTable dataTable) {Add_base(dataTable.Name(), dataTable);}
public static TdbTableList new_(Io_url dbInfo) {
TdbTableList rv = new TdbTableList();
rv.layout = DsvStoreLayout.dsv_full_();
return rv;
}
@gplx.Internal protected void DataObj_Wtr(DataWtr wtr) {
wtr.InitWtr(DsvStoreLayout.Key_const, layout);
wtr.WriteTableBgn(StoreTableName, FldList);
for (Object tblObj : this) {
TdbTable tbl = (TdbTable)tblObj;
wtr.WriteLeafBgn("tbl");
wtr.WriteData(Fld_id, tbl.Id());
wtr.WriteData(Fld_name, tbl.Name());
wtr.WriteData(Fld_file_id, tbl.File().Id());
wtr.WriteLeafEnd();
}
wtr.WriteNodeEnd();
}
@gplx.Internal protected void DataObj_Rdr(DataRdr rdr, TdbFileList files) {
layout = TdbStores.FetchLayout(rdr);
DataRdr subRdr = rdr.Subs();
this.Clear();
while (subRdr.MoveNextPeer()) {
int id = subRdr.ReadInt(Fld_id);
String name = subRdr.ReadStr(Fld_name);
int file_id = subRdr.ReadInt(Fld_file_id);
TdbFile file = files.Get_by_or_fail(file_id);
TdbTable table = TdbTable.load_(id, name, file);
this.Add(table);
}
}
DsvStoreLayout layout;
public static final String StoreTableName = "_tables";
static final String Fld_id = "id"; static final String Fld_name = "name"; static final String Fld_file_id = "file_id";
static final GfoFldList FldList = GfoFldList_.new_().Add(Fld_id, IntClassXtn._).Add(Fld_name, StringClassXtn._).Add(Fld_file_id, IntClassXtn._);
}

View File

@@ -0,0 +1,46 @@
/*
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.engines.tdbs; import gplx.*; import gplx.dbs.*; import gplx.dbs.engines.*;
import gplx.core.criterias.*; import gplx.lists.*; /*GfoNde*/
import gplx.dbs.qrys.*;
class TdbUpdateWkr implements Db_qryWkr {
public Object Exec(Db_engine engineObj, Db_qry cmdObj) {
TdbEngine engine = TdbEngine.cast_(engineObj); Db_qry_update cmd = (Db_qry_update)cmdObj;
int rv = 0;
TdbTable tbl = engine.FetchTbl(cmd.Base_table());
Criteria crt = cmd.Where();
for (int i = 0; i < tbl.Rows().Count(); i++) {
GfoNde row = (GfoNde)tbl.Rows().FetchAt_asGfoNde(i);
if (crt.Matches(row)) {
UpdateRow(cmd, row);
rv++;
}
}
if (rv > 0) tbl.IsDirty_set(true);
return rv;
}
void UpdateRow(Db_qry_update cmd, GfoNde row) {
for (int i = 0; i < cmd.Args().Count(); i++) {
KeyVal p = (KeyVal)cmd.Args().Get_at(i);
Db_arg prm = (Db_arg)p.Val();
row.Write(p.Key(), prm.Val());
}
}
public static TdbUpdateWkr new_() {TdbUpdateWkr rv = new TdbUpdateWkr(); return rv;}
}

View File

@@ -0,0 +1,37 @@
/*
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.engines.tdbs; import gplx.*; import gplx.dbs.*; import gplx.dbs.engines.*;
public class Tdb_conn_info extends Db_conn_info__base {
public Io_url Url() {return url;} Io_url url;
@Override public String Tid() {return Tid_const;} public static final String Tid_const = "tdb";
public static Db_conn_info new_(Io_url url) {
return Db_conn_info_.parse_(Bld_raw
( "gplx_key", Tid_const
, "url", url.Raw()
));
} Tdb_conn_info() {}
@Override public Db_conn_info New_self(String raw, GfoMsg m) {
Tdb_conn_info rv = new Tdb_conn_info();
String urlStr = m.ReadStr("url");
Io_url url = Io_url_.new_any_(urlStr);
rv.Ctor(urlStr, url.NameOnly(), raw, BldApi(m));
rv.url = url;
return rv;
}
public static final Tdb_conn_info _ = new Tdb_conn_info();
}