diff --git a/org.adempiere.base/src/org/compiere/db/AdempiereDatabase.java b/org.adempiere.base/src/org/compiere/db/AdempiereDatabase.java index 3ed231e406..0ed8a09578 100644 --- a/org.adempiere.base/src/org/compiere/db/AdempiereDatabase.java +++ b/org.adempiere.base/src/org/compiere/db/AdempiereDatabase.java @@ -353,6 +353,15 @@ public interface AdempiereDatabase */ public String intersectClauseForCSV(String columnName, String csv); + /** + * Quote column name if necessary (usually to avoid conflict with reserved keywords) + * @param columnName + * @return columnName or quoted columnName + */ + public default String quoteColumnName(String columnName) { + return columnName; + } + /** * * @return true if using native dialect, false if using oracle dialect diff --git a/org.adempiere.base/src/org/compiere/model/MViewComponent.java b/org.adempiere.base/src/org/compiere/model/MViewComponent.java index bd93e39d15..782996d236 100644 --- a/org.adempiere.base/src/org/compiere/model/MViewComponent.java +++ b/org.adempiere.base/src/org/compiere/model/MViewComponent.java @@ -21,6 +21,7 @@ import java.util.List; import java.util.Properties; import org.adempiere.exceptions.AdempiereException; +import org.compiere.util.DB; public class MViewComponent extends X_AD_ViewComponent { @@ -143,9 +144,9 @@ public class MViewComponent extends X_AD_ViewComponent { colSQL = "NULL"; } - sb.append(colSQL); + sb.append(DB.getDatabase().quoteColumnName(colSQL)); if (!colName.equals("*")) - sb.append(" AS ").append(colName); + sb.append(" AS ").append(DB.getDatabase().quoteColumnName(colName)); } sb.append(" ").append(getFromClause()); diff --git a/org.adempiere.base/src/org/compiere/model/PO.java b/org.adempiere.base/src/org/compiere/model/PO.java index ef7f0b204c..95c90b5724 100644 --- a/org.adempiere.base/src/org/compiere/model/PO.java +++ b/org.adempiere.base/src/org/compiere/model/PO.java @@ -1323,7 +1323,12 @@ public abstract class PO { if (i != 0) sql.append(","); - sql.append(p_info.getColumnSQL(i)); // Normal and Virtual Column + String columnSQL = p_info.getColumnSQL(i); + if (!p_info.isVirtualColumn(i)) + { + columnSQL = DB.getDatabase().quoteColumnName(columnSQL); + } + sql.append(columnSQL); // Normal and Virtual Column } sql.append(" FROM ").append(p_info.getTableName()) .append(" WHERE ") @@ -2545,7 +2550,7 @@ public abstract class PO if (changes) sql.append(", "); changes = true; - sql.append(columnName).append("="); + sql.append(DB.getDatabase().quoteColumnName(columnName)).append("="); if (withValues) { @@ -2888,7 +2893,7 @@ public abstract class PO } else doComma = true; - sqlInsert.append(p_info.getColumnName(i)); + sqlInsert.append(DB.getDatabase().quoteColumnName(p_info.getColumnName(i))); // // Based on class of definition, not class of value Class c = p_info.getColumnClass(i); diff --git a/org.adempiere.base/src/org/compiere/model/POInfo.java b/org.adempiere.base/src/org/compiere/model/POInfo.java index 871981c7db..46ca4f9ab5 100644 --- a/org.adempiere.base/src/org/compiere/model/POInfo.java +++ b/org.adempiere.base/src/org/compiere/model/POInfo.java @@ -814,6 +814,8 @@ public class POInfo implements Serializable if (count > 1) sql.append(","); String columnSQL = getColumnSQL(i); + if (!virtual) + columnSQL = DB.getDatabase().quoteColumnName(columnSQL); if (fullyQualified && !virtual) sql.append(getTableName()).append("."); sql.append(columnSQL); // Normal and Virtual Column diff --git a/org.compiere.db.postgresql.provider/src/org/compiere/db/DB_PostgreSQL.java b/org.compiere.db.postgresql.provider/src/org/compiere/db/DB_PostgreSQL.java index d74d412f89..3a1c0b6798 100755 --- a/org.compiere.db.postgresql.provider/src/org/compiere/db/DB_PostgreSQL.java +++ b/org.compiere.db.postgresql.provider/src/org/compiere/db/DB_PostgreSQL.java @@ -35,6 +35,8 @@ import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.sql.Timestamp; +import java.util.Arrays; +import java.util.List; import java.util.Properties; import java.util.Random; import java.util.logging.Level; @@ -135,6 +137,8 @@ public class DB_PostgreSQL implements AdempiereDatabase private Random rand = new Random(); + private static final List reservedKeywords = Arrays.asList("limit","action","old","new"); + /** * Get Database Name * @return database short name @@ -1175,6 +1179,22 @@ public class DB_PostgreSQL implements AdempiereDatabase return builder.toString(); } + @Override + public String quoteColumnName(String columnName) { + if (!isNativeMode()) { + return columnName; + } + + String lowerCase = columnName.toLowerCase(); + if (reservedKeywords.contains(lowerCase)) { + StringBuilder sql = new StringBuilder("\""); + sql.append(lowerCase).append("\""); + return sql.toString(); + } else { + return columnName; + } + } + @Override public String intersectClauseForCSV(String columnName, String csv) { StringBuilder builder = new StringBuilder();