Skip to content

Commit

Permalink
Add another abstraction layer on top of the existing jdbc layer for h…
Browse files Browse the repository at this point in the history
…andling DB specific SQL
  • Loading branch information
sdbuehlmann committed Feb 21, 2024
1 parent cce3e9d commit 35f2e7f
Show file tree
Hide file tree
Showing 15 changed files with 569 additions and 157 deletions.
2 changes: 1 addition & 1 deletion src/main/java/ch/admin/bar/siard2/cmd/ArchiveMapping.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public class ArchiveMapping implements IdMapper {
public SchemaMapping getSchemaMapping(String sSchemaName) { return _mapSchemas.get(sSchemaName); }
public String getMappedSchemaName(String sSchemaName) { return getSchemaMapping(sSchemaName).getMappedSchemaName(); }

private ArchiveMapping(boolean bSupportsArrays, boolean bSupportsUdts,
public ArchiveMapping(boolean bSupportsArrays, boolean bSupportsUdts,
Map<String,String> mapSchemas, MetaData md,
int iMaxTableNameLength, int iMaxColumnNameLength)
throws IOException
Expand Down
58 changes: 17 additions & 41 deletions src/main/java/ch/admin/bar/siard2/cmd/MetaDataToDb.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
import java.text.*;
import java.util.*;
import java.util.regex.*;

import ch.admin.bar.siard2.cmd.db.connector.SqlExecutor;
import ch.enterag.utils.jdbc.*;
import ch.enterag.utils.EU;
import ch.enterag.utils.background.*;
Expand All @@ -32,15 +34,24 @@ public class MetaDataToDb
{
/** logger */
private static IndentLogger _il = IndentLogger.getIndentLogger(MetaDataToDb.class.getName());
private ArchiveMapping _am = null;
private final ArchiveMapping _am;
public ArchiveMapping getArchiveMapping() { return _am; }
private int _iMaxTableNameLength = -1;
private int _iMaxColumnNameLength = -1;

private Progress _progress = null;
private int _iTablesCreated = -1;
private int _iTables = -1;
private int _iTablesPercent = -1;

private final SqlExecutor sqlExecutor;

// TODO remove ArchiveMapping
public MetaDataToDb(final MetaData metaData, final SqlExecutor sqlExecutor, final ArchiveMapping archiveMapping) throws IOException, SQLException {
super(sqlExecutor.getDatabaseMetaData(), metaData);

this.sqlExecutor = sqlExecutor;
this._am = archiveMapping;
}

/*------------------------------------------------------------------*/
/** increment the number or tables created, issuing a notification,
* when a percent is reached.
Expand Down Expand Up @@ -618,7 +629,7 @@ public void upload(Progress progress)
_dmd.getConnection().commit();
_il.exit();
} /* upload */

/*------------------------------------------------------------------*/
/** returns the number of tables that exist in the database and will
* be dropped, when upload is executed.
Expand All @@ -642,7 +653,7 @@ public int tablesDroppedByUpload()
}
_il.exit(String.valueOf(iTablesDropped));
return iTablesDropped;
} /* tablesDroppedByUpload */
}

/*------------------------------------------------------------------*/
/** matchAttributes returns true, if the attributes of the given
Expand Down Expand Up @@ -833,39 +844,4 @@ public int typesDroppedByUpload()
_il.exit(String.valueOf(iTypesDropped));
return iTypesDropped;
} /* typesDroppedByUpload */

/*------------------------------------------------------------------*/
/** constructor
* @param dmd database meta data.
* @param md SIARD meta data.
* @param mapSchemas schema mapping to be used for upload, or empty or null.
* @throws IOException if an I/O error occurred
* @throws SQLException if a database error occurred.
*/
private MetaDataToDb(DatabaseMetaData dmd, MetaData md, Map<String,String> mapSchemas)
throws IOException, SQLException
{
super(dmd,md);
dmd.getConnection().setAutoCommit(false);
_iMaxTableNameLength = _dmd.getMaxTableNameLength();
_iMaxColumnNameLength = _dmd.getMaxColumnNameLength();
_am = ArchiveMapping.newInstance(supportsArrays(), supportsUdts(),
mapSchemas, _md, _iMaxTableNameLength, _iMaxColumnNameLength);
} /* constructor */

/*------------------------------------------------------------------*/
/** factory
* @param dmd database meta data.
* @param md SIARD meta data.
* @param mapSchemas schema mapping to be used for upload, or null.
* @return new instance.
* @throws IOException if an I/O error occurred
* @throws SQLException if a database error occurred.
*/
public static MetaDataToDb newInstance(DatabaseMetaData dmd, MetaData md, Map<String,String> mapSchemas)
throws IOException, SQLException
{
return new MetaDataToDb(dmd,md,mapSchemas);
} /* factory */

} /* class MetaDataTransfer */
}
95 changes: 28 additions & 67 deletions src/main/java/ch/admin/bar/siard2/cmd/PrimaryDataToDb.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,14 @@
import ch.admin.bar.siard2.api.Table;
import ch.admin.bar.siard2.api.Value;
import ch.admin.bar.siard2.api.generated.CategoryType;
import ch.admin.bar.siard2.cmd.model.QualifiedTableId;
import ch.admin.bar.siard2.cmd.sql.CreateForeignKeySqlGenerator;
import ch.admin.bar.siard2.cmd.sql.IdEncoder;
import ch.admin.bar.siard2.cmd.utils.ListAssembler;
import ch.admin.bar.siard2.cmd.db.connector.Connector;
import ch.admin.bar.siard2.cmd.db.connector.SqlExecutor;
import ch.enterag.sqlparser.SqlLiterals;
import ch.enterag.sqlparser.identifier.QualifiedId;
import ch.enterag.utils.EU;
import ch.enterag.utils.StopWatch;
import ch.enterag.utils.background.Progress;
import ch.enterag.utils.logging.IndentLogger;
import lombok.val;

