SqlStorageWriter.java
package hu.ddsi.java.database.JavaSQLImp;
import java.io.Serializable;
import java.sql.Statement;
import java.util.Date;
import java.util.List;
import eu.javaexperience.collection.CollectionTools;
import eu.javaexperience.database.JDBC;
import eu.javaexperience.interfaces.simple.SimpleGetFactory;
import eu.javaexperience.io.SerializationTools;
import eu.javaexperience.text.Format;
import hu.ddsi.java.database.FieldData;
import hu.ddsi.java.database.GenericStorable;
import hu.ddsi.java.database.GenericStorage;
import hu.ddsi.java.database.GenericStoreDataArray;
import hu.ddsi.java.database.GenericStoreDataType;
import hu.ddsi.java.database.GenericStoreDataWriter;
import hu.ddsi.java.database.GenericStoreDatabase;
import hu.ddsi.java.database.GenericStoreException;
import hu.ddsi.java.database.JavaSQLImp.SqlStorageWriter.SQLCuccWriter;
public class SqlStorageWriter extends GenericStoreDataWriter<SqlStorage,SQLCuccWriter>
{
public static class SQLCuccWriter
{
public SQLCuccWriter(SqlStorage st,String cls,boolean update)
{
db = st;
this.cls = cls;
//this.update = update;
}
SqlStorage db;
String cls;
StringBuilder vals = null;
StringBuilder fields = new StringBuilder();
boolean nfirst = false;
boolean update;
private void comma()
{
if(nfirst)
{
if(!update)
fields.append(",");
vals.append(",");
}
else
nfirst = true;
}
}
public SQLCuccWriter newWriter(SqlStorage db, Class cls, boolean update)
{
update = false;
SQLCuccWriter ret = new SQLCuccWriter(db, cls.getName(), update);
if(update)
{
ret.vals = ret.fields;
ret.vals.append("UPDATE ");
ret.vals.append(db.quote);
ret.vals.append(cls.getName());
ret.vals.append(db.quote);
ret.vals.append(" SET ");
}
else
{
ret.vals = new StringBuilder();
}
return ret;
}
@Override
public void writeField(String name, FieldData type, Object value, SQLCuccWriter w) throws Exception
{
w.comma();
w.fields.append(w.db.quote);
w.fields.append(name);
w.fields.append(w.db.quote);
if(w.update)
w.fields.append("=");
putField(w.vals, w.db, type, value);
}
public static void putField(StringBuilder vals, GenericStoreDatabase gdb, FieldData fd, Object value) throws Exception
{
if(value == null)
{
vals.append("null");
return;
}
switch(fd.getDataType())
{
case Date:
vals.append(((Date)value).getTime());
break;
case Boolean:
vals.append(Boolean.TRUE.equals(value)?'1':'0');
break;
case Enum:
vals.append(((Enum<?>)value).ordinal());
break;
case Byte:
case Double:
case Float:
case Integer:
case Long:
case Short:
vals.append(value.toString());
break;
case GenericDataId:
GenericStorable gs = (GenericStorable) value;
if(null != gdb)
{
GenericStorage.storeObject(gs, gdb);
}
vals.append(GenericStorage.getID(gs));
break;
case Char:
case String:
SqlDialect dial = ((SqlStorage)gdb).dialect;
String q = dial.getStringQuote();
vals.append(q);
vals.append(dial.escapeString((String)value));
vals.append(q);
break;
case DontStore:
return;
case Serialized:
case Array:
appendArray(gdb, fd, vals, value);
break;
}
}
protected static void appendArray(GenericStoreDatabase gdb, FieldData type, StringBuilder dst, Object val) throws GenericStoreException
{
if(type.getArrayData().getDataType() == GenericStoreDataType.GenericDataId)
{
val = conventToLongArray((GenericStorable[])val,gdb);
}
dst.append("'");
dst.append(Format.toHex(SerializationTools.serializeIntoBlob((Serializable) val)));
dst.append("'");
}
@Override
public void writeArrayField(String name, GenericStoreDataArray arr,Object value,SQLCuccWriter w) throws Exception
{
w.comma();
w.fields.append(name);
if(w.update)
w.vals.append("=");
//Ez de hulladék megoldás
w.vals.append("'"+Format.toHex(SerializationTools.serializeIntoBlob((Serializable) value))+"'");
}
@Override
public void flushObject(SQLCuccWriter w) throws Exception
{
if(w.update)
{
try(Statement st = w.db.connection.createStatement())
{
st.execute(w.vals.toString());
}
}
else
{
StringBuilder sb = new StringBuilder();
sb.append("REPLACE INTO ");
sb.append(w.db.quote);
sb.append(w.cls);
sb.append(w.db.quote);
sb.append("(");
sb.append(w.fields);
sb.append(")VALUES(");
sb.append(w.vals);
sb.append(");");
try(Statement st = w.db.connection.createStatement())
{
st.execute(sb.toString());
}
}
}
@Override
public void writeID(long id, SQLCuccWriter w) throws Exception
{
if(w.update)
w.vals.append(" WHERE ");
else
w.comma();
w.fields.append(w.db.quote);
w.fields.append("do");
w.fields.append(w.db.quote);
if(w.update)
w.vals.append("=");
w.vals.append(id);
}
protected static void writeStart(StringBuilder sb, String quote, String cls, FieldData[] fds)
{
sb.append("REPLACE INTO ");
sb.append(quote);
sb.append(cls);
sb.append(quote);
sb.append("(`do`");
for(FieldData fd:fds)
{
sb.append(",`");
sb.append(fd.f.getName());
sb.append("`");
}
sb.append(")VALUES");
}
protected static void writeObject(StringBuilder sb, String quote, String cls, FieldData[] fds, GenericStoreDatabase gdb, List<? extends GenericStorable> objects) throws Exception
{
int n = 0;
for(GenericStorable obj:objects)
{
if(++n > 1)
{
sb.append(",");
}
sb.append("(");
sb.append(GenericStorage.getID(obj));
sb.append(",");
int fn = 0;
for(FieldData fd:fds)
{
if(++fn > 1)
{
sb.append(",");
}
putField(sb, gdb, fd, fd.f.get(obj));
}
sb.append(")");
}
}
@Override
public void writeObjects(List<? extends GenericStorable> objects, GenericStoreDatabase _gdb, FieldData[] fds) throws Exception
{
SqlStorage gdb = (SqlStorage) _gdb;
int shardSize = 1000;
if(objects.size() > 0)
{
String quote = gdb.quote;
Class cls = objects.get(0).getClass();
gdb.createStorageForClassIfNeeded(cls, fds);
String clsn = cls.getName();
StringBuilder sb = new StringBuilder();
List<List<GenericStorable>> shards = (List)CollectionTools.shard(objects, shardSize, SimpleGetFactory.getArrayListFactory(), SimpleGetFactory.getArrayListFactory());
for(List<GenericStorable> s:shards)
{
sb.delete(0, sb.length());
if(s.size() > 0)
{
writeStart(sb, gdb.quote, clsn, fds);
writeObject(sb, quote, clsn, fds, gdb, objects);
JDBC.execute(gdb.connection, sb.toString());
}
}
}
}
}