Merge pull request #635 from mwoodiupui/DS-2128

[DS-2128] Eliminate dspace.cfg:db.name
This commit is contained in:
Mark H. Wood
2014-09-19 13:46:13 -04:00
25 changed files with 906 additions and 233 deletions

View File

@@ -43,9 +43,6 @@ default.language = en_US
# DATABASE CONFIGURATION # # DATABASE CONFIGURATION #
########################## ##########################
# Database name ("oracle", or "postgres")
db.name=postgres
# Uncomment the appropriate block below for your database. # Uncomment the appropriate block below for your database.
# postgres # postgres
db.driver=org.postgresql.Driver db.driver=org.postgresql.Driver

View File

@@ -1143,11 +1143,7 @@ public class LogAnalyser
public static Integer getNumItems(Context context, String type) public static Integer getNumItems(Context context, String type)
throws SQLException throws SQLException
{ {
boolean oracle = false; boolean oracle = DatabaseManager.isOracle();
if ("oracle".equals(ConfigurationManager.getProperty("db.name")))
{
oracle = true;
}
// FIXME: this method is clearly not optimised // FIXME: this method is clearly not optimised

View File

@@ -9,6 +9,7 @@ package org.dspace.browse;
import org.dspace.core.ConfigurationManager; import org.dspace.core.ConfigurationManager;
import org.dspace.core.Context; import org.dspace.core.Context;
import org.dspace.storage.rdbms.DatabaseManager;
/** /**
* Factory class to generate DAOs based on the configuration * Factory class to generate DAOs based on the configuration
@@ -87,18 +88,13 @@ public class BrowseDAOFactory
public static BrowseItemDAO getItemInstance(Context context) public static BrowseItemDAO getItemInstance(Context context)
throws BrowseException throws BrowseException
{ {
String db = ConfigurationManager.getProperty("db.name"); if (! DatabaseManager.isOracle())
if ("postgres".equals(db))
{ {
return new BrowseItemDAOPostgres(context); return new BrowseItemDAOPostgres(context);
} }
else if ("oracle".equals(db))
{
return new BrowseItemDAOOracle(context);
}
else else
{ {
throw new BrowseException("The configuration for db.name is either invalid, or contains an unrecognised database"); return new BrowseItemDAOOracle(context);
} }
} }
@@ -113,18 +109,13 @@ public class BrowseDAOFactory
public static BrowseDAOUtils getUtils(Context context) public static BrowseDAOUtils getUtils(Context context)
throws BrowseException throws BrowseException
{ {
String db = ConfigurationManager.getProperty("db.name"); if (! DatabaseManager.isOracle())
if ("postgres".equals(db))
{ {
return new BrowseDAOUtilsPostgres(); return new BrowseDAOUtilsPostgres();
} }
else if ("oracle".equals(db)) else
{ {
return new BrowseDAOUtilsOracle(); return new BrowseDAOUtilsOracle();
} }
else
{
throw new BrowseException("The configuration for db.name is either invalid, or contains an unrecognised database");
}
} }
} }

View File

@@ -32,16 +32,16 @@ import org.dspace.sort.OrderFormat;
public class BrowseEngine public class BrowseEngine
{ {
/** the logger for this class */ /** the logger for this class */
private static Logger log = Logger.getLogger(BrowseEngine.class); private static final Logger log = Logger.getLogger(BrowseEngine.class);
/** the browse scope which is the basis for our browse */ /** the browse scope which is the basis for our browse */
private BrowserScope scope; private BrowserScope scope;
/** the DSpace context */ /** the DSpace context */
private Context context; private final Context context;
/** The Data Access Object for the browse tables */ /** The Data Access Object for the browse tables */
private BrowseDAO dao; private final BrowseDAO dao;
/** The Browse Index associated with the Browse Scope */ /** The Browse Index associated with the Browse Scope */
private BrowseIndex browseIndex; private BrowseIndex browseIndex;
@@ -49,7 +49,7 @@ public class BrowseEngine
/** /**
* Create a new instance of the Browse engine, using the given DSpace * Create a new instance of the Browse engine, using the given DSpace
* Context object. This will automatically assign a Data Access Object * Context object. This will automatically assign a Data Access Object
* for the Browse Engine, based on the dspace.cfg setting for db.name * for the Browse Engine, based on the brand of the provided DBMS.
* *
* @param context the DSpace context * @param context the DSpace context
* @throws BrowseException * @throws BrowseException

View File

@@ -12,7 +12,6 @@ import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import org.apache.solr.common.SolrInputDocument; import org.apache.solr.common.SolrInputDocument;
@@ -28,6 +27,7 @@ import org.dspace.discovery.SolrServiceIndexPlugin;
import org.dspace.sort.OrderFormat; import org.dspace.sort.OrderFormat;
import org.dspace.sort.SortException; import org.dspace.sort.SortException;
import org.dspace.sort.SortOption; import org.dspace.sort.SortOption;
import org.dspace.storage.rdbms.DatabaseManager;
import org.dspace.utils.DSpace; import org.dspace.utils.DSpace;
/** /**
@@ -68,19 +68,13 @@ public class SolrBrowseCreateDAO implements BrowseCreateDAO,
public SolrBrowseCreateDAO(Context context) throws BrowseException public SolrBrowseCreateDAO(Context context) throws BrowseException
{ {
// For compatibility with previous versions // For compatibility with previous versions
String db = ConfigurationManager.getProperty("db.name"); if (! DatabaseManager.isOracle())
if ("postgres".equals(db))
{ {
dbCreateDAO = new BrowseCreateDAOPostgres(context); dbCreateDAO = new BrowseCreateDAOPostgres(context);
} }
else if ("oracle".equals(db))
{
dbCreateDAO = new BrowseCreateDAOOracle(context);
}
else else
{ {
throw new BrowseException( dbCreateDAO = new BrowseCreateDAOOracle(context);
"The configuration for db.name is either invalid, or contains an unrecognised database");
} }
try try

View File

@@ -285,7 +285,7 @@ public final class BitstreamInfoDAO extends DAOSupport
{ {
LOG.debug("updating missing bitstreams"); LOG.debug("updating missing bitstreams");
conn = DatabaseManager.getConnection(); conn = DatabaseManager.getConnection();
if ("oracle".equals(ConfigurationManager.getProperty("db.name"))) if (DatabaseManager.isOracle())
{ {
stmt = conn.prepareStatement(INSERT_MISSING_CHECKSUM_BITSTREAMS_ORACLE); stmt = conn.prepareStatement(INSERT_MISSING_CHECKSUM_BITSTREAMS_ORACLE);
} }
@@ -398,7 +398,7 @@ public final class BitstreamInfoDAO extends DAOSupport
{ {
conn = DatabaseManager.getConnection(); conn = DatabaseManager.getConnection();
if ("oracle".equals(ConfigurationManager.getProperty("db.name"))) if (DatabaseManager.isOracle())
{ {
prepStmt = conn.prepareStatement(GET_OLDEST_BITSTREAM_ORACLE); prepStmt = conn.prepareStatement(GET_OLDEST_BITSTREAM_ORACLE);
} }
@@ -445,7 +445,7 @@ public final class BitstreamInfoDAO extends DAOSupport
try try
{ {
conn = DatabaseManager.getConnection(); conn = DatabaseManager.getConnection();
if ("oracle".equals(ConfigurationManager.getProperty("db.name"))) if (DatabaseManager.isOracle())
{ {
prepStmt = conn.prepareStatement(GET_OLDEST_BITSTREAM_DATE_ORACLE); prepStmt = conn.prepareStatement(GET_OLDEST_BITSTREAM_DATE_ORACLE);
} }

View File

@@ -111,7 +111,7 @@ public class ChecksumHistoryDAO extends DAOSupport
try try
{ {
conn = DatabaseManager.getConnection(); conn = DatabaseManager.getConnection();
if ("oracle".equals(ConfigurationManager.getProperty("db.name"))) if (DatabaseManager.isOracle())
{ {
stmt = conn.prepareStatement(INSERT_HISTORY_ORACLE); stmt = conn.prepareStatement(INSERT_HISTORY_ORACLE);
} }
@@ -183,7 +183,7 @@ public class ChecksumHistoryDAO extends DAOSupport
PreparedStatement stmt = null; PreparedStatement stmt = null;
try try
{ {
if ("oracle".equals(ConfigurationManager.getProperty("db.name"))) if (DatabaseManager.isOracle())
{ {
stmt = conn.prepareStatement(INSERT_MISSING_HISTORY_BITSTREAMS_ORACLE); stmt = conn.prepareStatement(INSERT_MISSING_HISTORY_BITSTREAMS_ORACLE);
} }

View File

@@ -180,7 +180,7 @@ public class ReporterDAO extends DAOSupport
// create the connection and execute the statement // create the connection and execute the statement
conn = DatabaseManager.getConnection(); conn = DatabaseManager.getConnection();
if ("oracle".equals(ConfigurationManager.getProperty("db.name"))) if (DatabaseManager.isOracle())
{ {
prepStmt = conn.prepareStatement(DATE_RANGE_NOT_PROCESSED_BITSTREAMS_ORACLE); prepStmt = conn.prepareStatement(DATE_RANGE_NOT_PROCESSED_BITSTREAMS_ORACLE);
} }

View File

@@ -531,11 +531,7 @@ public class Bitstream extends DSpaceObject
*/ */
void delete() throws SQLException void delete() throws SQLException
{ {
boolean oracle = false; boolean oracle = DatabaseManager.isOracle();
if ("oracle".equals(ConfigurationManager.getProperty("db.name")))
{
oracle = true;
}
// changed to a check on remove // changed to a check on remove
// Check authorisation // Check authorisation

View File

@@ -8,7 +8,7 @@
package org.dspace.content.dao; package org.dspace.content.dao;
import org.dspace.core.Context; import org.dspace.core.Context;
import org.dspace.core.ConfigurationManager; import org.dspace.storage.rdbms.DatabaseManager;
/** /**
* Created by IntelliJ IDEA. * Created by IntelliJ IDEA.
@@ -21,7 +21,7 @@ public class ItemDAOFactory
{ {
public static ItemDAO getInstance(Context context) public static ItemDAO getInstance(Context context)
{ {
if (ConfigurationManager.getProperty("db.name").equalsIgnoreCase("oracle")) if (DatabaseManager.isOracle())
{ {
return new ItemDAOOracle(context); return new ItemDAOOracle(context);
} }

View File

@@ -13,7 +13,6 @@ import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.GnuParser; import org.apache.commons.cli.GnuParser;
import org.apache.commons.cli.Option; import org.apache.commons.cli.Option;
import org.apache.commons.cli.OptionGroup; import org.apache.commons.cli.OptionGroup;
@@ -60,13 +59,13 @@ public class EPerson extends DSpaceObject
public static final int LANGUAGE = 5; public static final int LANGUAGE = 5;
/** log4j logger */ /** log4j logger */
private static Logger log = Logger.getLogger(EPerson.class); private static final Logger log = Logger.getLogger(EPerson.class);
/** Our context */ /** Our context */
private Context myContext; private final Context myContext;
/** The row in the table representing this eperson */ /** The row in the table representing this eperson */
private TableRow myRow; private final TableRow myRow;
/** Flag set when data is modified, for events */ /** Flag set when data is modified, for events */
private boolean modified; private boolean modified;
@@ -295,7 +294,7 @@ public class EPerson extends DSpaceObject
queryBuf.append("LOWER(firstname) LIKE LOWER(?) OR LOWER(lastname) LIKE LOWER(?) OR LOWER(email) LIKE LOWER(?) ORDER BY lastname, firstname ASC "); queryBuf.append("LOWER(firstname) LIKE LOWER(?) OR LOWER(lastname) LIKE LOWER(?) OR LOWER(email) LIKE LOWER(?) ORDER BY lastname, firstname ASC ");
// Add offset and limit restrictions - Oracle requires special code // Add offset and limit restrictions - Oracle requires special code
if ("oracle".equals(ConfigurationManager.getProperty("db.name"))) if (DatabaseManager.isOracle())
{ {
// First prepare the query to generate row numbers // First prepare the query to generate row numbers
if (limit > 0 || offset > 0) if (limit > 0 || offset > 0)
@@ -431,7 +430,7 @@ public class EPerson extends DSpaceObject
new Object[] {int_param,dbquery,dbquery,dbquery}); new Object[] {int_param,dbquery,dbquery,dbquery});
// use getIntColumn for Oracle count data // use getIntColumn for Oracle count data
if ("oracle".equals(ConfigurationManager.getProperty("db.name"))) if (DatabaseManager.isOracle())
{ {
count = Long.valueOf(row.getIntColumn("epcount")); count = Long.valueOf(row.getIntColumn("epcount"));
} }

View File

@@ -46,7 +46,7 @@ public class Group extends DSpaceObject
public static final int NAME = 1; // sort by NAME (default) public static final int NAME = 1; // sort by NAME (default)
/** log4j logger */ /** log4j logger */
private static Logger log = Logger.getLogger(Group.class); private static final Logger log = Logger.getLogger(Group.class);
/** ID of Anonymous Group */ /** ID of Anonymous Group */
public static final int ANONYMOUS_ID = 0; public static final int ANONYMOUS_ID = 0;
@@ -55,10 +55,10 @@ public class Group extends DSpaceObject
public static final int ADMIN_ID = 1; public static final int ADMIN_ID = 1;
/** Our context */ /** Our context */
private Context myContext; private final Context myContext;
/** The row in the table representing this object */ /** The row in the table representing this object */
private TableRow myRow; private final TableRow myRow;
/** lists of epeople and groups in the group */ /** lists of epeople and groups in the group */
private List<EPerson> epeople = new ArrayList<EPerson>(); private List<EPerson> epeople = new ArrayList<EPerson>();
@@ -852,7 +852,7 @@ public class Group extends DSpaceObject
queryBuf.append("SELECT * FROM epersongroup WHERE LOWER(name) LIKE LOWER(?) OR eperson_group_id = ? ORDER BY name ASC "); queryBuf.append("SELECT * FROM epersongroup WHERE LOWER(name) LIKE LOWER(?) OR eperson_group_id = ? ORDER BY name ASC ");
// Add offset and limit restrictions - Oracle requires special code // Add offset and limit restrictions - Oracle requires special code
if ("oracle".equals(ConfigurationManager.getProperty("db.name"))) if (DatabaseManager.isOracle())
{ {
// First prepare the query to generate row numbers // First prepare the query to generate row numbers
if (limit > 0 || offset > 0) if (limit > 0 || offset > 0)
@@ -985,7 +985,7 @@ public class Group extends DSpaceObject
// use getIntColumn for Oracle count data // use getIntColumn for Oracle count data
Long count; Long count;
if ("oracle".equals(ConfigurationManager.getProperty("db.name"))) if (DatabaseManager.isOracle())
{ {
count = Long.valueOf(row.getIntColumn("gcount")); count = Long.valueOf(row.getIntColumn("gcount"));
} }

View File

@@ -27,8 +27,8 @@ import java.util.List;
public class HarvestedCollection public class HarvestedCollection
{ {
private Context context; private final Context context;
private TableRow harvestRow; private final TableRow harvestRow;
public static final int TYPE_NONE = 0; public static final int TYPE_NONE = 0;
public static final int TYPE_DMD = 1; public static final int TYPE_DMD = 1;
@@ -238,7 +238,7 @@ public class HarvestedCollection
public static Integer findOldestHarvest (Context c) throws SQLException { public static Integer findOldestHarvest (Context c) throws SQLException {
String query = "select collection_id from harvested_collection where harvest_type > ? and harvest_status = ? order by last_harvested asc limit 1"; String query = "select collection_id from harvested_collection where harvest_type > ? and harvest_status = ? order by last_harvested asc limit 1";
if ("oracle".equals(ConfigurationManager.getProperty("db.name"))) if (DatabaseManager.isOracle())
{ {
query = "select collection_id from harvested_collection where harvest_type > ? and harvest_status = ? and rownum <= 1 order by last_harvested asc"; query = "select collection_id from harvested_collection where harvest_type > ? and harvest_status = ? and rownum <= 1 order by last_harvested asc";
} }
@@ -263,7 +263,7 @@ public class HarvestedCollection
public static Integer findNewestHarvest (Context c) throws SQLException { public static Integer findNewestHarvest (Context c) throws SQLException {
String query = "select collection_id from harvested_collection where harvest_type > ? and harvest_status = ? order by last_harvested desc limit 1"; String query = "select collection_id from harvested_collection where harvest_type > ? and harvest_status = ? order by last_harvested desc limit 1";
if ("oracle".equals(ConfigurationManager.getProperty("db.name"))) if (DatabaseManager.isOracle())
{ {
query = "select collection_id from harvested_collection where harvest_type > ? and harvest_status = ? and rownum <= 1 order by last_harvested desc"; query = "select collection_id from harvested_collection where harvest_type > ? and harvest_status = ? and rownum <= 1 order by last_harvested desc";
} }

View File

@@ -39,7 +39,7 @@ import java.util.*;
public class Harvest public class Harvest
{ {
/** log4j logger */ /** log4j logger */
private static Logger log = Logger.getLogger(Harvest.class); private static final Logger log = Logger.getLogger(Harvest.class);
/** /**
* Obtain information about items that have been created, modified or * Obtain information about items that have been created, modified or
@@ -173,7 +173,7 @@ public class Harvest
if (!withdrawn) if (!withdrawn)
{ {
// Exclude withdrawn items // Exclude withdrawn items
if ("oracle".equals(ConfigurationManager.getProperty("db.name"))) if (DatabaseManager.isOracle())
{ {
query += " AND withdrawn=0 "; query += " AND withdrawn=0 ";
} }

View File

@@ -7,6 +7,11 @@
*/ */
package org.dspace.storage.rdbms; package org.dspace.storage.rdbms;
import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.SQLException;
import javax.sql.DataSource;
import org.apache.commons.dbcp.*; import org.apache.commons.dbcp.*;
import org.apache.commons.pool.ObjectPool; import org.apache.commons.pool.ObjectPool;
import org.apache.commons.pool.impl.GenericKeyedObjectPool; import org.apache.commons.pool.impl.GenericKeyedObjectPool;
@@ -15,13 +20,8 @@ import org.apache.commons.pool.impl.GenericObjectPool;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import org.dspace.core.ConfigurationManager; import org.dspace.core.ConfigurationManager;
import javax.sql.DataSource;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.SQLException;
public class DataSourceInit { public class DataSourceInit {
private static Logger log = Logger.getLogger(DataSourceInit.class); private static final Logger log = Logger.getLogger(DataSourceInit.class);
private static DataSource dataSource = null; private static DataSource dataSource = null;
@@ -94,12 +94,6 @@ public class DataSourceInit {
// //
String validationQuery = "SELECT 1"; String validationQuery = "SELECT 1";
// Oracle has a slightly different validation query
if ("oracle".equals(ConfigurationManager.getProperty("db.name")))
{
validationQuery = "SELECT 1 FROM DUAL";
}
GenericKeyedObjectPoolFactory statementFactory = null; GenericKeyedObjectPoolFactory statementFactory = null;
if (useStatementPool) if (useStatementPool)
{ {
@@ -139,6 +133,16 @@ public class DataSourceInit {
poolingDataSource.setPool(connectionPool); poolingDataSource.setPool(connectionPool);
dataSource = poolingDataSource; dataSource = poolingDataSource;
// Set the proper validation query by DBMS brand.
Connection connection = dataSource.getConnection();
if ("oracle".equals(connection.getMetaData().getDatabaseProductName().toLowerCase()))
{
poolableConnectionFactory.setValidationQuery("SELECT 1 FROM DUAL");
}
connection.close();
// Ready to use
return poolingDataSource; return poolingDataSource;
} }
catch (Exception e) catch (Exception e)

View File

@@ -26,30 +26,29 @@ import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import javax.naming.InitialContext; import javax.naming.InitialContext;
import javax.sql.DataSource; import javax.sql.DataSource;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.apache.log4j.Level;
import org.dspace.core.ConfigurationManager; import org.dspace.core.ConfigurationManager;
import org.dspace.core.Context; import org.dspace.core.Context;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/** /**
* Executes SQL queries. * Executes SQL queries.
* *
* @author Peter Breton * @author Peter Breton
* @author Jim Downing * @author Jim Downing
* @version $Revision$ * @version $Revision$
*/ */
public class DatabaseManager public class DatabaseManager
{ {
/** log4j category */ /** logging category */
private static final Logger log = Logger.getLogger(DatabaseManager.class); private static final Logger log = LoggerFactory.getLogger(DatabaseManager.class);
/** True if initialization has been done */ /** True if initialization has been done */
private static boolean initialized = false; private static boolean initialized = false;
@@ -59,35 +58,24 @@ public class DatabaseManager
private static boolean isOracle = false; private static boolean isOracle = false;
private static boolean isPostgres = false; private static boolean isPostgres = false;
static
{
if ("oracle".equals(ConfigurationManager.getProperty("db.name")))
{
isOracle = true;
isPostgres = false;
}
else
{
isOracle = false;
isPostgres = true;
}
}
/** DataSource (retrieved from jndi */ /** DataSource (retrieved from jndi */
private static DataSource dataSource = null; private static DataSource dataSource = null;
/** Name of the DBMS, as returned by its driver. */
private static String dbms;
/** Name to use for the pool */ /** Name to use for the pool */
private static String poolName = "dspacepool"; private static String poolName = "dspacepool";
/** /**
* This regular expression is used to perform sanity checks * This regular expression is used to perform sanity checks
* on database names (i.e. tables and columns). * on database names (i.e. tables and columns).
* *
* FIXME: Regular expressions can be slow to solve this in the future we should * FIXME: Regular expressions can be slow to solve this in the future we should
* probably create a system where we don't pass in column and table names to these low * probably create a system where we don't pass in column and table names to these low
* level database methods. This approach is highly exploitable for injection * level database methods. This approach is highly exploitable for injection
* type attacks because we are unable to determine where the input came from. Instead * type attacks because we are unable to determine where the input came from. Instead
* we could pass in static integer constants which are then mapped to their sql name. * we could pass in static integer constants which are then mapped to their sql name.
*/ */
private static final Pattern DB_SAFE_NAME = Pattern.compile("^[a-zA-Z_1-9.]+$"); private static final Pattern DB_SAFE_NAME = Pattern.compile("^[a-zA-Z_1-9.]+$");
@@ -106,12 +94,19 @@ public class DatabaseManager
public static boolean isOracle() public static boolean isOracle()
{ {
try
{
initialize();
} catch (SQLException ex)
{
log.error("Failed to initialize the database: ", ex);
}
return isOracle; return isOracle;
} }
/** /**
* Set the constraint check to deferred (commit time) * Set the constraint check to deferred (commit time)
* *
* @param context * @param context
* The context object * The context object
* @param constraintName * @param constraintName
@@ -145,7 +140,7 @@ public class DatabaseManager
/** /**
* Set the constraint check to immediate (every query) * Set the constraint check to immediate (every query)
* *
* @param context * @param context
* The context object * The context object
* @param constraintName * @param constraintName
@@ -176,12 +171,12 @@ public class DatabaseManager
} }
} }
} }
/** /**
* Return an iterator with the results of the query. The table parameter * Return an iterator with the results of the query. The table parameter
* indicates the type of result. If table is null, the column names are read * indicates the type of result. If table is null, the column names are read
* from the ResultSetMetaData. * from the ResultSetMetaData.
* *
* @param context * @param context
* The context object * The context object
* @param table * @param table
@@ -189,8 +184,8 @@ public class DatabaseManager
* @param query * @param query
* The SQL query * The SQL query
* @param parameters * @param parameters
* A set of SQL parameters to be included in query. The order of * A set of SQL parameters to be included in query. The order of
* the parameters must correspond to the order of their reference * the parameters must correspond to the order of their reference
* within the query. * within the query.
* @return A TableRowIterator with the results of the query * @return A TableRowIterator with the results of the query
* @exception SQLException * @exception SQLException
@@ -211,7 +206,7 @@ public class DatabaseManager
} }
log.debug(sb.toString()); log.debug(sb.toString());
} }
PreparedStatement statement = context.getDBConnection().prepareStatement(query); PreparedStatement statement = context.getDBConnection().prepareStatement(query);
try try
{ {
@@ -238,24 +233,24 @@ public class DatabaseManager
throw sqle; throw sqle;
} }
} }
/** /**
* Return an iterator with the results of the query. * Return an iterator with the results of the query.
* *
* @param context * @param context
* The context object * The context object
* @param query * @param query
* The SQL query * The SQL query
* @param parameters * @param parameters
* A set of SQL parameters to be included in query. The order of * A set of SQL parameters to be included in query. The order of
* the parameters must correspond to the order of their reference * the parameters must correspond to the order of their reference
* within the query. * within the query.
* @return A TableRowIterator with the results of the query * @return A TableRowIterator with the results of the query
* @exception SQLException * @exception SQLException
* If a database error occurs * If a database error occurs
*/ */
public static TableRowIterator query(Context context, String query, public static TableRowIterator query(Context context, String query,
Object... parameters) throws SQLException Object... parameters) throws SQLException
{ {
if (log.isDebugEnabled()) if (log.isDebugEnabled())
{ {
@@ -301,14 +296,14 @@ public class DatabaseManager
/** /**
* Return the single row result to this query, or null if no result. If more * Return the single row result to this query, or null if no result. If more
* than one row results, only the first is returned. * than one row results, only the first is returned.
* *
* @param context * @param context
* Current DSpace context * Current DSpace context
* @param query * @param query
* The SQL query * The SQL query
* @param parameters * @param parameters
* A set of SQL parameters to be included in query. The order of * A set of SQL parameters to be included in query. The order of
* the parameters must correspond to the order of their reference * the parameters must correspond to the order of their reference
* within the query. * within the query.
* @return A TableRow object, or null if no result * @return A TableRow object, or null if no result
@@ -335,11 +330,11 @@ public class DatabaseManager
return (retRow); return (retRow);
} }
/** /**
* Return the single row result to this query, or null if no result. If more * Return the single row result to this query, or null if no result. If more
* than one row results, only the first is returned. * than one row results, only the first is returned.
* *
* @param context * @param context
* Current DSpace context * Current DSpace context
* @param table * @param table
@@ -347,8 +342,8 @@ public class DatabaseManager
* @param query * @param query
* The SQL query * The SQL query
* @param parameters * @param parameters
* A set of SQL parameters to be included in query. The order of * A set of SQL parameters to be included in query. The order of
* the parameters must correspond to the order of their reference * the parameters must correspond to the order of their reference
* within the query. * within the query.
* @return A TableRow object, or null if no result * @return A TableRow object, or null if no result
* @exception SQLException * @exception SQLException
@@ -373,18 +368,18 @@ public class DatabaseManager
} }
return (retRow); return (retRow);
} }
/** /**
* Execute an update, insert or delete query. Returns the number of rows * Execute an update, insert or delete query. Returns the number of rows
* affected by the query. * affected by the query.
* *
* @param context * @param context
* Current DSpace context * Current DSpace context
* @param query * @param query
* The SQL query to execute * The SQL query to execute
* @param parameters * @param parameters
* A set of SQL parameters to be included in query. The order of * A set of SQL parameters to be included in query. The order of
* the parameters must correspond to the order of their reference * the parameters must correspond to the order of their reference
* within the query. * within the query.
* @return The number of rows affected by the query. * @return The number of rows affected by the query.
* @exception SQLException * @exception SQLException
@@ -409,10 +404,10 @@ public class DatabaseManager
} }
try try
{ {
statement = context.getDBConnection().prepareStatement(query); statement = context.getDBConnection().prepareStatement(query);
loadParameters(statement, parameters); loadParameters(statement, parameters);
return statement.executeUpdate(); return statement.executeUpdate();
} }
finally finally
@@ -432,7 +427,7 @@ public class DatabaseManager
/** /**
* Create a new row in the given table, and assigns a unique id. * Create a new row in the given table, and assigns a unique id.
* *
* @param context * @param context
* Current DSpace context * Current DSpace context
* @param table * @param table
@@ -451,7 +446,7 @@ public class DatabaseManager
/** /**
* Find a table row by its primary key. Returns the row, or null if no row * Find a table row by its primary key. Returns the row, or null if no row
* with that primary key value exists. * with that primary key value exists.
* *
* @param context * @param context
* Current DSpace context * Current DSpace context
* @param table * @param table
@@ -476,7 +471,7 @@ public class DatabaseManager
* Find a table row by a unique value. Returns the row, or null if no row * Find a table row by a unique value. Returns the row, or null if no row
* with that primary key value exists. If multiple rows with the value * with that primary key value exists. If multiple rows with the value
* exist, one is returned. * exist, one is returned.
* *
* @param context * @param context
* Current DSpace context * Current DSpace context
* @param table * @param table
@@ -512,7 +507,7 @@ public class DatabaseManager
/** /**
* Delete a table row via its primary key. Returns the number of rows * Delete a table row via its primary key. Returns the number of rows
* deleted. * deleted.
* *
* @param context * @param context
* Current DSpace context * Current DSpace context
* @param table * @param table
@@ -535,7 +530,7 @@ public class DatabaseManager
/** /**
* Delete all table rows with the given value. Returns the number of rows * Delete all table rows with the given value. Returns the number of rows
* deleted. * deleted.
* *
* @param context * @param context
* Current DSpace context * Current DSpace context
* @param table * @param table
@@ -569,7 +564,7 @@ public class DatabaseManager
/** /**
* Obtain an RDBMS connection. * Obtain an RDBMS connection.
* *
* @return A new database connection. * @return A new database connection.
* @exception SQLException * @exception SQLException
* If a database error occurs, or a connection cannot be * If a database error occurs, or a connection cannot be
@@ -604,7 +599,7 @@ public class DatabaseManager
/** /**
* Release resources associated with this connection. * Release resources associated with this connection.
* *
* @param c * @param c
* The connection to release * The connection to release
*/ */
@@ -626,7 +621,7 @@ public class DatabaseManager
/** /**
* Create a table row object that can be passed into the insert method, not * Create a table row object that can be passed into the insert method, not
* commonly used unless the table has a referential integrity constraint. * commonly used unless the table has a referential integrity constraint.
* *
* @param table * @param table
* The RDBMS table in which to create the new row * The RDBMS table in which to create the new row
* @return The newly created row * @return The newly created row
@@ -639,7 +634,7 @@ public class DatabaseManager
/** /**
* Insert a table row into the RDBMS. * Insert a table row into the RDBMS.
* *
* @param context * @param context
* Current DSpace context * Current DSpace context
* @param row * @param row
@@ -665,7 +660,7 @@ public class DatabaseManager
/** /**
* Update changes to the RDBMS. Note that if the update fails, the values in * Update changes to the RDBMS. Note that if the update fails, the values in
* the row will NOT be reverted. * the row will NOT be reverted.
* *
* @param context * @param context
* Current DSpace context * Current DSpace context
* @param row * @param row
@@ -714,7 +709,7 @@ public class DatabaseManager
/** /**
* Delete row from the RDBMS. * Delete row from the RDBMS.
* *
* @param context * @param context
* Current DSpace context * Current DSpace context
* @param row * @param row
@@ -742,7 +737,7 @@ public class DatabaseManager
/** /**
* Return metadata about a table. * Return metadata about a table.
* *
* @param table * @param table
* The name of the table * The name of the table
* @return An array of ColumnInfo objects * @return An array of ColumnInfo objects
@@ -758,7 +753,7 @@ public class DatabaseManager
/** /**
* Return info about column in table. * Return info about column in table.
* *
* @param table * @param table
* The name of the table * The name of the table
* @param column * @param column
@@ -777,7 +772,7 @@ public class DatabaseManager
/** /**
* Return the names of all the columns of the given table. * Return the names of all the columns of the given table.
* *
* @param table * @param table
* The name of the table * The name of the table
* @return The names of all the columns of the given table, as a List. Each * @return The names of all the columns of the given table, as a List. Each
@@ -800,7 +795,7 @@ public class DatabaseManager
/** /**
* Return the names of all the columns of the ResultSet. * Return the names of all the columns of the ResultSet.
* *
* @param meta * @param meta
* The ResultSetMetaData * The ResultSetMetaData
* @return The names of all the columns of the given table, as a List. Each * @return The names of all the columns of the given table, as a List. Each
@@ -823,7 +818,7 @@ public class DatabaseManager
/** /**
* Return the canonical name for a table. * Return the canonical name for a table.
* *
* @param table * @param table
* The name of the table. * The name of the table.
* @return The canonical name of the table. * @return The canonical name of the table.
@@ -846,7 +841,7 @@ public class DatabaseManager
/** /**
* Load SQL into the RDBMS. * Load SQL into the RDBMS.
* *
* @param sql * @param sql
* The SQL to load. * The SQL to load.
* throws SQLException * throws SQLException
@@ -865,7 +860,7 @@ public class DatabaseManager
/** /**
* Load SQL from a reader into the RDBMS. * Load SQL from a reader into the RDBMS.
* *
* @param r * @param r
* The Reader from which to read the SQL. * The Reader from which to read the SQL.
* @throws SQLException * @throws SQLException
@@ -989,18 +984,12 @@ public class DatabaseManager
// If the messages are bogus, give them a low priority // If the messages are bogus, give them a low priority
if (isDrop || isNoResults) if (isDrop || isNoResults)
{ {
if (log.isDebugEnabled()) log.debug(msg, sqle);
{
log.debug(msg, sqle);
}
} }
// Otherwise, we need to know! // Otherwise, we need to know!
else else
{ {
if (log.isEnabledFor(Level.WARN)) log.warn(msg, sqle);
{
log.warn(msg, sqle);
}
} }
} }
@@ -1029,7 +1018,7 @@ public class DatabaseManager
/** /**
* Convert the current row in a ResultSet into a TableRow object. * Convert the current row in a ResultSet into a TableRow object.
* *
* @param results * @param results
* A ResultSet to process * A ResultSet to process
* @param table * @param table
@@ -1178,7 +1167,7 @@ public class DatabaseManager
* Return the name of the primary key column. We assume there's only one * Return the name of the primary key column. We assume there's only one
* primary key per table; if there are more, only the first one will be * primary key per table; if there are more, only the first one will be
* returned. * returned.
* *
* @param row * @param row
* The TableRow to return the primary key for. * The TableRow to return the primary key for.
* @return The name of the primary key column, or null if the row has no * @return The name of the primary key column, or null if the row has no
@@ -1195,7 +1184,7 @@ public class DatabaseManager
* Return the name of the primary key column in the given table. We assume * Return the name of the primary key column in the given table. We assume
* there's only one primary key per table; if there are more, only the first * there's only one primary key per table; if there are more, only the first
* one will be returned. * one will be returned.
* *
* @param table * @param table
* The name of the RDBMS table * The name of the RDBMS table
* @return The name of the primary key column, or null if the table has no * @return The name of the primary key column, or null if the table has no
@@ -1215,7 +1204,7 @@ public class DatabaseManager
* Return column information for the primary key column, or null if the * Return column information for the primary key column, or null if the
* table has no primary key. We assume there's only one primary key per * table has no primary key. We assume there's only one primary key per
* table; if there are more, only the first one will be returned. * table; if there are more, only the first one will be returned.
* *
* @param table * @param table
* The name of the RDBMS table * The name of the RDBMS table
* @return A ColumnInfo object, or null if the table has no primary key. * @return A ColumnInfo object, or null if the table has no primary key.
@@ -1240,7 +1229,7 @@ public class DatabaseManager
/** /**
* Execute SQL as a PreparedStatement on Connection. Bind parameters in * Execute SQL as a PreparedStatement on Connection. Bind parameters in
* columns to the values in the table row before executing. * columns to the values in the table row before executing.
* *
* @param connection * @param connection
* The SQL connection * The SQL connection
* @param sql * @param sql
@@ -1315,7 +1304,7 @@ public class DatabaseManager
/** /**
* Return metadata about a table. * Return metadata about a table.
* *
* @param table * @param table
* The name of the table * The name of the table
* @return An map of info. * @return An map of info.
@@ -1340,7 +1329,7 @@ public class DatabaseManager
/** /**
* Read metadata about a table from the database. * Read metadata about a table from the database.
* *
* @param table * @param table
* The RDBMS table. * The RDBMS table.
* @return A map of information about the columns. The key is the name of * @return A map of information about the columns. The key is the name of
@@ -1354,7 +1343,7 @@ public class DatabaseManager
Connection connection = null; Connection connection = null;
ResultSet pkcolumns = null; ResultSet pkcolumns = null;
ResultSet columns = null; ResultSet columns = null;
try try
{ {
String schema = ConfigurationManager.getProperty("db.schema"); String schema = ConfigurationManager.getProperty("db.schema");
@@ -1362,8 +1351,8 @@ public class DatabaseManager
schema = null; schema = null;
} }
String catalog = null; String catalog = null;
int dotIndex = table.indexOf('.'); int dotIndex = table.indexOf('.');
if (dotIndex > 0) if (dotIndex > 0)
{ {
catalog = table.substring(0, dotIndex); catalog = table.substring(0, dotIndex);
@@ -1371,7 +1360,7 @@ public class DatabaseManager
log.warn("catalog: " + catalog); log.warn("catalog: " + catalog);
log.warn("table: " + table); log.warn("table: " + table);
} }
connection = getConnection(); connection = getConnection();
DatabaseMetaData metadata = connection.getMetaData(); DatabaseMetaData metadata = connection.getMetaData();
@@ -1380,9 +1369,9 @@ public class DatabaseManager
int max = metadata.getMaxTableNameLength(); int max = metadata.getMaxTableNameLength();
String tname = ((max > 0) && (table.length() >= max)) ? table String tname = ((max > 0) && (table.length() >= max)) ? table
.substring(0, max - 1) : table; .substring(0, max - 1) : table;
pkcolumns = metadata.getPrimaryKeys(catalog, schema, tname); pkcolumns = metadata.getPrimaryKeys(catalog, schema, tname);
Set<String> pks = new HashSet<String>(); Set<String> pks = new HashSet<String>();
while (pkcolumns.next()) while (pkcolumns.next())
@@ -1487,6 +1476,33 @@ public class DatabaseManager
dataSource = DataSourceInit.getDatasource(); dataSource = DataSourceInit.getDatasource();
} }
// What brand of DBMS do we have?
Connection connection = dataSource.getConnection();
DatabaseMetaData meta = connection.getMetaData();
dbms = meta.getDatabaseProductName();
String dbms_lc = dbms.toLowerCase(Locale.ROOT);
if (dbms_lc.contains("postgresql"))
{
isPostgres = true;
log.info("DBMS is PostgreSQL");
}
else if (dbms_lc.contains("oracle"))
{
isOracle = true;
log.info("DBMS is Oracle Database");
}
else if (dbms_lc.contains("h2")) // Used in testing
{
isOracle = true;
log.info("DBMS is H2");
}
else
{
log.error("DBMS {} is unsupported", dbms);
}
log.info("DBMS driver version is '{}'", meta.getDatabaseProductVersion());
connection.close();
initialized = true; initialized = true;
} }
catch (SQLException se) catch (SQLException se)
@@ -1503,8 +1519,23 @@ public class DatabaseManager
} }
} }
/** /**
* Iterate over the given parameters and add them to the given prepared statement. * What is the name of our DBMS?
*
* @return name returned by the DBMS driver.
*/
public static String getDbName()
{
try {
initialize();
} catch (SQLException ex) {
log.error("Failed to initialize the database: ", ex);
}
return dbms;
}
/**
* Iterate over the given parameters and add them to the given prepared statement.
* Only a select number of datatypes are supported by the JDBC driver. * Only a select number of datatypes are supported by the JDBC driver.
* *
* @param statement * @param statement
@@ -1712,7 +1743,7 @@ public class DatabaseManager
{ {
params.add(col); params.add(col);
} }
} }
} }
PreparedStatement statement = null; PreparedStatement statement = null;

View File

@@ -11,9 +11,9 @@ import java.io.File;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.io.FileReader; import java.io.FileReader;
import java.io.IOException; import java.io.IOException;
import java.util.Locale;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import org.dspace.utils.DSpace;
/** /**
* Command-line executed class for initializing the DSpace database. This should * Command-line executed class for initializing the DSpace database. This should
@@ -25,7 +25,7 @@ import org.dspace.utils.DSpace;
public class InitializeDatabase public class InitializeDatabase
{ {
/** log4j category */ /** log4j category */
private static Logger log = Logger.getLogger(InitializeDatabase.class); private static final Logger log = Logger.getLogger(InitializeDatabase.class);
public static void main(String[] argv) public static void main(String[] argv)
{ {
@@ -61,13 +61,13 @@ public class InitializeDatabase
/** /**
* Attempt to get the named script, with the following rules: * Attempt to get the named script, with the following rules:
* etc/<db.name>/<name> * etc/<DBMS name>/<name>
* etc/<name> * etc/<name>
* <name> * <name>
*/ */
private static FileReader getScript(String name) throws FileNotFoundException, IOException private static FileReader getScript(String name) throws FileNotFoundException, IOException
{ {
String dbName = new DSpace().getConfigurationService().getProperty("db.name") ; String dbName = DatabaseManager.getDbName().toLowerCase(Locale.ROOT);
File myFile = null; File myFile = null;

View File

@@ -10,7 +10,6 @@ package org.dspace.xmlworkflow.storedcomponents;
import org.dspace.content.Collection; import org.dspace.content.Collection;
import org.dspace.content.Item; import org.dspace.content.Item;
import org.dspace.content.InProgressSubmission; import org.dspace.content.InProgressSubmission;
import org.dspace.core.ConfigurationManager;
import org.dspace.core.Context; import org.dspace.core.Context;
import org.dspace.core.LogManager; import org.dspace.core.LogManager;
import org.dspace.storage.rdbms.TableRow; import org.dspace.storage.rdbms.TableRow;
@@ -40,15 +39,15 @@ public class XmlWorkflowItem implements InProgressSubmission {
/* /*
* The current step in the workflow system in which this workflow item is present * The current step in the workflow system in which this workflow item is present
*/ */
private static Logger log = Logger.getLogger(XmlWorkflowItem.class); private static final Logger log = Logger.getLogger(XmlWorkflowItem.class);
private Collection collection; private Collection collection;
private Item item; private Item item;
private TableRow wfRow; private final TableRow wfRow;
private Context ourContext; private final Context ourContext;
public static XmlWorkflowItem create(Context context) throws AuthorizeException, IOException, SQLException { public static XmlWorkflowItem create(Context context) throws AuthorizeException, IOException, SQLException {
@@ -181,7 +180,7 @@ public class XmlWorkflowItem implements InProgressSubmission {
query.append("WHERE collection_id=").append(collectionId); query.append("WHERE collection_id=").append(collectionId);
} }
int offset = (page - 1) * pagesize; int offset = (page - 1) * pagesize;
if ("oracle".equals(ConfigurationManager.getProperty("db.name"))) { if (DatabaseManager.isOracle()) {
// First prepare the query to generate row numbers // First prepare the query to generate row numbers
if (pagesize > 0 || offset > 0) { if (pagesize > 0 || offset > 0) {
query.insert(0, "SELECT /*+ FIRST_ROWS(n) */ rec.*, ROWNUM rnum FROM ("); query.insert(0, "SELECT /*+ FIRST_ROWS(n) */ rec.*, ROWNUM rnum FROM (");

View File

@@ -0,0 +1,684 @@
/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
*
* http://www.dspace.org/license/
*/
package org.dspace.storage.rdbms;
import org.dspace.AbstractUnitTest;
import org.junit.After;
import org.junit.AfterClass;
import static org.junit.Assert.*;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
/**
*
* @author mhwood
*/
public class DatabaseManagerTest
extends AbstractUnitTest
{
public DatabaseManagerTest()
{
}
@BeforeClass
public static void setUpClass()
{
}
@AfterClass
public static void tearDownClass()
{
}
@Before
public void setUp()
{
}
@After
public void tearDown()
{
}
/**
* Test of isOracle method, of class DatabaseManager.
*/
@Test
public void testIsOracle()
{
System.out.println("isOracle");
boolean expResult = true;
boolean result = DatabaseManager.isOracle();
assertEquals(expResult, result);
}
/**
* Test of setConstraintDeferred method, of class DatabaseManager.
*/
/*
@Test
public void testSetConstraintDeferred() throws Exception
{
System.out.println("setConstraintDeferred");
Context context = null;
String constraintName = "";
DatabaseManager.setConstraintDeferred(context, constraintName);
// TODO review the generated test code and remove the default call to fail.
fail("The test case is a prototype.");
}
*/
/**
* Test of setConstraintImmediate method, of class DatabaseManager.
*/
/*
@Test
public void testSetConstraintImmediate() throws Exception
{
System.out.println("setConstraintImmediate");
Context context = null;
String constraintName = "";
DatabaseManager.setConstraintImmediate(context, constraintName);
// TODO review the generated test code and remove the default call to fail.
fail("The test case is a prototype.");
}
*/
/**
* Test of queryTable method, of class DatabaseManager.
*/
/*
@Test
public void testQueryTable() throws Exception
{
System.out.println("queryTable");
Context context = null;
String table = "";
String query = "";
Object[] parameters = null;
TableRowIterator expResult = null;
TableRowIterator result = DatabaseManager.queryTable(context, table,
query, parameters);
assertEquals(expResult, result);
// TODO review the generated test code and remove the default call to fail.
fail("The test case is a prototype.");
}
*/
/**
* Test of query method, of class DatabaseManager.
*/
/*
@Test
public void testQuery() throws Exception
{
System.out.println("query");
Context context = null;
String query = "";
Object[] parameters = null;
TableRowIterator expResult = null;
TableRowIterator result = DatabaseManager.query(context, query,
parameters);
assertEquals(expResult, result);
// TODO review the generated test code and remove the default call to fail.
fail("The test case is a prototype.");
}
*/
/**
* Test of querySingle method, of class DatabaseManager.
*/
/*
@Test
public void testQuerySingle() throws Exception
{
System.out.println("querySingle");
Context context = null;
String query = "";
Object[] parameters = null;
TableRow expResult = null;
TableRow result = DatabaseManager.querySingle(context, query, parameters);
assertEquals(expResult, result);
// TODO review the generated test code and remove the default call to fail.
fail("The test case is a prototype.");
}
*/
/**
* Test of querySingleTable method, of class DatabaseManager.
*/
/*
@Test
public void testQuerySingleTable() throws Exception
{
System.out.println("querySingleTable");
Context context = null;
String table = "";
String query = "";
Object[] parameters = null;
TableRow expResult = null;
TableRow result = DatabaseManager.querySingleTable(context, table, query,
parameters);
assertEquals(expResult, result);
// TODO review the generated test code and remove the default call to fail.
fail("The test case is a prototype.");
}
*/
/**
* Test of updateQuery method, of class DatabaseManager.
*/
/*
@Test
public void testUpdateQuery() throws Exception
{
System.out.println("updateQuery");
Context context = null;
String query = "";
Object[] parameters = null;
int expResult = 0;
int result = DatabaseManager.updateQuery(context, query, parameters);
assertEquals(expResult, result);
// TODO review the generated test code and remove the default call to fail.
fail("The test case is a prototype.");
}
*/
/**
* Test of create method, of class DatabaseManager.
*/
/*
@Test
public void testCreate() throws Exception
{
System.out.println("create");
Context context = null;
String table = "";
TableRow expResult = null;
TableRow result = DatabaseManager.create(context, table);
assertEquals(expResult, result);
// TODO review the generated test code and remove the default call to fail.
fail("The test case is a prototype.");
}
*/
/**
* Test of find method, of class DatabaseManager.
*/
/*
@Test
public void testFind() throws Exception
{
System.out.println("find");
Context context = null;
String table = "";
int id = 0;
TableRow expResult = null;
TableRow result = DatabaseManager.find(context, table, id);
assertEquals(expResult, result);
// TODO review the generated test code and remove the default call to fail.
fail("The test case is a prototype.");
}
*/
/**
* Test of findByUnique method, of class DatabaseManager.
*/
/*
@Test
public void testFindByUnique() throws Exception
{
System.out.println("findByUnique");
Context context = null;
String table = "";
String column = "";
Object value = null;
TableRow expResult = null;
TableRow result = DatabaseManager.findByUnique(context, table, column,
value);
assertEquals(expResult, result);
// TODO review the generated test code and remove the default call to fail.
fail("The test case is a prototype.");
}
*/
/**
* Test of delete method, of class DatabaseManager.
*/
/*
@Test
public void testDelete_3args() throws Exception
{
System.out.println("delete");
Context context = null;
String table = "";
int id = 0;
int expResult = 0;
int result = DatabaseManager.delete(context, table, id);
assertEquals(expResult, result);
// TODO review the generated test code and remove the default call to fail.
fail("The test case is a prototype.");
}
*/
/**
* Test of deleteByValue method, of class DatabaseManager.
*/
/*
@Test
public void testDeleteByValue() throws Exception
{
System.out.println("deleteByValue");
Context context = null;
String table = "";
String column = "";
Object value = null;
int expResult = 0;
int result = DatabaseManager.deleteByValue(context, table, column, value);
assertEquals(expResult, result);
// TODO review the generated test code and remove the default call to fail.
fail("The test case is a prototype.");
}
*/
/**
* Test of getConnection method, of class DatabaseManager.
*/
/*
@Test
public void testGetConnection() throws Exception
{
System.out.println("getConnection");
Connection expResult = null;
Connection result = DatabaseManager.getConnection();
assertEquals(expResult, result);
// TODO review the generated test code and remove the default call to fail.
fail("The test case is a prototype.");
}
*/
/**
* Test of getDataSource method, of class DatabaseManager.
*/
/*
@Test
public void testGetDataSource()
{
System.out.println("getDataSource");
DataSource expResult = null;
DataSource result = DatabaseManager.getDataSource();
assertEquals(expResult, result);
// TODO review the generated test code and remove the default call to fail.
fail("The test case is a prototype.");
}
*/
/**
* Test of freeConnection method, of class DatabaseManager.
*/
/*
@Test
public void testFreeConnection()
{
System.out.println("freeConnection");
Connection c = null;
DatabaseManager.freeConnection(c);
// TODO review the generated test code and remove the default call to fail.
fail("The test case is a prototype.");
}
*/
/**
* Test of row method, of class DatabaseManager.
*/
/*
@Test
public void testRow() throws Exception
{
System.out.println("row");
String table = "";
TableRow expResult = null;
TableRow result = DatabaseManager.row(table);
assertEquals(expResult, result);
// TODO review the generated test code and remove the default call to fail.
fail("The test case is a prototype.");
}
*/
/**
* Test of insert method, of class DatabaseManager.
*/
/*
@Test
public void testInsert() throws Exception
{
System.out.println("insert");
Context context = null;
TableRow row = null;
DatabaseManager.insert(context, row);
// TODO review the generated test code and remove the default call to fail.
fail("The test case is a prototype.");
}
*/
/**
* Test of update method, of class DatabaseManager.
*/
/*
@Test
public void testUpdate() throws Exception
{
System.out.println("update");
Context context = null;
TableRow row = null;
int expResult = 0;
int result = DatabaseManager.update(context, row);
assertEquals(expResult, result);
// TODO review the generated test code and remove the default call to fail.
fail("The test case is a prototype.");
}
*/
/**
* Test of delete method, of class DatabaseManager.
*/
/*
@Test
public void testDelete_Context_TableRow() throws Exception
{
System.out.println("delete");
Context context = null;
TableRow row = null;
int expResult = 0;
int result = DatabaseManager.delete(context, row);
assertEquals(expResult, result);
// TODO review the generated test code and remove the default call to fail.
fail("The test case is a prototype.");
}
*/
/**
* Test of getColumnInfo method, of class DatabaseManager.
*/
/*
@Test
public void testGetColumnInfo_String() throws Exception
{
System.out.println("getColumnInfo");
String table = "";
Collection<ColumnInfo> expResult = null;
Collection<ColumnInfo> result = DatabaseManager.getColumnInfo(table);
assertEquals(expResult, result);
// TODO review the generated test code and remove the default call to fail.
fail("The test case is a prototype.");
}
*/
/**
* Test of getColumnInfo method, of class DatabaseManager.
*/
/*
@Test
public void testGetColumnInfo_String_String() throws Exception
{
System.out.println("getColumnInfo");
String table = "";
String column = "";
ColumnInfo expResult = null;
ColumnInfo result = DatabaseManager.getColumnInfo(table, column);
assertEquals(expResult, result);
// TODO review the generated test code and remove the default call to fail.
fail("The test case is a prototype.");
}
*/
/**
* Test of getColumnNames method, of class DatabaseManager.
*/
/*
@Test
public void testGetColumnNames_String() throws Exception
{
System.out.println("getColumnNames");
String table = "";
List<String> expResult = null;
List<String> result = DatabaseManager.getColumnNames(table);
assertEquals(expResult, result);
// TODO review the generated test code and remove the default call to fail.
fail("The test case is a prototype.");
}
*/
/**
* Test of getColumnNames method, of class DatabaseManager.
*/
/*
@Test
public void testGetColumnNames_ResultSetMetaData() throws Exception
{
System.out.println("getColumnNames");
ResultSetMetaData meta = null;
List<String> expResult = null;
List<String> result = DatabaseManager.getColumnNames(meta);
assertEquals(expResult, result);
// TODO review the generated test code and remove the default call to fail.
fail("The test case is a prototype.");
}
*/
/**
* Test of canonicalize method, of class DatabaseManager.
*/
/*
@Test
public void testCanonicalize()
{
System.out.println("canonicalize");
String table = "";
String expResult = "";
String result = DatabaseManager.canonicalize(table);
assertEquals(expResult, result);
// TODO review the generated test code and remove the default call to fail.
fail("The test case is a prototype.");
}
*/
/**
* Test of loadSql method, of class DatabaseManager.
*/
/*
@Test
public void testLoadSql_String() throws Exception
{
System.out.println("loadSql");
String sql = "";
DatabaseManager.loadSql(sql);
// TODO review the generated test code and remove the default call to fail.
fail("The test case is a prototype.");
}
*/
/**
* Test of loadSql method, of class DatabaseManager.
*/
/*
@Test
public void testLoadSql_Reader() throws Exception
{
System.out.println("loadSql");
Reader r = null;
DatabaseManager.loadSql(r);
// TODO review the generated test code and remove the default call to fail.
fail("The test case is a prototype.");
}
*/
/**
* Test of process method, of class DatabaseManager.
*/
/*
@Test
public void testProcess_ResultSet_String() throws Exception
{
System.out.println("process");
ResultSet results = null;
String table = "";
TableRow expResult = null;
TableRow result = DatabaseManager.process(results, table);
assertEquals(expResult, result);
// TODO review the generated test code and remove the default call to fail.
fail("The test case is a prototype.");
}
*/
/**
* Test of process method, of class DatabaseManager.
*/
/*
@Test
public void testProcess_3args() throws Exception
{
System.out.println("process");
ResultSet results = null;
String table = "";
List<String> pColumnNames = null;
TableRow expResult = null;
TableRow result = DatabaseManager.process(results, table, pColumnNames);
assertEquals(expResult, result);
// TODO review the generated test code and remove the default call to fail.
fail("The test case is a prototype.");
}
*/
/**
* Test of getPrimaryKeyColumn method, of class DatabaseManager.
*/
/*
@Test
public void testGetPrimaryKeyColumn_TableRow() throws Exception
{
System.out.println("getPrimaryKeyColumn");
TableRow row = null;
String expResult = "";
String result = DatabaseManager.getPrimaryKeyColumn(row);
assertEquals(expResult, result);
// TODO review the generated test code and remove the default call to fail.
fail("The test case is a prototype.");
}
*/
/**
* Test of getPrimaryKeyColumn method, of class DatabaseManager.
*/
/*
@Test
public void testGetPrimaryKeyColumn_String() throws Exception
{
System.out.println("getPrimaryKeyColumn");
String table = "";
String expResult = "";
String result = DatabaseManager.getPrimaryKeyColumn(table);
assertEquals(expResult, result);
// TODO review the generated test code and remove the default call to fail.
fail("The test case is a prototype.");
}
*/
/**
* Test of getPrimaryKeyColumnInfo method, of class DatabaseManager.
*/
/*
@Test
public void testGetPrimaryKeyColumnInfo() throws Exception
{
System.out.println("getPrimaryKeyColumnInfo");
String table = "";
ColumnInfo expResult = null;
ColumnInfo result = DatabaseManager.getPrimaryKeyColumnInfo(table);
assertEquals(expResult, result);
// TODO review the generated test code and remove the default call to fail.
fail("The test case is a prototype.");
}
*/
/**
* Test of shutdown method, of class DatabaseManager.
*/
/*
@Test
public void testShutdown() throws Exception
{
System.out.println("shutdown");
DatabaseManager.shutdown();
// TODO review the generated test code and remove the default call to fail.
fail("The test case is a prototype.");
}
*/
/**
* Test of getDbName method, of class DatabaseManager.
*/
@Test
public void testGetDbName()
{
System.out.println("getDbName");
String expResult = "H2";
String result = DatabaseManager.getDbName();
assertEquals(expResult, result);
}
/**
* Test of loadParameters method, of class DatabaseManager.
*/
/*
@Test
public void testLoadParameters() throws Exception
{
System.out.println("loadParameters");
PreparedStatement statement = null;
Object[] parameters = null;
DatabaseManager.loadParameters(statement, parameters);
// TODO review the generated test code and remove the default call to fail.
fail("The test case is a prototype.");
}
*/
/**
* Test of main method, of class DatabaseManager.
*/
/*
@Test
public void testMain()
{
System.out.println("main");
String[] args = null;
DatabaseManager.main(args);
// TODO review the generated test code and remove the default call to fail.
fail("The test case is a prototype.");
}
*/
/**
* Test of applyOffsetAndLimit method, of class DatabaseManager.
*/
/*
@Test
public void testApplyOffsetAndLimit()
{
System.out.println("applyOffsetAndLimit");
StringBuffer query = null;
List<Serializable> params = null;
int offset = 0;
int limit = 0;
DatabaseManager.applyOffsetAndLimit(query, params, offset, limit);
// TODO review the generated test code and remove the default call to fail.
fail("The test case is a prototype.");
}
*/
}

View File

@@ -14,7 +14,6 @@ import java.sql.Statement;
import java.sql.Types; import java.sql.Types;
import java.util.List; import java.util.List;
import mockit.Deencapsulation;
import mockit.Mock; import mockit.Mock;
import mockit.MockUp; import mockit.MockUp;
@@ -35,16 +34,14 @@ public final class MockDatabaseManager
{ {
// Set our logger to specify the Mock class, so we know which logs are from the "real" vs "mock" class // Set our logger to specify the Mock class, so we know which logs are from the "real" vs "mock" class
private static final Logger log = Logger.getLogger(MockDatabaseManager.class); private static final Logger log = Logger.getLogger(MockDatabaseManager.class);
// Get the values of private static variables 'isOracle' and 'isPostgres' from /** Is our DBMS Oracle-like? */
// DatabaseManager itself (by using Deencapsulation) private static final boolean isOracle = DatabaseManager.isOracle();
private static final boolean isOracle = Deencapsulation.getField(DatabaseManager.class, "isOracle");
private static final boolean isPostgres = Deencapsulation.getField(DatabaseManager.class, "isPostgres");
/** /**
* Override/Mock the default "setConstraintDeferred()" method in order to * Override/Mock the default "setConstraintDeferred()" method in order to
* add some custom H2-specific code (look for the comments with "H2" in them). * add some custom H2-specific code (look for the comments with "H2" in them).
* *
* Set the constraint check to deferred (commit time) * Set the constraint check to deferred (commit time)
* *
* @param context * @param context
@@ -58,13 +55,13 @@ public final class MockDatabaseManager
String constraintName) throws SQLException String constraintName) throws SQLException
{ {
log.debug("Mocked setContraintDeferred() method for H2 database"); log.debug("Mocked setContraintDeferred() method for H2 database");
Statement statement = null; Statement statement = null;
try try
{ {
statement = context.getDBConnection().createStatement(); statement = context.getDBConnection().createStatement();
//statement.execute("SET CONSTRAINTS " + constraintName + " DEFERRED"); //statement.execute("SET CONSTRAINTS " + constraintName + " DEFERRED");
// H2 does NOT support "SET CONSTRAINTS" syntax. // H2 does NOT support "SET CONSTRAINTS" syntax.
// Instead it requires the following SQL // Instead it requires the following SQL
statement.execute("SET REFERENTIAL_INTEGRITY FALSE"); statement.execute("SET REFERENTIAL_INTEGRITY FALSE");
statement.close(); statement.close();
@@ -84,11 +81,11 @@ public final class MockDatabaseManager
} }
} }
} }
/** /**
* Override/Mock the default "setConstraintImmediate()" method in order to * Override/Mock the default "setConstraintImmediate()" method in order to
* add some custom H2-specific code (look for the comments with "H2" in them). * add some custom H2-specific code (look for the comments with "H2" in them).
* *
* Set the constraint check to immediate (every query) * Set the constraint check to immediate (every query)
* *
* @param context * @param context
@@ -102,13 +99,13 @@ public final class MockDatabaseManager
String constraintName) throws SQLException String constraintName) throws SQLException
{ {
log.debug("Mocked setContraintImmediate() method for H2 database"); log.debug("Mocked setContraintImmediate() method for H2 database");
Statement statement = null; Statement statement = null;
try try
{ {
statement = context.getDBConnection().createStatement(); statement = context.getDBConnection().createStatement();
//statement.execute("SET CONSTRAINTS " + constraintName + " IMMEDIATE"); //statement.execute("SET CONSTRAINTS " + constraintName + " IMMEDIATE");
// H2 does NOT support "SET CONSTRAINTS" syntax. // H2 does NOT support "SET CONSTRAINTS" syntax.
// Instead it requires the following SQL // Instead it requires the following SQL
statement.execute("SET REFERENTIAL_INTEGRITY TRUE"); statement.execute("SET REFERENTIAL_INTEGRITY TRUE");
statement.close(); statement.close();
@@ -127,11 +124,11 @@ public final class MockDatabaseManager
} }
} }
} }
/** /**
* Override/Mock the default "process()" method in order to add some custom * Override/Mock the default "process()" method in order to add some custom
* H2-specific code (look for the comments with "H2" in them below). * H2-specific code (look for the comments with "H2" in them below).
* *
* Convert the current row in a ResultSet into a TableRow object. * Convert the current row in a ResultSet into a TableRow object.
* *
* @param results * @param results
@@ -149,7 +146,7 @@ public final class MockDatabaseManager
{ {
// Added for H2 debugging // Added for H2 debugging
log.debug("Mocked process() method for H2 database"); log.debug("Mocked process() method for H2 database");
ResultSetMetaData meta = results.getMetaData(); ResultSetMetaData meta = results.getMetaData();
int columns = meta.getColumnCount() + 1; int columns = meta.getColumnCount() + 1;
@@ -239,7 +236,7 @@ public final class MockDatabaseManager
{ {
log.error("Unable to parse text from database", e); log.error("Unable to parse text from database", e);
}*/ }*/
// H2 assumes that "getBytes()" should return hexidecimal. // H2 assumes that "getBytes()" should return hexidecimal.
// So, the above commented out code will throw a JdbcSQLException: // So, the above commented out code will throw a JdbcSQLException:
// "Hexadecimal string contains non-hex character" // "Hexadecimal string contains non-hex character"

View File

@@ -10,9 +10,12 @@ package org.dspace.xoai.services.impl.database;
import com.lyncode.xoai.dataprovider.filter.Scope; import com.lyncode.xoai.dataprovider.filter.Scope;
import com.lyncode.xoai.dataprovider.filter.ScopedFilter; import com.lyncode.xoai.dataprovider.filter.ScopedFilter;
import com.lyncode.xoai.dataprovider.filter.conditions.Condition; import com.lyncode.xoai.dataprovider.filter.conditions.Condition;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.apache.log4j.LogManager; import org.apache.log4j.LogManager;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import org.dspace.storage.rdbms.DatabaseManager;
import org.dspace.xoai.services.api.config.ConfigurationService; import org.dspace.xoai.services.api.config.ConfigurationService;
import org.dspace.xoai.services.api.context.ContextService; import org.dspace.xoai.services.api.context.ContextService;
import org.dspace.xoai.services.api.context.ContextServiceException; import org.dspace.xoai.services.api.context.ContextServiceException;
@@ -22,11 +25,8 @@ import org.dspace.xoai.services.api.database.DatabaseQueryResolver;
import org.dspace.xoai.services.api.xoai.DSpaceFilterResolver; import org.dspace.xoai.services.api.xoai.DSpaceFilterResolver;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import java.util.ArrayList;
import java.util.List;
public class DSpaceDatabaseQueryResolver implements DatabaseQueryResolver { public class DSpaceDatabaseQueryResolver implements DatabaseQueryResolver {
private static Logger log = LogManager.getLogger(DSpaceDatabaseQueryResolver.class); private static final Logger log = LogManager.getLogger(DSpaceDatabaseQueryResolver.class);
@Autowired @Autowired
DSpaceFilterResolver filterResolver; DSpaceFilterResolver filterResolver;
@@ -61,10 +61,7 @@ public class DSpaceDatabaseQueryResolver implements DatabaseQueryResolver {
} }
query += " ORDER BY i.item_id"; query += " ORDER BY i.item_id";
String db = configurationService.getProperty("db.name"); boolean postgres = ! DatabaseManager.isOracle();
boolean postgres = true;
// Assuming Postgres as default
if ("oracle".equals(db)) postgres = false;
if (postgres) if (postgres)
{ {
query += " OFFSET ? LIMIT ?"; query += " OFFSET ? LIMIT ?";

View File

@@ -13,7 +13,6 @@ import org.dspace.core.Context;
import org.dspace.storage.rdbms.DatabaseManager; import org.dspace.storage.rdbms.DatabaseManager;
import org.dspace.storage.rdbms.TableRowIterator; import org.dspace.storage.rdbms.TableRowIterator;
import org.dspace.xoai.exceptions.InvalidMetadataFieldException; import org.dspace.xoai.exceptions.InvalidMetadataFieldException;
import org.dspace.xoai.services.api.config.ConfigurationService;
import org.dspace.xoai.services.api.database.EarliestDateResolver; import org.dspace.xoai.services.api.database.EarliestDateResolver;
import org.dspace.xoai.services.api.database.FieldResolver; import org.dspace.xoai.services.api.database.FieldResolver;
import org.dspace.xoai.util.DateUtils; import org.dspace.xoai.util.DateUtils;
@@ -23,22 +22,15 @@ import java.sql.SQLException;
import java.util.Date; import java.util.Date;
public class DSpaceEarliestDateResolver implements EarliestDateResolver { public class DSpaceEarliestDateResolver implements EarliestDateResolver {
private static Logger log = LogManager.getLogger(DSpaceEarliestDateResolver.class); private static final Logger log = LogManager.getLogger(DSpaceEarliestDateResolver.class);
@Autowired @Autowired
private FieldResolver fieldResolver; private FieldResolver fieldResolver;
@Autowired
private ConfigurationService configurationService;
@Override @Override
public Date getEarliestDate(Context context) throws InvalidMetadataFieldException, SQLException { public Date getEarliestDate(Context context) throws InvalidMetadataFieldException, SQLException {
String query = "SELECT MIN(text_value) as value FROM metadatavalue WHERE metadata_field_id = ?"; String query = "SELECT MIN(text_value) as value FROM metadatavalue WHERE metadata_field_id = ?";
String db = configurationService.getProperty("db.name"); boolean postgres = ! DatabaseManager.isOracle();
boolean postgres = true;
// Assuming Postgres as default
if ("oracle".equals(db))
postgres = false;
if (!postgres) { if (!postgres) {
query = "SELECT MIN(TO_CHAR(text_value)) as value FROM metadatavalue WHERE metadata_field_id = ?"; query = "SELECT MIN(TO_CHAR(text_value)) as value FROM metadatavalue WHERE metadata_field_id = ?";

View File

@@ -15,7 +15,6 @@ import java.util.Comparator;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
import org.apache.avalon.framework.activity.Disposable; import org.apache.avalon.framework.activity.Disposable;
import org.apache.avalon.framework.service.ServiceException; import org.apache.avalon.framework.service.ServiceException;
import org.apache.avalon.framework.service.ServiceManager; import org.apache.avalon.framework.service.ServiceManager;
@@ -42,10 +41,11 @@ import org.dspace.app.xmlui.wing.element.Table;
import org.dspace.app.xmlui.wing.element.TextArea; import org.dspace.app.xmlui.wing.element.TextArea;
import org.dspace.authorize.AuthorizeException; import org.dspace.authorize.AuthorizeException;
import org.dspace.authorize.AuthorizeManager; import org.dspace.authorize.AuthorizeManager;
import org.dspace.harvest.HarvestedCollection;
import org.dspace.harvest.OAIHarvester.HarvestScheduler;
import org.dspace.core.ConfigurationManager; import org.dspace.core.ConfigurationManager;
import org.dspace.eperson.EPerson; import org.dspace.eperson.EPerson;
import org.dspace.harvest.HarvestedCollection;
import org.dspace.harvest.OAIHarvester.HarvestScheduler;
import org.dspace.storage.rdbms.DatabaseManager;
import org.xml.sax.SAXException; import org.xml.sax.SAXException;
/** /**
@@ -510,7 +510,7 @@ public class ControlPanel extends AbstractDSpaceTransformer implements Serviceab
dspace.addItem(notnull(ConfigurationManager.getProperty("dspace.name"))); dspace.addItem(notnull(ConfigurationManager.getProperty("dspace.name")));
dspace.addLabel(T_DB_NAME); dspace.addLabel(T_DB_NAME);
dspace.addItem(notnull(ConfigurationManager.getProperty("db.name"))); dspace.addItem(notnull(DatabaseManager.getDbName()));
dspace.addLabel(T_DB_URL); dspace.addLabel(T_DB_URL);
dspace.addItem(notnull(ConfigurationManager.getProperty("db.url"))); dspace.addItem(notnull(ConfigurationManager.getProperty("db.url")));

View File

@@ -50,9 +50,6 @@ default.language = ${default.language}
##### Database settings ##### ##### Database settings #####
# Database name ("oracle", or "postgres")
db.name = ${db.name}
# URL for connecting to database # URL for connecting to database
db.url = ${db.url} db.url = ${db.url}
@@ -89,7 +86,7 @@ db.poolname = ${db.poolname}
# Specify a configured database connection pool to be fetched from a # Specify a configured database connection pool to be fetched from a
# directory. This overrides the pool and driver settings above. If # directory. This overrides the pool and driver settings above. If
# none can be found, then DSpace will use the above settings to create a # none can be found, then DSpace will use the above settings to create a
# pool. db.name should be specified regardless. # pool.
#db.jndi = jdbc/dspace #db.jndi = jdbc/dspace
##### Email settings ###### ##### Email settings ######

View File

@@ -7,9 +7,8 @@ Revision: 11-sep-04 dstuve
Oracle Porting Notes for the Curious Oracle Porting Notes for the Curious
Oracle is missing quite a number of cool features found in Postgres, so Oracle is missing quite a number of cool features found in Postgres, so
workarounds had to be found, most of which are hidden behind tests of workarounds had to be found, most of which are hidden behind tests in
the db.name configuration parameter in dspace.cfg. If the db.name is DatabaseManager. If Oracle is your DBMS, the workarounds are activated:
set to Oracle the workarounds are activated:
Oracle doesn't like ';' characters in JDBC SQL - they have all been removed Oracle doesn't like ';' characters in JDBC SQL - they have all been removed
from the DSpace source, including code in the .sql file reader to strip ;'s. from the DSpace source, including code in the .sql file reader to strip ;'s.
@@ -18,8 +17,8 @@ browse code - LIMIT and OFFSET is used to limit browse results, and an
Oracle-hack is used to limit the result set to a given size Oracle-hack is used to limit the result set to a given size
Oracle has no boolean data type, so a new schema file was created that Oracle has no boolean data type, so a new schema file was created that
uses NUMBER(1) (AKA 'integers') and code is inserted everywhere to use 0 for false uses NUMBER(1) (AKA 'integers') and code is inserted everywhere to use 0 for
and 1 for true if the db.name is Oracle false and 1 for true if DSpace is using Oracle.
Oracle doesn't have a TEXT data type either, so TEXT columns are defined Oracle doesn't have a TEXT data type either, so TEXT columns are defined
as VARCHAR2 in the Oracle-specific schema. as VARCHAR2 in the Oracle-specific schema.