import java.io.IOException;
import java.io.InputStream;
Expand Down Expand Up @@ -73,6 +70,29 @@ public class PrimaryDataToDb extends PrimaryDataTransfer
private long _lRecordsTotal = -1;
private long _lRecordsPercent = -1;

private final SqlExecutor sqlExecutor;

/**
*
* TODO remove Connector and ArchiveMapping
*
*/
public PrimaryDataToDb(
final Archive archive,
final Connector connector,
final SqlExecutor sqlExecutor,
final ArchiveMapping archiveMapping
) {
super(connector.getConnection(),
archive,
archiveMapping,
connector.getDbFeatures().isArraysSupported(),
connector.getDbFeatures().isDistinctsSupported(),
connector.getDbFeatures().isUdtsSupported());

this.sqlExecutor = sqlExecutor;
}

/*------------------------------------------------------------------*/
/** increment the number or records uploaded, issuing a notification,
* when a percent is reached.
Expand Down Expand Up @@ -167,30 +187,6 @@ public void addCandidateKeys(Connection conn, MetaTable mt)
}
}
} /* addCandidateKeys */

public void addForeignKeys(Connection conn, MetaTable mt) throws SQLException {
_il.enter(mt.getName());

if (mt.getMetaForeignKeys() > 0) {
val sqlGenerator = CreateForeignKeySqlGenerator.builder()
.tableId(QualifiedTableId.builder()
.schema(mt.getParentMetaSchema().getName())
.table(mt.getName())
.build())
.idEncoder(new IdEncoder())
.idMapper(_am)
.build();

val sql = sqlGenerator.create(ListAssembler.assemble(mt.getMetaForeignKeys(), mt::getMetaForeignKey));

Statement stmt = conn.createStatement();
stmt.setQueryTimeout(_iQueryTimeoutSeconds);
stmt.execute(sql);
stmt.close();
}

_il.exit();
}

private void enableConstraints(MetaSchema ms)
{
Expand All @@ -200,7 +196,9 @@ private void enableConstraints(MetaSchema ms)
MetaTable mt = ms.getMetaTable(iTable);
try { addCandidateKeys(_conn, mt); }
catch(SQLException se) { System.err.println(EU.getExceptionMessage(se)); }
try { addForeignKeys(_conn, mt); }
try {
sqlExecutor.addForeignKeys(mt);
}
catch(SQLException se) { System.err.println(EU.getExceptionMessage(se)); }
}
_il.exit();
Expand Down Expand Up @@ -517,41 +515,4 @@ public void upload(Progress progress)
_conn.commit();
_il.exit();
} /* upload */

