net.ucanaccess.converters.LoadJet Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of ucanaccess Show documentation
Show all versions of ucanaccess Show documentation
An open source pure Java JDBC Driver implementation which allows Java developers and JDBC client programs (e.g., Open Office, Libre Office, Squirrel SQL) to read/write Microsoft Access databases.
/*
Copyright (c) 2012 Marco Amadei.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package net.ucanaccess.converters;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.SQLSyntaxErrorException;
import java.sql.SQLWarning;
import java.sql.Statement;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.hsqldb.error.ErrorCode;
import net.ucanaccess.complex.ComplexBase;
import net.ucanaccess.converters.TypesMap.AccessType;
import net.ucanaccess.ext.FunctionType;
import net.ucanaccess.jdbc.DBReference;
import net.ucanaccess.jdbc.UcanaccessSQLException;
import net.ucanaccess.util.Logger;
import net.ucanaccess.util.Logger.Messages;
import com.healthmarketscience.jackcess.Column;
import com.healthmarketscience.jackcess.DataType;
import com.healthmarketscience.jackcess.Database;
import com.healthmarketscience.jackcess.Index;
import com.healthmarketscience.jackcess.PropertyMap;
import com.healthmarketscience.jackcess.Row;
import com.healthmarketscience.jackcess.Table;
import com.healthmarketscience.jackcess.Database.FileFormat;
import com.healthmarketscience.jackcess.PropertyMap.Property;
import com.healthmarketscience.jackcess.complex.ComplexValueForeignKey;
import com.healthmarketscience.jackcess.impl.ColumnImpl;
import com.healthmarketscience.jackcess.impl.IndexData;
import com.healthmarketscience.jackcess.impl.IndexImpl;
import com.healthmarketscience.jackcess.impl.ColumnImpl.AutoNumberGenerator;
import com.healthmarketscience.jackcess.impl.query.QueryFormat;
import com.healthmarketscience.jackcess.impl.query.QueryImpl;
import com.healthmarketscience.jackcess.query.Query;
public class LoadJet {
private static int namingCounter = 0;
private final class FunctionsLoader {
private HashSet functionsDefinition = new HashSet();
private void addAggregates() {
functionsDefinition.add(getAggregate("LONGVARCHAR", "last"));
functionsDefinition.add(getAggregate("DECIMAL(100,10)", "last"));
functionsDefinition.add(getAggregate("BOOLEAN", "last"));
functionsDefinition.add(getAggregate("TIMESTAMP", "last"));
functionsDefinition.add(getAggregate("LONGVARCHAR", "first"));
functionsDefinition.add(getAggregate("DECIMAL(100,10)", "first"));
functionsDefinition.add(getAggregate("BOOLEAN", "first"));
functionsDefinition.add(getAggregate("TIMESTAMP", "first"));
}
private void addFunction(String functionName, String methodName,
String returnType, String... parTypes) {
StringBuffer funDef = new StringBuffer();
if (DBReference.is2xx()) {
funDef.append("CREATE FUNCTION ").append(functionName)
.append("(");
String comma = "";
for (int i = 0; i < parTypes.length; i++) {
funDef.append(comma).append("par").append(i).append(" ")
.append(parTypes[i]);
comma = ",";
}
funDef.append(")");
funDef.append(" RETURNS ");
funDef.append(returnType);
funDef.append(" LANGUAGE JAVA DETERMINISTIC NO SQL EXTERNAL NAME 'CLASSPATH:");
funDef.append(methodName).append("'");
} else {
funDef.append("CREATE ALIAS ").append(functionName)
.append(" FOR \"").append(methodName).append("\"");
}
functionsDefinition.add(funDef.toString());
}
private void addFunctions(Class> clazz, boolean cswitch) throws SQLException {
Method[] mths = clazz.getDeclaredMethods();
HashMap tmap = TypesMap.getAccess2HsqlTypesMap();
for (Method mth : mths) {
Annotation[] ants = mth.getAnnotations();
for (Annotation ant : ants) {
if (ant.annotationType().equals(FunctionType.class)) {
FunctionType ft = (FunctionType) ant;
String methodName = clazz.getName() + "."
+ mth.getName();
String functionName = ft.functionName();
if (functionName == null)
functionName = methodName;
AccessType[] acts = ft.argumentTypes();
AccessType ret = ft.returnType();
String retTypeName = ret.name();
String returnType = tmap.containsKey(retTypeName) ? tmap
.get(retTypeName) : retTypeName;
if (AccessType.TEXT.equals(ret)) {
returnType += "(255)";
}
String[] args = new String[acts.length];
for (int i = 0; i < args.length; i++) {
String typeName = acts[i].name();
args[i] = tmap.containsKey(typeName) ? tmap
.get(typeName) : typeName;
if (AccessType.TEXT.equals(acts[i])) {
args[i] += "(255)";
}
}
if (ft.namingConflict()) {
SQLConverter.addWAFunctionName(functionName);
functionName += "WA";
}
addFunction(functionName, methodName, returnType, args);
}
}
}
createFunctions();
if(cswitch)
createSwitch();
}
private void resetDefault() throws SQLException {
Class> clazz=Functions.class;
Method[] mths = clazz.getDeclaredMethods();
for (Method mth : mths) {
Annotation[] ants = mth.getAnnotations();
for (Annotation ant : ants) {
if (ant.annotationType().equals(FunctionType.class)) {
FunctionType ft = (FunctionType) ant;
String functionName = ft.functionName();
if (ft.namingConflict()) {
SQLConverter.addWAFunctionName(functionName);
}
}
}
}
}
private void createFunctions() throws SQLException {
for (String functionDef : functionsDefinition) {
try{
exec(functionDef,true);
}catch(SQLException e){
Logger.logParametricWarning(Messages.FUNCTION_ALREADY_ADDED,functionDef);
}
}
functionsDefinition.clear();
}
private void createSwitch() throws SQLException{
DataType[] dtypes=new DataType[]{
DataType.BINARY,
DataType.BOOLEAN,
DataType.SHORT_DATE_TIME,
DataType.INT,
DataType.LONG,
DataType.DOUBLE,
DataType.MONEY,
DataType.NUMERIC,
DataType.COMPLEX_TYPE,
DataType.MEMO
};
for(DataType dtype:dtypes){
String type=" "+TypesMap.map2hsqldb(dtype)+" ";
for(int i=1;i<10;i++){
StringBuffer header=new StringBuffer("CREATE FUNCTION SWITCH( ");
StringBuffer body=new StringBuffer("(CASE ");
String comma="";
for(int j=0; j logs) {
dumpList(logs, false);
}
private void dumpList(List logs, boolean cr) {
String comma = "";
StringBuffer sb = new StringBuffer();
String crs = cr ? System.getProperty("line.separator") : "";
for (String log : logs) {
sb.append(comma).append(log).append(crs);
comma = ", ";
}
Logger.log(sb.toString());
logs.clear();
}
}
private final class TablesLoader {
private static final int HSQL_FK_ALREADY_EXISTS = -ErrorCode.X_42528; // -5528;
private static final int HSQL_UK_ALREADY_EXISTS= -ErrorCode.X_42522;//-5522
private static final int HSQL_NOT_NULL= -ErrorCode.X_23502;
private static final int HSQL_FK_VIOLATION= -ErrorCode.X_23503;
private static final int HSQL_UK_VIOLATION=-ErrorCode.X_23505;
private static final String SYSTEM_SCHEMA = "SYS";
private ArrayList unresolvedTables = new ArrayList();
private ArrayList calculatedFieldsTriggers=new ArrayList();
private LinkedList loadingOrder=new LinkedList();
private HashSet alreadyIndexed=new HashSet();
private HashSet readOnlyTables=new HashSet();
private String commaSeparated(List extends Index.Column> columns,boolean escape) throws SQLException {
String comma = "";
StringBuffer sb = new StringBuffer(" (");
for (Index.Column cd : columns) {
String cl=escape?escapeIdentifier(cd.getColumn()
.getName()):cd.getColumn()
.getName();
sb.append(comma)
.append(cl);
comma = ",";
}
return sb.append(") ").toString();
}
private String schema(String name,boolean systemTable){
if(systemTable){
return SYSTEM_SCHEMA+"."+name;
}
return name;
}
private DataType getReturnType(Column cl) throws IOException{
if(cl.getProperties().get( PropertyMap.EXPRESSION_PROP)==null||cl.getProperties().get(PropertyMap.RESULT_TYPE_PROP)==null)
return null;
byte pos=(Byte) cl.getProperties().get(PropertyMap.RESULT_TYPE_PROP).getValue();
return DataType.fromByte(pos);
}
private String getHsqldbColumnType(Column cl) throws IOException{
String htype ;
DataType dtyp=cl.getType();
DataType rtyp= getReturnType( cl);
boolean calcType=false;
if( rtyp!=null){
dtyp=rtyp;
calcType=true;
}
if( dtyp.equals(DataType.TEXT)){
int ln=ff1997?cl.getLength():cl.getLengthInUnits();
htype="VARCHAR("
+ ln + ")" ;
}
else if(dtyp.equals(DataType.NUMERIC)&&(cl.getScale()>0||calcType)){
if(calcType){
htype="NUMERIC(100 ,4)";
}
else{
htype="NUMERIC("+
(cl.getPrecision()>0?cl.getPrecision():100)+","+
cl.getScale()+")";
}
}
else if(dtyp.equals(DataType.FLOAT)&&calcType){
htype="NUMERIC("+
(cl.getPrecision()>0?cl.getPrecision():100)+","+
4+")";
}
else{
htype=TypesMap.map2hsqldb(dtyp);
}
return htype;
}
private String getCalculatedFieldTrigger(String ntn,Column cl,boolean isCreate) throws IOException, SQLException{
DataType dt=getReturnType(cl);
String fun=null;
if(isNumeric(dt)){
fun="formulaToNumeric";
}else if(isBoolean(dt)){
fun="formulaToBoolean";
}else if(isDate(dt)){
fun="formulaToDate";
}else if(isTextual(dt)){
fun="formulaToText";
}
String call= fun==null?"%s":fun+"(%s,'"+dt.name()+"')";
String ecl=procedureEscapingIdentifier(cl.getName());
String trg=isCreate? "CREATE TRIGGER expr%d before insert ON "+ntn+
" REFERENCING NEW AS newrow FOR EACH ROW "+
" BEGIN ATOMIC "+
" SET newrow."+ecl+" = "+call+
"; END "
:
"CREATE TRIGGER expr%d before update ON "+ntn+
" REFERENCING NEW AS newrow OLD AS OLDROW FOR EACH ROW "+
" BEGIN ATOMIC IF %s THEN "+
" SET newrow."+ecl+" = "+call+
"; ELSEIF newrow."+ecl+" <> oldrow."+ecl
+" THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '"+Logger.getMessage(Messages.TRIGGER_UPDATE_CF_ERR.name())+cl.getName()+"'"
+"; END IF ; END ";
return trg;
}
private boolean isNumeric(DataType dt){
return typeGroup(dt,DataType.NUMERIC,DataType.MONEY,DataType.DOUBLE,DataType.FLOAT,DataType.LONG,DataType.INT,DataType.BYTE);
}
private boolean isDate(DataType dt){
return typeGroup(dt,DataType.SHORT_DATE_TIME);
}
private boolean isBoolean(DataType dt){
return typeGroup(dt,DataType.BOOLEAN);
}
private boolean isTextual(DataType dt){
return typeGroup(dt,DataType.MEMO,DataType.TEXT);
}
private boolean typeGroup(DataType dt,DataType...gr){
for(DataType el:gr){
if(el.equals(dt))return true;
}
return false;
}
private void createSyncrTable(Table t,boolean systemTable) throws SQLException, IOException{
createSyncrTable(t,systemTable, true) ;
}
private void createSyncrTable(Table t,boolean systemTable, boolean constraints) throws SQLException, IOException {
String tn = t.getName();
if(tn.equalsIgnoreCase("DUAL")){
SQLConverter.setDualUsedAsTableName(true);
}
String ntn =SQLConverter.preEscapingIdentifier(tn);
int seq=metadata.newTable(tn, ntn, Metadata.Types.TABLE);
ntn =SQLConverter.completeEscaping(ntn);
ntn =SQLConverter.checkLang(ntn,conn);
ntn =schema(ntn ,systemTable);
StringBuffer sbC = new StringBuffer("CREATE CACHED TABLE ").append(
ntn).append("(");
List extends Column> lc = t.getColumns();
String comma = "";
for (Column cl : lc) {
if("USER".equalsIgnoreCase(cl.getName())){
Logger.logParametricWarning(Messages.USER_AS_COLUMNNAME,t.getName());
}
String expr=getExpression(cl);
if(expr!=null&&constraints){
String tgrI=getCalculatedFieldTrigger(ntn,cl,true);
String tgrU=getCalculatedFieldTrigger(ntn,cl,false);
calculatedFieldsTriggers.add(String.format(tgrI,namingCounter++,SQLConverter.convertFormula(expr)));
String uc=getUpdateConditions(cl);
if(uc.length()>0){
calculatedFieldsTriggers.add(String.format(tgrU,namingCounter++,uc,SQLConverter.convertFormula(expr)));
}
}
String htype= getHsqldbColumnType(cl) ;
String cn=SQLConverter.preEscapingIdentifier(cl.getName());
String ctype=cl.getType().name();
if(cl.isAutoNumber()){
ColumnImpl cli=(ColumnImpl)cl;
AutoNumberGenerator ang=cli.getAutoNumberGenerator();
if(ang.getType().equals(
DataType.LONG))ctype="COUNTER";
}
metadata.newColumn(cl.getName(),cn,ctype,seq);
if(expr!=null&&constraints)
metadata.calculatedField(t.getName(), cl.getName());
cn=SQLConverter.completeEscaping(cn);
cn=SQLConverter.checkLang(cn,conn);
sbC.append(comma)
.append(cn)
.append(" ").append(htype);
PropertyMap pm = cl.getProperties();
Object required = pm.getValue(PropertyMap.REQUIRED_PROP);
if (constraints&&required != null&&
required instanceof Boolean && ((Boolean) required)
) {
sbC.append(" NOT NULL ");
}
comma = ",";
}
sbC.append(")");
exec(sbC.toString(),true);
}
private String getExpression(Column cl) throws IOException {
PropertyMap map=cl.getProperties();
Property exprp=map.get( PropertyMap.EXPRESSION_PROP);
if(exprp!=null){
Table tl=cl.getTable();
String expr= SQLConverter.convertPowOperator((String)exprp.getValue());
for(Column cl1:tl.getColumns()){
expr=expr.replaceAll("\\[(?i)("+Pattern.quote(cl1.getName())+")\\]","newrow.$0");
}
return expr;
}
return null;
}
private String getUpdateConditions(Column cl) throws IOException, SQLException {
PropertyMap map=cl.getProperties();
Property exprp=map.get(PropertyMap.EXPRESSION_PROP);
if(exprp!=null){
Set setu=SQLConverter.getFormulaDependencies(exprp.getValue().toString());
if(setu.size()>0){
String or="";
StringBuffer cw=new StringBuffer();
for(String dep:setu){
dep=escapeIdentifier(dep);
cw.append(or).
append("oldrow.").append(dep).append("<>").append("newrow.").append(dep);
or=" OR ";
}
return cw.toString();
}
}
return " FALSE ";
}
private String procedureEscapingIdentifier(String name) throws SQLException{
return SQLConverter.procedureEscapingIdentifier( escapeIdentifier(name));
}
private void defaultValues(Table t) throws SQLException, IOException {
String tn = t.getName();
String ntn = escapeIdentifier(tn);
List extends Column> lc = t.getColumns();
ArrayList arTrigger = new ArrayList();
for (Column cl : lc) {
PropertyMap pm = cl.getProperties();
String ncn =procedureEscapingIdentifier(cl.getName());
Object defaulT = pm.getValue(PropertyMap.DEFAULT_VALUE_PROP);
if (defaulT != null) {
String cdefaulT = SQLConverter.convertSQL(" "
+ defaulT.toString()).getSql();
if (cdefaulT.trim().startsWith("=")) {
cdefaulT = cdefaulT.trim().substring(1);
}
if (cl.getType().equals(DataType.BOOLEAN)
&& ("=yes".equalsIgnoreCase(cdefaulT) || "yes"
.equalsIgnoreCase(cdefaulT)))
cdefaulT = "true";
if (cl.getType().equals(DataType.BOOLEAN)
&& ("=no".equalsIgnoreCase(cdefaulT) || "no"
.equalsIgnoreCase(cdefaulT)))
cdefaulT = "false";
if(
(cl.getType().equals(DataType.MEMO)||
cl.getType().equals(DataType.TEXT))&&
(!defaulT.toString().startsWith("\"")||
!defaulT.toString().endsWith("\"")
)
){
cdefaulT="'"+cdefaulT.replaceAll("'","''")+"'";
}
String guidExp = "GenGUID()";
if (!guidExp.equals(defaulT)) {
Object defFound=cdefaulT;
boolean isNull=(cdefaulT+"").equalsIgnoreCase("null");
if (!isNull&&(defFound=tryDefault(cdefaulT))==null) {
Logger.logParametricWarning(Messages.UNKNOWN_EXPRESSION,
""+ defaulT, cl.getName(), cl.getTable().getName());
} else {
if(defFound!=null){
metadata.columnDef(cl.getTable().getName(), cl.getName(), defFound.toString());
}
if(cl.getType()==DataType.TEXT
&&
defaulT.toString().startsWith("'")&&defaulT.toString().endsWith("'")&&
defaulT.toString().length()>cl.getLengthInUnits()
){
Logger.logParametricWarning(Messages.DEFAULT_VALUES_DELIMETERS,
""+defaulT,cl.getName(),cl.getTable().getName(),""+cl.getLengthInUnits());
}
arTrigger
.add("CREATE TRIGGER DEFAULT_TRIGGER"
+ (namingCounter++)
+ " BEFORE INSERT ON "
+ ntn
+ " REFERENCING NEW ROW AS NEW FOR EACH ROW IF NEW."
+ ncn + " IS NULL THEN "
+ "SET NEW." + ncn + "= "
+ cdefaulT + " ; END IF");
}
}
}
}
for (String trigger : arTrigger) {
exec(trigger,true);
}
}
private int countFKs() throws IOException{
int i=0;
for (String tn : this.loadingOrder) {
UcanaccessTable table = new UcanaccessTable(dbIO.getTable(tn),tn);
if (!this.unresolvedTables.contains(tn)) {
for (Index idxi : table.getIndexes()) {
// riw
IndexImpl idx = (IndexImpl) idxi;
if (idx.isForeignKey()
&& !idx.getReference().isPrimaryTable())
i++;
}
}
}
return i;
}
private boolean reorder() throws IOException, SQLException {
int maxIteration=countFKs()+1;
for (int i = 0; i < maxIteration; i++) {
boolean change = false;
ArrayList loadingOrder0=new ArrayList();
loadingOrder0.addAll(this.loadingOrder);
for (String tn : loadingOrder0) {
UcanaccessTable table = new UcanaccessTable(dbIO.getTable(tn),tn);
if (!this.unresolvedTables.contains(tn)) {
for (Index idxi : table.getIndexes()) {
// riw
IndexImpl idx = (IndexImpl) idxi;
if (idx.isForeignKey()
&& !idx.getReference().isPrimaryTable()&&!tryReorder(idx))
change = true;
}
}
}
if(!change )return true;
}
return false;
}
private boolean tryReorder(Index idxi) throws IOException{
IndexImpl idx=(IndexImpl)idxi;
String ctn=idx.getTable().getName();
String rtn=idx.getReferencedIndex().getTable().getName();
int ict=this.loadingOrder.indexOf(ctn);
int irt=this.loadingOrder.indexOf(rtn);
if(ict cls=idx.getColumns();
if(cls.size()==1){
this.alreadyIndexed.add(cls.get(0).getColumn());
}
String ntn = escapeIdentifier(ctn);
if(ntn==null)return;
String nin = escapeIdentifier(ctn + "_" + idx.getName());
String colsIdx = commaSeparated(cls,true);
String colsIdxRef = commaSeparated(idx.getReferencedIndex()
.getColumns(),true);
StringBuffer ci = new StringBuffer("ALTER TABLE ").append(ntn);
ci.append(" ADD CONSTRAINT ").append(nin);
String nrt = escapeIdentifier(rtn);
if(nrt==null)return;
ci.append(" FOREIGN KEY ").append(colsIdx).append(" REFERENCES ")
.append(nrt).append(colsIdxRef);
if (idx.getReference().isCascadeDeletes()) {
ci.append(" ON DELETE CASCADE ");
}
if (idx.getReference().isCascadeUpdates()) {
ci.append(" ON UPDATE CASCADE ");
}
try {
exec(ci.toString(),true);
} catch (SQLException e) {
if (e.getErrorCode() == HSQL_FK_ALREADY_EXISTS) {
Logger.log(e.getMessage());
} else
throw e;
}
loadedIndexes.add("FK on " + ntn + " Columns:" + commaSeparated(cls,false)
+ " References " + nrt + " Columns:" + commaSeparated(idx.getReferencedIndex()
.getColumns(),false));
}
private void loadIndex(Index idx,String tn) throws IOException, SQLException {
String ntn = escapeIdentifier(tn);
if(ntn==null)return;
String nin = idx.getName();
nin = escapeIdentifier(tn + "_" + nin);
boolean uk = idx.isUnique();
boolean pk = idx.isPrimaryKey();
if(!uk&&!pk&&idx.getColumns().size()==1){
Column cl=idx.getColumns().get(0).getColumn();
if(this.alreadyIndexed.contains(cl))
return;
}
if(uk&&idx.getColumns().size()==1){
Column cl=idx.getColumns().get(0).getColumn();
DataType dt=cl.getType();
if(dt.equals(DataType.COMPLEX_TYPE))return;
}
StringBuffer ci = new StringBuffer("ALTER TABLE ").append(ntn);
String colsIdx = commaSeparated(idx.getColumns(),true);
if (pk) {
ci.append(" ADD PRIMARY KEY ").append(colsIdx);
} else if (uk) {
ci.append(" ADD CONSTRAINT ").append(nin);
ci.append(" UNIQUE ").append(colsIdx);
} else {
ci = new StringBuffer("CREATE INDEX ").append(nin)
.append(" ON ").append(ntn).append(colsIdx);
}
try {
exec(ci.toString(),true);
}
catch (SQLException e) {
if( HSQL_UK_ALREADY_EXISTS== e.getErrorCode())return ;
if (idx.isUnique()) {
for (Index.Column cd : idx.getColumns()) {
if (cd.getColumn().getType()
.equals(DataType.COMPLEX_TYPE)) {
return;
}
}
}
Logger.logWarning(e.getMessage());
return;
}
catch (Exception e) {
Logger.logWarning(e.getMessage());
return;
}
String pre = pk ? "Primary Key " : uk ? "Index Unique " : "Index";
loadedIndexes.add(pre + " on " + tn + " Columns:" + commaSeparated(idx.getColumns(),false));
}
private void createTable(Table t) throws SQLException, IOException {
createTable(t,false) ;
}
private void dropTable(Table t,boolean systemTable) throws SQLException{
String tn = t.getName();
String ntn =schema( escapeIdentifier(tn),systemTable);
exec("DROP TABLE "+ntn+" CASCADE ",false);
metadata.dropTable(tn);
}
private void makeTableReadOnly(Table t,boolean systemTable) throws SQLException{
String tn = t.getName();
this.readOnlyTables.add(t.getName());
String ntn =schema( escapeIdentifier(tn),systemTable);
exec("SET TABLE "+ntn+" READONLY TRUE ",false);
}
private void recreate(Table t,boolean systemTable,Row record, int errorCode) throws SQLException, IOException{
String type="";
switch(errorCode){
case HSQL_FK_VIOLATION: type="Foreign Key";break;
case HSQL_NOT_NULL: type="Not Null";break;
case HSQL_UK_VIOLATION: type="Unique";break;
}
Logger.logParametricWarning(Messages.CONSTRAINT,type,t.getName(), record.toString(),t.getName() );
dropTable( t,systemTable);
createSyncrTable(t, systemTable,false);
if(errorCode!=HSQL_FK_VIOLATION)
loadTableFKs(t.getName(),false);
loadTableData(t, systemTable);
makeTableReadOnly(t,systemTable);
}
private void createTable(Table t, boolean systemTable) throws SQLException, IOException {
String tn = t.getName();
if (tn.indexOf(" ") > 0) {
SQLConverter.addWhiteSpacedTableNames(tn);
}
String ntn = SQLConverter.escapeIdentifier(tn);//clean
if (ntn == null)
return;
createSyncrTable(t,systemTable);
}
private boolean hasAppendOnly(Table t) {
for (Column c:t.getColumns()){
if(c.isAppendOnly()){
return true;
}
}
return false;
}
private void loadTableData(Table t, boolean systemTable)
throws IOException, SQLException {
PreparedStatement ps = null;
try {
int i = 0;
int step=2000;
Iterator it=t.iterator();
while (it.hasNext()) {
Row row=it.next();
ArrayList