You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@empire-db.apache.org by do...@apache.org on 2022/01/25 21:58:08 UTC
[empire-db] branch version3 updated: EMPIREDB-362 Entity interface
This is an automated email from the ASF dual-hosted git repository.
doebele pushed a commit to branch version3
in repository https://gitbox.apache.org/repos/asf/empire-db.git
The following commit(s) were added to refs/heads/version3 by this push:
new a9fcd0b EMPIREDB-362 Entity interface
a9fcd0b is described below
commit a9fcd0b9d80733f73cb4fee741b31938a9f1458e
Author: Rainer Döbele <do...@apache.org>
AuthorDate: Tue Jan 25 22:58:06 2022 +0100
EMPIREDB-362 Entity interface
---
.../org/apache/empire/samples/db/SampleApp.java | 9 +
.../empire/jsf2/utils/TagEncodingHelper.java | 6 +
.../java/org/apache/empire/data/ColumnExpr.java | 8 +-
.../main/java/org/apache/empire/data/Entity.java | 12 +
.../org/apache/empire/data/bean/BeanClass.java | 34 ++-
.../org/apache/empire/data/bean/BeanProperty.java | 11 +
.../org/apache/empire/data/list/DataListEntry.java | 285 +++++++++++++++++++++
.../org/apache/empire/data/list/DataListHead.java | 155 +++++++++++
.../java/org/apache/empire/db/DBColumnExpr.java | 10 +
.../main/java/org/apache/empire/db/DBCommand.java | 16 +-
.../main/java/org/apache/empire/db/DBRowSet.java | 6 +-
.../main/java/org/apache/empire/db/DBUtils.java | 114 ++++++++-
.../apache/empire/db/expr/column/DBAliasExpr.java | 60 +++--
.../empire/db/expr/compare/DBCompareColExpr.java | 4 +-
.../empire/dbms/oracle/DBMSHandlerOracle.java | 2 +-
.../empire/dbms/oracle/OracleDBModelChecker.java | 20 +-
.../empire/dbms/sqlserver/DBMSHandlerMSSQL.java | 2 +-
.../empire/dbms/sqlserver/MSSqlDBModelChecker.java | 3 +-
.../exceptions/UnsupportedTypeException.java | 15 ++
19 files changed, 704 insertions(+), 68 deletions(-)
diff --git a/empire-db-examples/empire-db-example-basic/src/main/java/org/apache/empire/samples/db/SampleApp.java b/empire-db-examples/empire-db-example-basic/src/main/java/org/apache/empire/samples/db/SampleApp.java
index 2fc7d42..91d6b3a 100644
--- a/empire-db-examples/empire-db-example-basic/src/main/java/org/apache/empire/samples/db/SampleApp.java
+++ b/empire-db-examples/empire-db-example-basic/src/main/java/org/apache/empire/samples/db/SampleApp.java
@@ -27,6 +27,7 @@ import java.util.List;
import org.apache.empire.commons.StringUtils;
import org.apache.empire.data.bean.BeanResult;
+import org.apache.empire.data.list.DataListEntry;
import org.apache.empire.db.DBColumnExpr;
import org.apache.empire.db.DBCommand;
import org.apache.empire.db.DBContext;
@@ -625,6 +626,14 @@ public class SampleApp
cmd.where(EMP.LASTNAME.length().isGreaterThan(0));
// Order by
cmd.orderBy(EMPLOYEE_FULLNAME);
+
+ /*
+ List<DataListEntry> list = context.getUtils().queryDataList(cmd);
+ for (DataListEntry dle : list)
+ {
+ System.out.println(dle.toString());
+ }
+ */
/*
* Example for limitRows() and skipRows()
diff --git a/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/utils/TagEncodingHelper.java b/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/utils/TagEncodingHelper.java
index 8c8f01c..eb999cb 100644
--- a/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/utils/TagEncodingHelper.java
+++ b/empire-db-jsf2/src/main/java/org/apache/empire/jsf2/utils/TagEncodingHelper.java
@@ -149,6 +149,12 @@ public class TagEncodingHelper implements NamingContainer
}
@Override
+ public ColumnExpr unwrap()
+ {
+ return expr.unwrap();
+ }
+
+ @Override
public double getSize()
{
return 0;
diff --git a/empire-db/src/main/java/org/apache/empire/data/ColumnExpr.java b/empire-db/src/main/java/org/apache/empire/data/ColumnExpr.java
index a045c87..e092a54 100644
--- a/empire-db/src/main/java/org/apache/empire/data/ColumnExpr.java
+++ b/empire-db/src/main/java/org/apache/empire/data/ColumnExpr.java
@@ -26,7 +26,6 @@ import org.apache.empire.commons.Options;
*/
public interface ColumnExpr
{
-
/**
* Returns the column's data type.
* @see DataType
@@ -78,5 +77,10 @@ public interface ColumnExpr
* @return the column on which this expression is based or null if not applicable.
*/
Column getSourceColumn();
-
+
+ /**
+ * This helper function unwraps an alias expression
+ * @return the original expresion before renaming
+ */
+ ColumnExpr unwrap();
}
diff --git a/empire-db/src/main/java/org/apache/empire/data/Entity.java b/empire-db/src/main/java/org/apache/empire/data/Entity.java
new file mode 100644
index 0000000..7344fbf
--- /dev/null
+++ b/empire-db/src/main/java/org/apache/empire/data/Entity.java
@@ -0,0 +1,12 @@
+package org.apache.empire.data;
+
+import java.util.List;
+
+public interface Entity
+{
+ String getName();
+
+ List<? extends Column> getColumns();
+
+ Column[] getKeyColumns();
+}
diff --git a/empire-db/src/main/java/org/apache/empire/data/bean/BeanClass.java b/empire-db/src/main/java/org/apache/empire/data/bean/BeanClass.java
index 443efbf..d945199 100644
--- a/empire-db/src/main/java/org/apache/empire/data/bean/BeanClass.java
+++ b/empire-db/src/main/java/org/apache/empire/data/bean/BeanClass.java
@@ -24,7 +24,7 @@ import java.util.List;
import org.apache.empire.data.Column;
import org.apache.empire.data.DataType;
-
+import org.apache.empire.data.Entity;
/**
* BeanObject
@@ -33,7 +33,7 @@ import org.apache.empire.data.DataType;
* A metadata definition consists primarily of the class name and a list of properties.
* @author Rainer
*/
-public abstract class BeanClass
+public abstract class BeanClass implements Entity
{
private final String name;
private final List<BeanProperty> properties = new ArrayList<BeanProperty>();
@@ -102,12 +102,33 @@ public abstract class BeanClass
* returns the name of this class
* @return the class name
*/
+ @Override
public String getName()
{
return name;
}
/**
+ * returns the list of key columns (if any)
+ * @return the list of key columns or null.
+ */
+ @Override
+ public List<BeanProperty> getColumns()
+ {
+ return Collections.unmodifiableList(this.properties);
+ }
+
+ /**
+ * returns the list of key columns (if any)
+ * @return the list of key columns or null.
+ */
+ @Override
+ public Column[] getKeyColumns()
+ {
+ return keyColumns;
+ }
+
+ /**
* returns the list of properties for this class.
* @return the list of properties for this class.
*/
@@ -124,13 +145,4 @@ public abstract class BeanClass
{
return domain;
}
-
- /**
- * returns the list of key columns (if any)
- * @return the list of key columns or null.
- */
- public Column[] getKeyColumns()
- {
- return keyColumns;
- }
}
diff --git a/empire-db/src/main/java/org/apache/empire/data/bean/BeanProperty.java b/empire-db/src/main/java/org/apache/empire/data/bean/BeanProperty.java
index c38d3d2..b417375 100644
--- a/empire-db/src/main/java/org/apache/empire/data/bean/BeanProperty.java
+++ b/empire-db/src/main/java/org/apache/empire/data/bean/BeanProperty.java
@@ -22,6 +22,7 @@ import org.apache.empire.commons.Attributes;
import org.apache.empire.commons.ObjectUtils;
import org.apache.empire.commons.Options;
import org.apache.empire.data.Column;
+import org.apache.empire.data.ColumnExpr;
import org.apache.empire.data.DataType;
import org.apache.empire.db.exceptions.FieldNotNullException;
@@ -198,6 +199,16 @@ public class BeanProperty implements Column
return this;
}
+ /**
+ * This helper function unwraps an alias expression
+ * @return the original expresion before renaming
+ */
+ @Override
+ public ColumnExpr unwrap()
+ { // Nothing to unwrap
+ return this;
+ }
+
// --- Column interface implementation ---
@Override
diff --git a/empire-db/src/main/java/org/apache/empire/data/list/DataListEntry.java b/empire-db/src/main/java/org/apache/empire/data/list/DataListEntry.java
new file mode 100644
index 0000000..b10e546
--- /dev/null
+++ b/empire-db/src/main/java/org/apache/empire/data/list/DataListEntry.java
@@ -0,0 +1,285 @@
+/*
+ * ESTEAM Software GmbH, 25.01.2022
+ */
+package org.apache.empire.data.list;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.Collection;
+import java.util.Date;
+
+import org.apache.empire.commons.ObjectUtils;
+import org.apache.empire.commons.StringUtils;
+import org.apache.empire.data.Column;
+import org.apache.empire.data.ColumnExpr;
+import org.apache.empire.data.Entity;
+import org.apache.empire.data.RecordData;
+import org.apache.empire.exceptions.InvalidArgumentException;
+import org.apache.empire.exceptions.ItemNotFoundException;
+import org.apache.empire.exceptions.NotImplementedException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class DataListEntry implements RecordData, Serializable
+{
+ /**
+ * Comment for <code>serialVersionUID</code>
+ */
+ private static final long serialVersionUID = 1L;
+
+ private static final Logger log = LoggerFactory.getLogger(DataListEntry.class);
+
+ protected final DataListHead<? extends DataListEntry> head;
+ protected final int rownum;
+ protected final Object values[];
+
+ public DataListEntry(DataListHead<? extends DataListEntry> head, int rownum, Object values[])
+ {
+ this.head = head;
+ this.rownum = rownum;
+ this.values = values;
+ }
+
+ public Object[] getKey(Entity entity)
+ {
+ Column[] keyColumns = entity.getKeyColumns();
+ Object[] key = new Object[keyColumns.length];
+ for (int i=0; i<key.length; i++)
+ key[i] = this.getValue(keyColumns[i]);
+ return key;
+ }
+
+ public int getId(Entity entity)
+ {
+ Column[] keyColumns = entity.getKeyColumns();
+ if (keyColumns.length!=1)
+ throw new InvalidArgumentException("entity", entity.getName());
+ // return id
+ return ObjectUtils.getInteger(getValue(keyColumns[0]));
+ }
+
+ public boolean compareKey(Column[] keyColumns, Object[] keyValues)
+ {
+ for (int i=0; i<keyColumns.length; i++)
+ { // find field
+ int index = getFieldIndex(keyColumns[i]);
+ if (index<0)
+ throw new ItemNotFoundException(keyColumns[i].getName());
+ // compare
+ if (!ObjectUtils.compareEqual(values[index], keyValues[i]))
+ return false; // not equal
+ }
+ // found
+ return true;
+ }
+
+ public void updateData(RecordData recData)
+ {
+ ColumnExpr[] cols = head.getColumns();
+ for (int i=0; i<cols.length; i++)
+ {
+ ColumnExpr col = cols[i].unwrap();
+ // must be a column!
+ if (!(col instanceof Column))
+ { // not a true column
+ log.info("Column expression {} is not a column. Skipping update.", col.getName());
+ continue;
+ }
+ int ri = recData.getFieldIndex(col);
+ if (ri<0)
+ continue;
+ // update
+ try {
+ values[i] = recData.getValue(ri);
+ } catch(Exception e) {
+ log.error("Failed to update value for column {}", cols[i].getName());
+ }
+ }
+ }
+
+ public void modifyValue(ColumnExpr col, Object value)
+ {
+ int i = getFieldIndex(col);
+ if (i<0)
+ throw new ItemNotFoundException(col);
+ // update
+ values[i] = value;
+ }
+
+ public int getRownum()
+ {
+ return rownum;
+ }
+
+ public String val(String name)
+ {
+ int idx = getFieldIndex(name);
+ return head.formatValue(idx, values[idx]);
+ }
+
+ public String val(ColumnExpr col)
+ {
+ int idx = getFieldIndex(col);
+ return head.formatValue(idx, values[idx]);
+ }
+
+ @Override
+ public int getFieldCount()
+ {
+ return head.columns.length;
+ }
+
+ @Override
+ public int getFieldIndex(ColumnExpr column)
+ {
+ return head.getColumnIndex(column);
+ }
+
+ @Override
+ public int getFieldIndex(String column)
+ {
+ return head.getColumnIndex(column);
+ }
+
+ @Override
+ public ColumnExpr getColumnExpr(int i)
+ {
+ return head.columns[i];
+ }
+
+ @Override
+ public Object getValue(int index)
+ {
+ if (index<0 || index>=values.length)
+ throw new InvalidArgumentException("index", index);
+ return values[index];
+ }
+
+ @Override
+ public Object getValue(ColumnExpr column)
+ {
+ return getValue(getFieldIndex(column));
+ }
+
+ @Override
+ public boolean isNull(int index)
+ {
+ return ObjectUtils.isEmpty(values[index]);
+ }
+
+ @Override
+ public boolean isNull(ColumnExpr column)
+ {
+ return isNull(getFieldIndex(column));
+ }
+
+ @Override
+ public int setBeanProperties(Object bean, Collection<? extends ColumnExpr> ignoreList)
+ {
+ throw new NotImplementedException(this, "setBeanProperties");
+ }
+
+ @Override
+ public int setBeanProperties(Object bean)
+ {
+ return setBeanProperties(bean, null);
+ }
+
+ /*
+ * Additional
+ */
+
+ public String getString(int index)
+ { // Get String value
+ Object o = getValue(index);
+ return StringUtils.toString(o);
+ }
+
+ public final String getString(ColumnExpr column)
+ {
+ return getString(getFieldIndex(column));
+ }
+
+ public int getInt(int index)
+ { // Get Integer value
+ Object o = getValue(index);
+ return ObjectUtils.getInteger(o);
+ }
+
+ public final int getInt(ColumnExpr column)
+ {
+ return getInt(getFieldIndex(column));
+ }
+
+ public BigDecimal getDecimal(int index)
+ { // Get Integer value
+ Object o = getValue(index);
+ return ObjectUtils.getDecimal(o);
+ }
+
+ public final BigDecimal getDecimal(ColumnExpr column)
+ {
+ return getDecimal(getFieldIndex(column));
+ }
+
+ public boolean getBoolean(int index)
+ { // Get Integer value
+ Object o = getValue(index);
+ return ObjectUtils.getBoolean(o);
+ }
+
+ public final boolean getBoolean(ColumnExpr column)
+ {
+ return getBoolean(getFieldIndex(column));
+ }
+
+ public <T extends Enum<?>> T getEnum(int index, Class<T> enumType)
+ { // check for null
+ if (isNull(index))
+ return null;
+ // check column data type
+ ColumnExpr col = getColumnExpr(index);
+ boolean numeric = col.getDataType().isNumeric();
+ return ObjectUtils.getEnum(enumType, (numeric ? getInt(index) : getValue(index)));
+ }
+
+ public final <T extends Enum<?>> T getEnum(ColumnExpr column, Class<T> enumType)
+ {
+ return getEnum(getFieldIndex(column), enumType);
+ }
+
+ @SuppressWarnings("unchecked")
+ public final <T extends Enum<?>> T getEnum(Column column)
+ {
+ Class<T> enumType = (Class<T>)column.getEnumType();
+ if (enumType==null)
+ { // Not an enum column (Attribute "enumType" has not been set)
+ throw new InvalidArgumentException("column", column);
+ }
+ return getEnum(getFieldIndex(column), enumType);
+ }
+
+ public Date getDate(int index)
+ {
+ Object o = getValue(index);
+ return ObjectUtils.getDate(o);
+ }
+
+ public final Date getDate(ColumnExpr column)
+ {
+ return getDate(getFieldIndex(column));
+ }
+
+ @Override
+ public String toString()
+ {
+ StringBuilder b = new StringBuilder();
+ for (int i=0; i<values.length; i++)
+ {
+ b.append(head.formatValue(i, values[i]));
+ b.append(head.columnSeparator);
+ }
+ return b.toString();
+ }
+
+}
diff --git a/empire-db/src/main/java/org/apache/empire/data/list/DataListHead.java b/empire-db/src/main/java/org/apache/empire/data/list/DataListHead.java
new file mode 100644
index 0000000..d6e92d5
--- /dev/null
+++ b/empire-db/src/main/java/org/apache/empire/data/list/DataListHead.java
@@ -0,0 +1,155 @@
+/*
+ * ESTEAM Software GmbH, 25.01.2022
+ */
+package org.apache.empire.data.list;
+
+import java.io.Serializable;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+
+import org.apache.empire.commons.ObjectUtils;
+import org.apache.empire.commons.Options;
+import org.apache.empire.commons.StringUtils;
+import org.apache.empire.data.ColumnExpr;
+import org.apache.empire.data.RecordData;
+import org.apache.empire.exceptions.InternalException;
+import org.apache.empire.exceptions.InvalidArgumentException;
+import org.apache.empire.exceptions.NotSupportedException;
+import org.apache.empire.exceptions.UnsupportedTypeException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class DataListHead<T extends DataListEntry> implements Serializable
+{
+ private static final long serialVersionUID = 1L;
+ private static final Logger log = LoggerFactory.getLogger(DataListHead.class);
+
+ final Constructor<T> constructor;
+ final ColumnExpr[] columns;
+
+ protected String columnSeparator = "\t";
+
+ public DataListHead(Class<T> listEntryClass, ColumnExpr[] columns)
+ {
+ if (listEntryClass!=null)
+ { try
+ { // Find the constructor
+ this.constructor = listEntryClass.getDeclaredConstructor(DataListHead.class, int.class, Object[].class);
+ }
+ catch (NoSuchMethodException e)
+ {
+ throw new UnsupportedTypeException(listEntryClass);
+ }
+ catch (SecurityException e)
+ {
+ throw new UnsupportedTypeException(listEntryClass);
+ }
+ }
+ else
+ { // Must override newEntry for this to work
+ this.constructor = null;
+ }
+ this.columns = columns;
+ }
+
+ public ColumnExpr[] getColumns()
+ {
+ return columns;
+ }
+
+ public int getColumnIndex(ColumnExpr column)
+ {
+ for (int i=0; i<columns.length; i++)
+ if (columns[i]==column)
+ return i;
+ // Not found, try by name
+ return getColumnIndex(column.getName());
+ }
+
+ public int getColumnIndex(String columnName)
+ {
+ for (int i=0; i<columns.length; i++)
+ if (columnName.equalsIgnoreCase(columns[i].getName()))
+ return i;
+ // Not found
+ log.warn("Column \"{}\" not found in DataListEntry!", columnName);
+ return -1;
+ }
+
+ public T newEntry(int rownum, Object[] values)
+ { try
+ { // check
+ if (columns.length!=values.length)
+ throw new InvalidArgumentException("values", values);
+ // must override newEntry if no listEntryClass is provided
+ if (constructor==null)
+ throw new NotSupportedException(this, "newEntry");
+ // create item
+ return constructor.newInstance(this, rownum, values);
+ }
+ catch (InstantiationException e)
+ {
+ throw new InternalException(e);
+ }
+ catch (IllegalAccessException e)
+ {
+ throw new InternalException(e);
+ }
+ catch (IllegalArgumentException e)
+ {
+ throw new InternalException(e);
+ }
+ catch (InvocationTargetException e)
+ {
+ throw new InternalException(e);
+ }
+ }
+
+ public final T newEntry(int rownum, RecordData data)
+ { // check
+ if (columns.length!=data.getFieldCount())
+ throw new InvalidArgumentException("data", data);
+ // copy values
+ Object[] values = new Object[columns.length];
+ for (int i=0; i<columns.length; i++)
+ values[i] = data.getValue(i);
+ // create
+ return newEntry(rownum, values);
+ }
+
+ public String formatValue(int idx, Object value)
+ { // check empty
+ if (ObjectUtils.isEmpty(value))
+ return StringUtils.EMPTY;
+ // check options
+ Options options = columns[idx].getOptions();
+ if (options!=null && options.has(value))
+ { // lookup option
+ value = options.get(value);
+ }
+ // Escape
+ return escape(String.valueOf(value));
+ }
+
+ /**
+ * Escapes the formatted value
+ * Default is a simple HTML escape
+ */
+ protected String escape(String text)
+ {
+ if (text==null || text.length()==0)
+ return StringUtils.EMPTY;
+ // &
+ if (text.indexOf('&')>=0)
+ text = StringUtils.replaceAll(text, "&", "&");
+ // <
+ if (text.indexOf('<')>=0)
+ text = StringUtils.replaceAll(text, "<", "<");
+ // >
+ if (text.indexOf('>')>=0)
+ text = StringUtils.replaceAll(text, ">", ">");
+ // done
+ return text;
+ }
+
+}
diff --git a/empire-db/src/main/java/org/apache/empire/db/DBColumnExpr.java b/empire-db/src/main/java/org/apache/empire/db/DBColumnExpr.java
index 55b084d..7192abc 100644
--- a/empire-db/src/main/java/org/apache/empire/db/DBColumnExpr.java
+++ b/empire-db/src/main/java/org/apache/empire/db/DBColumnExpr.java
@@ -110,6 +110,16 @@ public abstract class DBColumnExpr extends DBExpr
public abstract Element addXml(Element parent, long flags);
/**
+ * This helper function unwraps an alias expression
+ * @return the original expresion before renaming
+ */
+ @Override
+ public DBColumnExpr unwrap()
+ { // Noting to unwrap
+ return this;
+ }
+
+ /**
* Returns the value of a column attribute.
* Column attributes are used to provide metadata for a column.
*
diff --git a/empire-db/src/main/java/org/apache/empire/db/DBCommand.java b/empire-db/src/main/java/org/apache/empire/db/DBCommand.java
index 39862e5..8928be6 100644
--- a/empire-db/src/main/java/org/apache/empire/db/DBCommand.java
+++ b/empire-db/src/main/java/org/apache/empire/db/DBCommand.java
@@ -369,6 +369,20 @@ public abstract class DBCommand extends DBCommandExpr
}
/**
+ * Checks whether or not there are any aggregate functions in the Select
+ * @return true if at least on of the selected expressions is an aggregate
+ */
+ public boolean hasAggegation()
+ {
+ for (DBColumnExpr expr : this.select)
+ {
+ if (expr.isAggregate())
+ return true;
+ }
+ return false;
+ }
+
+ /**
* returns true if prepared statements are enabled for this database
*/
protected boolean isPreparedStatementsEnabled()
@@ -985,7 +999,7 @@ public abstract class DBCommand extends DBCommandExpr
* @return an array of all DBColumnExpr objects or <code>null</code> if there is nothing to select
*/
@Override
- protected DBColumnExpr[] getSelectExprList()
+ public DBColumnExpr[] getSelectExprList()
{
int count = (select != null) ? select.size() : 0;
if (count < 1)
diff --git a/empire-db/src/main/java/org/apache/empire/db/DBRowSet.java b/empire-db/src/main/java/org/apache/empire/db/DBRowSet.java
index 897cd7d..bef4ede 100644
--- a/empire-db/src/main/java/org/apache/empire/db/DBRowSet.java
+++ b/empire-db/src/main/java/org/apache/empire/db/DBRowSet.java
@@ -32,6 +32,7 @@ import org.apache.empire.commons.ObjectUtils;
import org.apache.empire.commons.StringUtils;
import org.apache.empire.data.Column;
import org.apache.empire.data.DataType;
+import org.apache.empire.data.Entity;
import org.apache.empire.db.DBRelation.DBCascadeAction;
import org.apache.empire.db.DBRelation.DBReference;
import org.apache.empire.db.exceptions.FieldIsReadOnlyException;
@@ -64,7 +65,7 @@ import org.slf4j.LoggerFactory;
*
*
*/
-public abstract class DBRowSet extends DBExpr
+public abstract class DBRowSet extends DBExpr implements Entity
{
// *Deprecated* private static final long serialVersionUID = 1L;
@@ -227,6 +228,7 @@ public abstract class DBRowSet extends DBExpr
// ------- Abstract Methods -------
+ @Override
public abstract String getName();
public abstract String getAlias();
@@ -275,6 +277,7 @@ public abstract class DBRowSet extends DBExpr
* <P>
* @return all columns of this rowset
*/
+ @Override
public List<DBColumn> getColumns()
{
return Collections.unmodifiableList(columns);
@@ -360,6 +363,7 @@ public abstract class DBRowSet extends DBExpr
*
* @return an array of all primary key columns
*/
+ @Override
public DBColumn[] getKeyColumns()
{
return ((primaryKey != null) ? primaryKey.getColumns() : null);
diff --git a/empire-db/src/main/java/org/apache/empire/db/DBUtils.java b/empire-db/src/main/java/org/apache/empire/db/DBUtils.java
index 8bf06dd..2098c04 100644
--- a/empire-db/src/main/java/org/apache/empire/db/DBUtils.java
+++ b/empire-db/src/main/java/org/apache/empire/db/DBUtils.java
@@ -29,7 +29,10 @@ public class DBUtils implements DBContextAware
protected static final Logger log = LoggerFactory.getLogger(DBDatabase.class);
// Threshold for long running queries in milliseconds
- protected long longRunndingStmtThreshold = 30000;
+ protected static long longRunndingStmtThreshold = 30000;
+ // Max-Rows for list queries
+ protected static int MAX_QUERY_ROWS = 999;
+
// the context
protected final DBContext context;
// the dbms
@@ -605,4 +608,113 @@ public class DBUtils implements DBContextAware
}
}
+ /**
+ * Crates a default DataListHead for a DataListEntry class
+ * The DataListEntry class must provide the following constructor
+ * DataListEntry(DataListHead<? extends DataListEntry> head, int rownum, Object values[])
+ * @param entryClass the entryClass for which to create the list head
+ * @return
+ protected <T extends DataListEntry> DataListHead<T> createDefaultDataListHead(DBCommand cmd, Class<T> entryClass)
+ {
+ return new DataListHead<T>(entryClass, cmd.getSelectExprList());
+ }
+ */
+
+ /**
+ * Executes a query and returns a list of DataListEntry items
+ * @param sqlCmd the SQL-Command for the query
+ * @param listHead the HeadInfo to be used for each list item
+ * @param first the number of records to skip from the beginning of the result
+ * @param pageSize the maximum number of item to return
+ * @return the list
+ public <T extends DataListEntry<?>> List<T> queryDataList(DBCommand cmd, DataListHead<T> listHead, int first, int pageSize)
+ {
+ DBReader r = new DBReader(context);
+ try
+ { // check pageSize
+ if (pageSize==0)
+ { log.warn("PageSize must not be 0. Setting to -1 for all records!");
+ pageSize = -1;
+ }
+ // set range
+ DBMSHandler dbms = cmd.getDatabase().getDbms();
+ if (pageSize>0 && dbms.isSupported(DBMSFeature.QUERY_LIMIT_ROWS))
+ { // let the database limit the rows
+ if (first>0 && dbms.isSupported(DBMSFeature.QUERY_SKIP_ROWS))
+ { // let the database skip the rows
+ cmd.skipRows(first);
+ // no need to skip rows
+ first = 0;
+ }
+ cmd.limitRows(first+pageSize);
+ }
+ // Runquery
+ r.open(cmd);
+ if (first>0)
+ { // skip rows
+ r.skipRows(first);
+ }
+ // Create a list of data entries
+ int maxCount = (pageSize>=0) ? pageSize : MAX_QUERY_ROWS;
+ ArrayList<T> list = new ArrayList<T>((pageSize>=0) ? pageSize : 10);
+ // add data
+ int rownum = 0;
+ while (r.moveNext() && maxCount != 0)
+ { // Create bean an init
+ T entry = listHead.newEntry(++rownum, r);
+ // add entry
+ list.add(entry);
+ // Decrease count
+ if (maxCount > 0)
+ maxCount--;
+ }
+ // check
+ if (rownum==MAX_QUERY_ROWS)
+ {
+ log.warn("********************************************************");
+ log.warn("Query Result was limited to {} by MAX_QUERY_ROWS", rownum);
+ log.warn("********************************************************");
+ }
+ return list;
+ }
+ finally
+ {
+ r.close();
+ }
+ }
+ */
+
+ /**
+ * Queries a list of DataListEntry items
+ public final <T extends DataListEntry<?>> List<T> queryDataList(DBCommand cmd, Class<T> entryClass)
+ {
+ return queryDataList(cmd, createDefaultDataListHead(cmd, entryClass), 0, -1);
+ }
+ */
+
+ /**
+ * Queries a list of DataListEntry items
+ public final List<DataListEntry> queryDataList(DBCommand cmd)
+ {
+ return queryDataList(cmd, DataListEntry.class);
+ }
+ */
+
+ /**
+ * Queries a single DataListEntry item
+ public final <T extends DataListEntry<?>> T queryDataEntry(DBCommand cmd, Class<T> entryClass)
+ {
+ List<T> dle = queryDataList(cmd, createDefaultDataListHead(cmd, entryClass), 0, 1);
+ return (dle.isEmpty() ? null : dle.get(0));
+ }
+ */
+
+ /**
+ * Queries a single DataListEntry item
+ public final DataListEntry<?> queryDataEntry(DBCommand cmd)
+ {
+ return queryDataEntry(cmd, DataListEntry.class);
+ }
+ */
+
}
diff --git a/empire-db/src/main/java/org/apache/empire/db/expr/column/DBAliasExpr.java b/empire-db/src/main/java/org/apache/empire/db/expr/column/DBAliasExpr.java
index b21ac62..f13310b 100644
--- a/empire-db/src/main/java/org/apache/empire/db/expr/column/DBAliasExpr.java
+++ b/empire-db/src/main/java/org/apache/empire/db/expr/column/DBAliasExpr.java
@@ -30,9 +30,6 @@ import org.apache.empire.dbms.DBMSHandler;
import org.apache.empire.dbms.DBSqlPhrase;
import org.w3c.dom.Element;
-// XML
-
-
/**
* This class allows column renaming in SQL.
* <P>
@@ -97,42 +94,25 @@ public class DBAliasExpr extends DBColumnExpr
}
/**
- * This helper function returns the underlying column expression.
- *
- * @return the underlying column expression
- */
- public DBColumnExpr getExpr()
- {
- return expr;
- }
-
- /**
- * This function set the alias name to the XML tag.
+ * Returns the DBColunm object.
*
- * @return the XML tag (with the alias name)
+ * @return the DBColunm object
*/
@Override
- public Element addXml(Element parent, long flags)
- { // Set name to Alias
- Element field = expr.addXml(parent, flags);
- if (field != null)
- { // Set Name
- if (field.hasAttribute("name"))
- field.setAttribute("source", StringUtils.toString(field.getAttribute("name")));
- field.setAttribute("name", alias);
- }
- return field;
+ public DBColumn getUpdateColumn()
+ {
+ return expr.getUpdateColumn();
}
/**
- * Returns the DBColunm object.
+ * This helper function returns the underlying column expression.
*
- * @return the DBColunm object
+ * @return the underlying column expression
*/
@Override
- public DBColumn getUpdateColumn()
+ public DBColumnExpr unwrap()
{
- return expr.getUpdateColumn();
+ return expr;
}
/**
@@ -181,7 +161,25 @@ public class DBAliasExpr extends DBColumnExpr
expr.addSQL(buf, context);
}
}
-
+
+ /**
+ * This function set the alias name to the XML tag.
+ *
+ * @return the XML tag (with the alias name)
+ */
+ @Override
+ public Element addXml(Element parent, long flags)
+ { // Set name to Alias
+ Element field = expr.addXml(parent, flags);
+ if (field != null)
+ { // Set Name
+ if (field.hasAttribute("name"))
+ field.setAttribute("source", StringUtils.toString(field.getAttribute("name")));
+ field.setAttribute("name", alias);
+ }
+ return field;
+ }
+
/**
* Overrides the equals method
*
@@ -197,7 +195,7 @@ public class DBAliasExpr extends DBColumnExpr
{ // Compare with another alias expression
DBAliasExpr otherExpr = ((DBAliasExpr)other);
return this.alias.equalsIgnoreCase(otherExpr.getName()) &&
- this.expr.equals(otherExpr.getExpr());
+ this.expr.equals(otherExpr.unwrap());
}
return false;
}
diff --git a/empire-db/src/main/java/org/apache/empire/db/expr/compare/DBCompareColExpr.java b/empire-db/src/main/java/org/apache/empire/db/expr/compare/DBCompareColExpr.java
index a89d9df..53da6d9 100644
--- a/empire-db/src/main/java/org/apache/empire/db/expr/compare/DBCompareColExpr.java
+++ b/empire-db/src/main/java/org/apache/empire/db/expr/compare/DBCompareColExpr.java
@@ -257,9 +257,9 @@ public class DBCompareColExpr extends DBCompareExpr
// unwrap
DBColumnExpr texpr = expr;
if (texpr instanceof DBAliasExpr)
- texpr = ((DBAliasExpr) texpr).getExpr();
+ texpr = ((DBAliasExpr) texpr).unwrap();
if (oexpr instanceof DBAliasExpr)
- oexpr = ((DBAliasExpr) oexpr).getExpr();
+ oexpr = ((DBAliasExpr) oexpr).unwrap();
// check function expression
boolean tfunc = (texpr instanceof DBAbstractFuncExpr);
boolean ofunc = (oexpr instanceof DBAbstractFuncExpr);
diff --git a/empire-db/src/main/java/org/apache/empire/dbms/oracle/DBMSHandlerOracle.java b/empire-db/src/main/java/org/apache/empire/dbms/oracle/DBMSHandlerOracle.java
index 44a3ccc..0ec6447 100644
--- a/empire-db/src/main/java/org/apache/empire/dbms/oracle/DBMSHandlerOracle.java
+++ b/empire-db/src/main/java/org/apache/empire/dbms/oracle/DBMSHandlerOracle.java
@@ -538,7 +538,7 @@ public class DBMSHandlerOracle extends DBMSHandlerBase
if (StringUtils.isEmpty(schemaPattern))
throw new InvalidPropertyException("schemaName", null);
// the default model checker
- return new OracleDBModelChecker(db, schemaPattern);
+ return new OracleDBModelChecker(schemaPattern, getBooleanType());
}
}
diff --git a/empire-db/src/main/java/org/apache/empire/dbms/oracle/OracleDBModelChecker.java b/empire-db/src/main/java/org/apache/empire/dbms/oracle/OracleDBModelChecker.java
index 282bae6..646b692 100644
--- a/empire-db/src/main/java/org/apache/empire/dbms/oracle/OracleDBModelChecker.java
+++ b/empire-db/src/main/java/org/apache/empire/dbms/oracle/OracleDBModelChecker.java
@@ -23,12 +23,9 @@ import java.sql.SQLException;
import org.apache.empire.data.DataType;
import org.apache.empire.db.DBColumn;
-import org.apache.empire.db.DBDatabase;
import org.apache.empire.db.validation.DBModelChecker;
import org.apache.empire.db.validation.DBModelErrorHandler;
-import org.apache.empire.dbms.DBMSHandler;
import org.apache.empire.dbms.oracle.DBMSHandlerOracle.BooleanType;
-import org.apache.empire.exceptions.InvalidArgumentException;
import org.apache.empire.exceptions.InvalidPropertyException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -40,22 +37,15 @@ public class OracleDBModelChecker extends DBModelChecker
{
private static final Logger log = LoggerFactory.getLogger(OracleDBModelChecker.class);
- private BooleanType booleanType = BooleanType.NUMBER;
+ private final BooleanType booleanType;
- public OracleDBModelChecker(DBDatabase db, String schemaName)
+ public OracleDBModelChecker(String schemaName, BooleanType booleanType)
{
super(null, schemaName);
// Detect boolean type
- DBMSHandler dbms = db.getDbms();
- if (dbms instanceof DBMSHandlerOracle)
- {
- booleanType = ((DBMSHandlerOracle)dbms).getBooleanType();
- }
- else
- { // Illegal DBMSHandler
- log.error("The database is not attached to a DBMSHandlerOracle");
- throw new InvalidArgumentException("db", db);
- }
+ this.booleanType = booleanType;
+ // ok
+ log.info("OracleDBModelChecker created for {} with booleanType {}", schemaName, booleanType);
}
/**
diff --git a/empire-db/src/main/java/org/apache/empire/dbms/sqlserver/DBMSHandlerMSSQL.java b/empire-db/src/main/java/org/apache/empire/dbms/sqlserver/DBMSHandlerMSSQL.java
index fd59293..6b7234b 100644
--- a/empire-db/src/main/java/org/apache/empire/dbms/sqlserver/DBMSHandlerMSSQL.java
+++ b/empire-db/src/main/java/org/apache/empire/dbms/sqlserver/DBMSHandlerMSSQL.java
@@ -557,7 +557,7 @@ public class DBMSHandlerMSSQL extends DBMSHandlerBase
schema = catalog.substring(schemaSep+1);
}
// the default model checker
- return new MSSqlDBModelChecker(db, catalog, schema);
+ return new MSSqlDBModelChecker(catalog, schema);
}
}
diff --git a/empire-db/src/main/java/org/apache/empire/dbms/sqlserver/MSSqlDBModelChecker.java b/empire-db/src/main/java/org/apache/empire/dbms/sqlserver/MSSqlDBModelChecker.java
index aa858bc..1dc83e0 100644
--- a/empire-db/src/main/java/org/apache/empire/dbms/sqlserver/MSSqlDBModelChecker.java
+++ b/empire-db/src/main/java/org/apache/empire/dbms/sqlserver/MSSqlDBModelChecker.java
@@ -22,7 +22,6 @@ import java.sql.DatabaseMetaData;
import java.sql.SQLException;
import org.apache.empire.commons.StringUtils;
-import org.apache.empire.db.DBDatabase;
import org.apache.empire.db.validation.DBModelChecker;
/**
@@ -37,7 +36,7 @@ public class MSSqlDBModelChecker extends DBModelChecker
* @param db the database
* @param catalog the catalog
*/
- public MSSqlDBModelChecker(DBDatabase db, String catalog, String schema)
+ public MSSqlDBModelChecker(String catalog, String schema)
{
super(catalog, StringUtils.coalesce(schema, "DBO"));
}
diff --git a/empire-db/src/main/java/org/apache/empire/exceptions/UnsupportedTypeException.java b/empire-db/src/main/java/org/apache/empire/exceptions/UnsupportedTypeException.java
new file mode 100644
index 0000000..81754e9
--- /dev/null
+++ b/empire-db/src/main/java/org/apache/empire/exceptions/UnsupportedTypeException.java
@@ -0,0 +1,15 @@
+package org.apache.empire.exceptions;
+
+import org.apache.empire.commons.ErrorType;
+
+public class UnsupportedTypeException extends EmpireException
+{
+ private static final long serialVersionUID = 1L;
+
+ public static final ErrorType errorType = new ErrorType("error.typeNotSupported", "The type {0} is not supported.");
+
+ public UnsupportedTypeException(Class<?> clazz)
+ {
+ super(errorType, new String[] { clazz.getSimpleName() } );
+ }
+}