/*------------------------------------------------------------------*/
/** constructor
* @param conn database connection.
* @param archive SIARD archive.
* @param am mapping of names in archive.
* @param bSupportsArrays true, if database supports Arrays.
* @param bSupportsDistincts true, if database supports DISTINCTs.
* @param bSupportsUdts true, if database supports UDTs.
* @throws SQLException if a database error occurred.
*/
private PrimaryDataToDb(Connection conn, Archive archive,
ArchiveMapping am, boolean bSupportsArrays, boolean bSupportsDistincts, boolean bSupportsUdts)
throws SQLException
{
super(conn,archive,am,bSupportsArrays,bSupportsDistincts,bSupportsUdts);
conn.setAutoCommit(false);
} /* constructor PrimaryDataTransfer */

/*------------------------------------------------------------------*/
/** factory
* @param conn database connection.
* @param archive SIARD archive.
* @param am mapping of names in archive.
* @param bSupportsArrays true, if database supports Arrays.
* @param bSupportsDistincts true, if database supports DISTINCTs.
* @param bSupportsUdts true, if database supports UDTs.
* @return new instance of PrimaryDataTransfer.
* @throws SQLException if a database error occurred.
*/
public static PrimaryDataToDb newInstance(Connection conn, Archive archive,
ArchiveMapping am, boolean bSupportsArrays, boolean bSupportsDistincts, boolean bSupportsUdts)
throws SQLException
{
return new PrimaryDataToDb(conn, archive, am, bSupportsArrays, bSupportsDistincts, bSupportsUdts);
} /* newInstance */

} /* class PrimaryDataToDb */
105 changes: 57 additions & 48 deletions src/main/java/ch/admin/bar/siard2/cmd/SiardToDb.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@
import java.io.File;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.time.Duration;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
Expand All @@ -24,11 +24,15 @@
import ch.admin.bar.siard2.api.MetaData;
import ch.admin.bar.siard2.api.MetaSchema;
import ch.admin.bar.siard2.api.primary.ArchiveImpl;
import ch.admin.bar.siard2.cmd.db.connector.ConnectorProperties;
import ch.admin.bar.siard2.cmd.db.connector.ConnectorsRegistry;
import ch.admin.bar.siard2.cmd.utils.ListAssembler;
import ch.admin.bar.siard2.cmd.utils.VersionsExplorer;
import ch.enterag.utils.EU;
import ch.enterag.utils.ProgramInfo;
import ch.enterag.utils.cli.Arguments;
import ch.enterag.utils.logging.IndentLogger;
import lombok.val;

