com.hfg.sql.table.DatabaseTable Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of com_hfg Show documentation
Show all versions of com_hfg Show documentation
com.hfg xml, html, svg, and bioinformatics utility library
package com.hfg.sql.table;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.function.Function;
import com.hfg.exception.ProgrammingException;
import com.hfg.sql.SQLClause;
import com.hfg.sql.SQLQuery;
import com.hfg.sql.SQLUtil;
import com.hfg.sql.WhereClause;
import com.hfg.sql.jdbc.JDBCException;
import com.hfg.sql.jdbc.RDBMS;
import com.hfg.sql.jdbc.SQLStatementOptions;
import com.hfg.sql.jdbc.Schema;
import com.hfg.util.CompareUtil;
import com.hfg.util.StringBuilderPlus;
import com.hfg.util.collection.CollectionUtil;
import com.hfg.util.StringUtil;
//------------------------------------------------------------------------------
/**
Database table object.
@author J. Alex Taylor, hairyfatguy.com
*/
//------------------------------------------------------------------------------
// com.hfg XML/HTML Coding Library
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// J. Alex Taylor, President, Founder, CEO, COO, CFO, OOPS hairyfatguy.com
// [email protected]
//------------------------------------------------------------------------------
public class DatabaseTable implements Cloneable, Comparable>
{
private String mName;
private String mAlias;
private Schema mSchema;
private RDBMS mRDBMS = sDefaultRDBMS;
private List mCols;
private Function mResultSetConstructorFn;
private String mCachedQualifiedName;
private static RDBMS sDefaultRDBMS = RDBMS.PostgreSQL;
//###########################################################################
// CONSTRUCTORS
//###########################################################################
//---------------------------------------------------------------------------
public DatabaseTable(String inName, Function inResultSetConstructorFn)
{
mName = inName;
mResultSetConstructorFn = inResultSetConstructorFn;
}
//###########################################################################
// PUBLIC METHODS
//###########################################################################
//---------------------------------------------------------------------------
public static void setDefaultRDBMS(RDBMS inValue)
{
if (null == inValue)
{
throw new JDBCException("The default RDBMS cannot be set to null!");
}
sDefaultRDBMS = inValue;
}
//---------------------------------------------------------------------------
public static RDBMS getDefaultRDBMS()
{
return sDefaultRDBMS;
}
//---------------------------------------------------------------------------
public DatabaseTable setRDBMS(RDBMS inValue)
{
mRDBMS = inValue;
return this;
}
//---------------------------------------------------------------------------
public RDBMS getRDBMS()
{
return mRDBMS;
}
//---------------------------------------------------------------------------
@Override
public int compareTo(DatabaseTable inObj2)
{
int result = 1;
if (inObj2 != null)
{
result = CompareUtil.compare(getQualifiedName(), inObj2.getQualifiedName());
}
return result;
}
//---------------------------------------------------------------------------
@Override
public boolean equals(Object inObj2)
{
return (inObj2 != null
&& inObj2 instanceof DatabaseTable
&& 0 == compareTo((DatabaseTable) inObj2));
}
//---------------------------------------------------------------------------
@Override
public int hashCode()
{
return getQualifiedName().hashCode();
}
//---------------------------------------------------------------------------
public DatabaseTable setName(String inValue)
{
mName = inValue;
mCachedQualifiedName = null;
return this;
}
//---------------------------------------------------------------------------
public String name()
{
return mName;
}
//---------------------------------------------------------------------------
public String getQualifiedName()
{
if (null == mCachedQualifiedName)
{
mCachedQualifiedName = (mSchema != null ? mSchema.name() + "." : "") + name();
}
return mCachedQualifiedName;
}
//---------------------------------------------------------------------------
@Override
public String toString()
{
return getQualifiedName();
}
//---------------------------------------------------------------------------
public DatabaseTable clone()
{
DatabaseTable clone;
try
{
clone = (DatabaseTable) super.clone();
}
catch (CloneNotSupportedException e)
{
throw new ProgrammingException(e);
}
for (DatabaseCol col : getCols())
{
clone.addCol(col.clone());
}
return clone;
}
//---------------------------------------------------------------------------
public DatabaseTable setAlias(String inValue)
{
mAlias = inValue;
return this;
}
//---------------------------------------------------------------------------
public String getAlias()
{
return mAlias;
}
//---------------------------------------------------------------------------
public DatabaseTable setSchema(Schema inValue)
{
mSchema = inValue;
mCachedQualifiedName = null;
return this;
}
//---------------------------------------------------------------------------
public Schema getSchema()
{
return mSchema;
}
//---------------------------------------------------------------------------
public List getCols()
{
return Collections.unmodifiableList(mCols);
}
//---------------------------------------------------------------------------
public DatabaseCol getCol(String inColName)
{
DatabaseCol requestedCol = null;
if (mCols != null)
{
for (DatabaseCol col : mCols)
{
if (col.name().equalsIgnoreCase(inColName))
{
requestedCol = col;
break;
}
}
}
return requestedCol;
}
//---------------------------------------------------------------------------
public Collection getTaggedCols(String inTag)
{
Collection taggedCols = null;
if (mCols != null)
{
for (DatabaseCol col : mCols)
{
if (col.tagged(inTag))
{
if (null == taggedCols)
{
taggedCols = new ArrayList<>(4);
}
taggedCols.add(col);
}
}
}
return taggedCols;
}
//---------------------------------------------------------------------------
public void addCol(DatabaseCol inCol)
{
if (null == mCols)
{
mCols = new ArrayList<>(50);
}
if (! mCols.contains(inCol))
{
mCols.add(inCol);
}
inCol.setTable(this);
}
//---------------------------------------------------------------------------
public DatabaseCol getIdCol()
{
DatabaseCol idCol = null;
if (mCols != null)
{
for (DatabaseCol col : mCols)
{
if (col.isId())
{
idCol = col;
break;
}
}
}
return idCol;
}
//---------------------------------------------------------------------------
public T getRow(Connection inConn, SQLQuery inQuery)
throws JDBCException
{
T requestedRow = null;
List rows = getRows(inConn, inQuery);
if (CollectionUtil.hasValues(rows))
{
if (rows.size() > 1)
{
throw new JDBCException(rows.size() + " " + name() + " rows found with query " + StringUtil.singleQuote(inQuery) + "! Expected only one.");
}
requestedRow = rows.get(0);
}
return requestedRow;
}
//---------------------------------------------------------------------------
public T getRow(Connection inConn, List inSQLClauses)
throws JDBCException
{
SQLQuery query = getBaseQuery();
if (CollectionUtil.hasValues(inSQLClauses))
{
for (SQLClause clause : inSQLClauses)
{
query.addClause(clause);
}
}
return getRow(inConn, query);
}
//---------------------------------------------------------------------------
public T getRow(Connection inConn, SQLClause inClause)
throws JDBCException
{
SQLQuery query = getBaseQuery().addClause(inClause);
return getRow(inConn, query);
}
//---------------------------------------------------------------------------
public T getRowById(Connection inConn, Long inId)
throws JDBCException
{
return getRow(inConn, new WhereClause(this.getIdCol() + " = " + inId));
}
//---------------------------------------------------------------------------
public T getRowById(Connection inConn, Integer inId)
throws JDBCException
{
return getRow(inConn, new WhereClause(this.getIdCol() + " = " + inId));
}
//---------------------------------------------------------------------------
public List getRows(Connection inConn)
throws JDBCException
{
return getRows(inConn, (List) null);
}
//---------------------------------------------------------------------------
public List getRows(Connection inConn, List inSQLClauses)
throws JDBCException
{
SQLQuery query = getBaseQuery();
if (CollectionUtil.hasValues(inSQLClauses))
{
for (SQLClause clause : inSQLClauses)
{
query.addClause(clause);
}
}
return getRows(inConn, query);
}
//---------------------------------------------------------------------------
public List getRows(Connection inConn, SQLClause inClause)
throws JDBCException
{
SQLQuery query = getBaseQuery().addClause(inClause);
return getRows(inConn, query);
}
//---------------------------------------------------------------------------
public List getRows(Connection inConn, SQLClause... inClauses)
throws JDBCException
{
SQLQuery query = getBaseQuery();
for (SQLClause clause : inClauses)
{
query.addClause(clause);
}
return getRows(inConn, query);
}
//---------------------------------------------------------------------------
public List getRows(Connection inConn, SQLQuery inQuery)
throws JDBCException
{
return getRows(inConn, inQuery, null);
}
//---------------------------------------------------------------------------
public List getRows(Connection inConn, SQLQuery inQuery, SQLStatementOptions inOptions)
throws JDBCException
{
ArrayList rows = null;
ResultSet rs = null;
try
{
rs = inQuery.execute(inConn, inOptions);
while (rs.next())
{
if (null == rows)
{
rows = new ArrayList();
}
T row = mResultSetConstructorFn.apply(rs);
// Initially blessing the row should no longer be necessary.
// row.bless(); // It's fresh from the database
rows.add(row);
}
if (rows != null)
{
// Don't waste extra capacity in the ArrayList
rows.trimToSize();
}
}
catch (SQLException e)
{
throw new JDBCException("Problem getting rows from " + name() + "!", e);
}
finally
{
SQLUtil.closeResultSetAndStatement(rs);
}
return rows;
}
//---------------------------------------------------------------------------
public int getRowCount(Connection inConn)
throws SQLException
{
return getRowCount(inConn, (Collection) null);
}
//---------------------------------------------------------------------------
public int getRowCount(Connection inConn, SQLClause inClause)
throws SQLException
{
List clauses = new ArrayList<>(1);
clauses.add(inClause);
return getRowCount(inConn, clauses);
}
//---------------------------------------------------------------------------
public int getRowCount(Connection inConn, Collection inSQLClauses)
throws SQLException
{
return SQLUtil.getRowCount(inConn, this, inSQLClauses);
}
//---------------------------------------------------------------------------
public SQLQuery getBaseQuery()
{
SQLQuery query = new SQLQuery();
if (containsColumnsNotRetrievedByDefault())
{
StringBuilderPlus colList = new StringBuilderPlus().setDelimiter(", ");
for (DatabaseCol col : getCols())
{
if (col.getRetrievedByDefault())
{
colList.delimitedAppend(col.name());
}
}
query.addSelect(colList.toString());
}
else
{
query.addSelect((StringUtil.isSet(getAlias()) ? getAlias() + "." : "") + "*");
}
query.addFrom(this);
return query;
}
//---------------------------------------------------------------------------
public boolean exists(Connection inConn)
throws SQLException
{
return getRDBMS().tableExists(inConn, getSchema(), name());
}
//---------------------------------------------------------------------------
public void drop(Connection inConn)
throws SQLException
{
SQLUtil.execute(inConn, "DROP TABLE " + getQualifiedName());
}
//---------------------------------------------------------------------------
public void truncate(Connection inConn)
throws SQLException
{
SQLUtil.execute(inConn, "TRUNCATE TABLE " + getQualifiedName());
}
//---------------------------------------------------------------------------
public void renameTo(Connection inConn, String inNewName)
throws SQLException
{
SQLUtil.execute(inConn, "ALTER TABLE " + getQualifiedName() + " RENAME TO " + inNewName);
}
//---------------------------------------------------------------------------
public List getForeignKeyConstraints(Connection inConn)
throws SQLException
{
return getRDBMS().getForeignKeyConstraints(inConn, getSchema(), name());
}
//---------------------------------------------------------------------------
public boolean hasForeignKeyConstraint(Connection inConn, ForeignKeyConstraint inFkConstraint)
throws SQLException
{
boolean result = false;
List foreignKeyConstraints = getForeignKeyConstraints(inConn);
if (CollectionUtil.hasValues(foreignKeyConstraints))
{
for (ForeignKeyConstraint constraint : foreignKeyConstraints)
{
if (inFkConstraint.equals(constraint))
{
result = true;
break;
}
}
}
return result;
}
//###########################################################################
// PRIVATE METHODS
//###########################################################################
//---------------------------------------------------------------------------
private boolean containsColumnsNotRetrievedByDefault()
{
boolean result = false;
for (DatabaseCol col : getCols())
{
if (! col.getRetrievedByDefault())
{
result = true;
break;
}
}
return result;
}
}