IDEMPIERE-2745 2Pack is not creating foreign keys - foreign key processing needs to be done at the end as the primary keys of related tables can be inexistent when processing columns

This commit is contained in:
Carlos Ruiz 2015-08-17 20:47:03 -05:00
parent ee4814b6ca
commit 0e0589d8be
3 changed files with 65 additions and 24 deletions

View File

@ -25,7 +25,6 @@ import java.util.logging.Level;
import javax.xml.transform.sax.TransformerHandler;
import org.adempiere.exceptions.AdempiereException;
import org.adempiere.pipo2.AbstractElementHandler;
import org.adempiere.pipo2.Element;
import org.adempiere.pipo2.PIPOContext;
@ -81,6 +80,7 @@ public class ColumnElementHandler extends AbstractElementHandler {
if (!mColumn.is_new() && !mColumn.is_Changed()) {
boolean syncDatabase = "Y".equalsIgnoreCase(getStringValue(element, "IsSyncDatabase"));
if (syncDatabase) {
deferFK(element, mColumn);
syncColumn(ctx, mColumn, "Sync", false);
}
return;
@ -111,10 +111,12 @@ public class ColumnElementHandler extends AbstractElementHandler {
}
boolean recreateColumn = (mColumn.is_new()
|| mColumn.is_ValueChanged("AD_Reference_ID")
|| mColumn.is_ValueChanged("FieldLength")
|| mColumn.is_ValueChanged("ColumnName") || mColumn
.is_ValueChanged("IsMandatory"));
|| mColumn.is_ValueChanged(X_AD_Column.COLUMNNAME_AD_Reference_ID)
|| mColumn.is_ValueChanged(X_AD_Column.COLUMNNAME_FieldLength)
|| mColumn.is_ValueChanged(X_AD_Column.COLUMNNAME_ColumnName)
|| mColumn.is_ValueChanged(X_AD_Column.COLUMNNAME_FKConstraintName)
|| mColumn.is_ValueChanged(X_AD_Column.COLUMNNAME_FKConstraintType)
|| mColumn.is_ValueChanged(X_AD_Column.COLUMNNAME_IsMandatory));
//ignore fieldlength change for clob and lob
if (!mColumn.is_ValueChanged("AD_Reference_ID") && mColumn.is_ValueChanged("FieldLength")) {
@ -161,6 +163,7 @@ public class ColumnElementHandler extends AbstractElementHandler {
}
if (recreateColumn || syncDatabase) {
deferFK(element, mColumn);
syncColumn(ctx, mColumn, action, recreateColumn);
}
} else {
@ -168,6 +171,12 @@ public class ColumnElementHandler extends AbstractElementHandler {
}
}
private void deferFK(Element element, MColumn mColumn) {
String foreignTable = mColumn.getReferenceTableName();
if (foreignTable != null && ! "AD_Ref_List".equals(foreignTable))
element.deferFKColumnID = mColumn.getAD_Column_ID();
}
private void syncColumn(PIPOContext ctx, MColumn mColumn, String action,
boolean recreateColumn) throws SAXException {
int success = 0;
@ -229,11 +238,6 @@ public class ColumnElementHandler extends AbstractElementHandler {
if (!rst.next()) {
// table doesn't exist
sql = table.getSQLCreate();
MColumn[] cols = table.getColumns(false);
for (MColumn col : cols)
{
sql += addConstraint(table, md, catalog, schema, tableName, col);
}
} else {
//
rsc = md.getColumns(catalog, schema, tableName, columnName);
@ -249,7 +253,6 @@ public class ColumnElementHandler extends AbstractElementHandler {
// No existing column
sql = column.getSQLAdd(table);
}
sql += addConstraint(table, md, catalog, schema, tableName, column);
}
//execute modify or add if needed
@ -296,19 +299,6 @@ public class ColumnElementHandler extends AbstractElementHandler {
return 1;
}
private String addConstraint(MTable table, DatabaseMetaData md,
String catalog, String schema, String tableName, MColumn col) {
String fkConstraintSql;
try {
fkConstraintSql = MColumn.getForeignKeyConstraintSql(md, catalog, schema, tableName, table, col, false);
} catch (Exception e) {
throw new AdempiereException(e);
}
if (fkConstraintSql != null && fkConstraintSql.length() > 0)
fkConstraintSql = "";
return fkConstraintSql;
}
public void endElement(PIPOContext ctx, Element element) throws SAXException {
}

View File

@ -37,6 +37,8 @@ public class Element {
public Attributes attributes;
//defer for later reprocessing
public boolean defer = false;
//defer for post packin foreign key processing
public int deferFKColumnID = 0;
//parent element
public Element parent;
//resolved db recordid, store for reference by child element

View File

@ -19,6 +19,8 @@
package org.adempiere.pipo2;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
@ -27,13 +29,17 @@ import java.util.Set;
import java.util.Stack;
import java.util.logging.Level;
import org.adempiere.exceptions.AdempiereException;
import org.adempiere.pipo2.exception.DatabaseAccessException;
import org.compiere.model.MColumn;
import org.compiere.model.MTable;
import org.compiere.model.X_AD_Package_Imp;
import org.compiere.model.X_AD_Package_Imp_Inst;
import org.compiere.util.CLogger;
import org.compiere.util.DB;
import org.compiere.util.Env;
import org.compiere.util.Trx;
import org.compiere.util.Util;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.AttributesImpl;
@ -68,6 +74,7 @@ public class PackInHandler extends DefaultHandler {
private IHandlerRegistry handlerRegistry = null;
private List<DeferEntry> defer = new ArrayList<DeferEntry>();
private List<Integer> deferFK = new ArrayList<Integer>();
private Stack<Element> stack = new Stack<Element>();
private PackIn packIn;
private int elementProcessed = 0;
@ -228,6 +235,11 @@ public class PackInHandler extends DefaultHandler {
{
defer.add(new DeferEntry(element, true));
}
if (element.deferFKColumnID > 0)
{
if (! deferFK.contains(element.deferFKColumnID))
deferFK.add(element.deferFKColumnID);
}
for (Element childElement : element.childrens)
{
@ -280,6 +292,9 @@ public class PackInHandler extends DefaultHandler {
if (elementValue.equals("idempiere")){
processDeferElements();
processDeferFKElements();
if (!packageStatus.equals("Completed with errors"))
packageStatus = "Completed successfully";
@ -368,6 +383,40 @@ public class PackInHandler extends DefaultHandler {
} while (defer.size() > 0);
}
private void processDeferFKElements() throws SAXException {
if (deferFK.isEmpty())
return;
for (int columnID : deferFK) {
MColumn column = MColumn.get(m_ctx.ctx, columnID);
try {
Connection conn = m_ctx.trx.getConnection();
DatabaseMetaData md = conn.getMetaData();
String catalog = DB.getDatabase().getCatalog();
String schema = DB.getDatabase().getSchema();
MTable table = MTable.get(m_ctx.ctx, column.getAD_Table_ID());
String tableName = table.getTableName();
String fkConstraintSql = MColumn.getForeignKeyConstraintSql(md, catalog, schema, tableName, table, column, false);
if (! Util.isEmpty(fkConstraintSql)) {
if (fkConstraintSql.indexOf(DB.SQLSTATEMENT_SEPARATOR) == -1) {
DB.executeUpdate(fkConstraintSql, false, m_ctx.trx.getTrxName());
} else {
String statements[] = fkConstraintSql.split(DB.SQLSTATEMENT_SEPARATOR);
for (int i = 0; i < statements.length; i++) {
if (Util.isEmpty(statements[i]))
continue;
DB.executeUpdateEx(statements[i], m_ctx.trx.getTrxName());
}
}
}
} catch (Exception e) {
throw new AdempiereException(e);
}
}
}
public void setCtx(PIPOContext ctx) {
m_ctx = ctx;
}