/*====================================================================*/
/** Loads the data from a siard file to a database instance.
Expand Down Expand Up @@ -260,57 +264,62 @@ public SiardToDb(String asArgs[])
_archive = ArchiveImpl.newInstance();
_archive.open(_fileSiard);
/* open connection */
String sError = SiardConnection.getSiardConnection().loadDriver(_sJdbcUrl);
if ((sError == null) || (sError.length() == 0))
{
DriverManager.setLoginTimeout(_iLoginTimeoutSeconds);
_conn = DriverManager.getConnection(_sJdbcUrl, _sDatabaseUser, _sDatabasePassword);
if ((_conn != null) && (!_conn.isClosed()))
{
System.out.println("Connected to "+_conn.getMetaData().getURL().toString());
_conn.setAutoCommit(false);
/* create types and tables */
MetaData md = _archive.getMetaData();
MetaDataToDb mdtd = MetaDataToDb.newInstance(_conn.getMetaData(),md,_mapSchemas);
mdtd.setQueryTimeout(_iQueryTimeoutSeconds);
if (_bOverwrite || ((mdtd.tablesDroppedByUpload() == 0) && (mdtd.typesDroppedByUpload() == 0)))
{
if (!mdtd.supportsUdts())
{
int iTypesInSiard = 0;
for (int iSchema = 0; iSchema < md.getMetaSchemas(); iSchema++)
{
MetaSchema ms = md.getMetaSchema(iSchema);
iTypesInSiard = iTypesInSiard + ms.getMetaTypes();
}
if (iTypesInSiard > 0)
logPrint("Target database does not support UDTs. UDTs will be \"flattened\".\r\n");
}
mdtd.upload(null);
/* upload primary data from DB */
PrimaryDataToDb pdtd = PrimaryDataToDb.newInstance(_conn, _archive,
mdtd.getArchiveMapping(), mdtd.supportsArrays(), mdtd.supportsDistincts(), mdtd.supportsUdts());
pdtd.setQueryTimeout(_iQueryTimeoutSeconds);
pdtd.upload(null);
}
else
{
System.err.println("Database objects exist which would be overwritten on upload!");
System.err.println("Backup and delete them first or use -o option for overwriting them.");
_iReturn = iRETURN_WARNING;
}
// _conn.commit();
_conn.close();
}
else
System.err.println("Connection to "+_conn.getMetaData().getURL().toString()+" failed!");

val connector = ConnectorsRegistry.INSTANCE.getConnector(ConnectorProperties.builder()
.jdbcUrl(_sJdbcUrl)
.user(_sDatabaseUser)
.password(_sDatabasePassword)
.queryTimeout(Duration.ofSeconds(_iQueryTimeoutSeconds))
.loginTimeout(Duration.ofSeconds(_iLoginTimeoutSeconds))
.build());

val dbFeatures = connector.getDbFeatures();

val idMapper = new ArchiveMapping(
dbFeatures.isArraysSupported(),
dbFeatures.isUdtsSupported(),
_mapSchemas,
_archive.getMetaData(),
dbFeatures.getMaxTableNameLength(),
dbFeatures.getMaxColumnNameLength());

val sqlExecutor = connector.createExecutor(idMapper);

val metaDataToDb = new MetaDataToDb(_archive.getMetaData(), sqlExecutor, idMapper);
val primaryDataToDb = new PrimaryDataToDb(_archive, connector, sqlExecutor, idMapper);

if (!_bOverwrite && ((metaDataToDb.tablesDroppedByUpload() < 0) || (metaDataToDb.typesDroppedByUpload() > 0))) {
System.err.println("Database objects exist which would be overwritten on upload!");
System.err.println("Backup and delete them first or use -o option for overwriting them.");

connector.close();
_archive.close();
_iReturn = iRETURN_WARNING;

return;
}
else
System.err.println("Connection to "+_sJdbcUrl+" not supported ("+sError+")!");

if (!dbFeatures.isUdtsSupported() && containsUDTs(_archive.getMetaData())) {
logPrint("Target database does not support UDTs. UDTs will be \"flattened\".\r\n");
}

metaDataToDb.upload(null);
primaryDataToDb.upload(null);

connector.close();
_archive.close();
_iReturn = iRETURN_OK;
}
_il.exit();
} /* constructor SiardToDb */
}

private boolean containsUDTs(final MetaData metaData) {
val nrOfUDTsInSiardArchive = ListAssembler.assemble(metaData.getMetaSchemas(), metaData::getMetaSchema).stream()
.mapToInt(MetaSchema::getMetaTypes)
.sum();

return nrOfUDTsInSiardArchive > 0;
}

/*====================================================================
factory
Expand Down
18 changes: 18 additions & 0 deletions src/main/java/ch/admin/bar/siard2/cmd/db/connector/Connector.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package ch.admin.bar.siard2.cmd.db.connector;

import ch.admin.bar.siard2.cmd.db.features.DbFeatures;
import ch.admin.bar.siard2.cmd.mapping.IdMapper;

import java.sql.Connection;
import java.sql.SQLException;

public interface Connector {
DbFeatures getDbFeatures();

@Deprecated
Connection getConnection();

SqlExecutor createExecutor(IdMapper idMapper) throws SQLException;

void close();
}

0 comments on commit 35f2e7f

Please sign in to comment.