use of org.jaxdb.vendor.DBVendor in project jaxdb by jaxdb.
the class InsertTest method testInsertBatch.
@Test
public void testInsertBatch(@Schema(types.class) final Transaction transaction) throws IOException, SQLException {
final DBVendor vendor = transaction.getVendor();
final boolean isOracle = vendor == DBVendor.ORACLE;
final Batch batch = new Batch();
batch.addStatement(INSERT(t1), (e, c) -> assertEquals(isOracle ? 0 : 1, c));
batch.addStatement(INSERT(t2), (e, c) -> assertEquals(isOracle ? 0 : 1, c));
batch.addStatement(INSERT(t3.id, t3.bigintType, t3.charType, t3.doubleType, t3.tinyintType, t3.timeType), (e, c) -> assertEquals(isOracle ? 0 : 1, c));
assertEquals(isOracle ? 0 : 3, batch.execute(transaction));
if (isOracle || vendor == DBVendor.DERBY || vendor == DBVendor.SQLITE)
return;
final int id = getMaxId(transaction, t1);
assertEquals(id - 2, t1.id.getAsInt());
assertEquals(id - 1, t2.id.getAsInt());
assertEquals(id - 0, t3.id.getAsInt());
}
use of org.jaxdb.vendor.DBVendor in project jaxdb by jaxdb.
the class Connector method addNotificationListener0.
@SuppressWarnings({ "resource", "unchecked" })
private <T extends data.Table<?>> boolean addNotificationListener0(final INSERT insert, final UP up, final DELETE delete, final Notification.Listener<T> notificationListener, final Queue<Notification<T>> queue, final T... tables) throws IOException, SQLException {
assertNotNull(notificationListener);
assertNotEmpty(tables);
if (notifier == null) {
final Connection connection = connectionFactory.getConnection();
final DBVendor vendor = DBVendor.valueOf(connection.getMetaData());
if (vendor == DBVendor.POSTGRE_SQL) {
notifier = new PostgreSQLNotifier(connection, this);
} else {
connection.close();
throw new UnsupportedOperationException("Unsupported DBVendor: " + vendor);
}
}
return notifier.addNotificationListener(insert, up, delete, notificationListener, queue, tables);
}
use of org.jaxdb.vendor.DBVendor in project jaxdb by jaxdb.
the class Generator method main.
public static void main(final String[] args) throws GeneratorExecutionException, IOException, SAXException, TransformerException {
if (args.length != 5)
trapPrintUsage();
DBVendor vendor = null;
File destDir = null;
URL schemaUrl = null;
String sqlFileName = null;
for (int i = 0; i < args.length; ++i) {
if ("-v".equals(args[i]))
vendor = DBVendor.valueOf(args[++i]);
else if ("-d".equals(args[i]))
destDir = new File(args[++i]).getAbsoluteFile();
else {
final File schemaFile = new File(args[i]);
sqlFileName = schemaFile.getName().substring(0, schemaFile.getName().lastIndexOf('.') + 1) + "sql";
schemaUrl = schemaFile.getAbsoluteFile().toURI().toURL();
}
}
if (vendor == null || destDir == null || schemaUrl == null) {
trapPrintUsage();
} else {
final StatementBatch statementBatch = createDDL(new DDLx(schemaUrl), vendor);
destDir.mkdirs();
statementBatch.writeOutput(new File(destDir, sqlFileName));
}
}
use of org.jaxdb.vendor.DBVendor in project jaxdb by jaxdb.
the class Batch method execute.
@SuppressWarnings({ "null", "resource", "unchecked" })
private int execute(final Transaction transaction, final String dataSourceId) throws IOException, SQLException {
if (statements == null)
return 0;
AtomicReference<int[]> countRef = new AtomicReference<>();
try {
final int noStatements = statements.size();
final Consumer<Transaction.Event>[] eventListeners = new Consumer[noStatements];
final InsertImpl<?>[] insertsWithGeneratedKeys = new InsertImpl<?>[noStatements];
final Compilation[] compilations = new Compilation[noStatements];
final Connection connection;
final Connector connector;
String last = null;
Statement statement = null;
SQLException suppressed = null;
boolean isPrepared;
int total = 0;
int index = 0;
final Command<?> command0 = (Command<?>) statements.get(0);
final Class<? extends Schema> schema = command0.schema();
if (transaction != null) {
connector = transaction.getConnector();
connection = transaction.getConnection();
isPrepared = transaction.isPrepared();
} else {
connector = Database.getConnector(command0.schema(), dataSourceId);
connection = connector.getConnection();
connection.setAutoCommit(true);
isPrepared = connector.isPrepared();
}
try {
int listenerIndex = 0;
for (int statementIndex = 0, eventIndex = 0; statementIndex < noStatements; ++statementIndex) {
final Command<?> command = (Command<?>) statements.get(statementIndex);
if (schema != command.schema())
throw new IllegalArgumentException("Cannot execute batch across different schemas: " + schema.getSimpleName() + " and " + command.schema().getSimpleName());
final DBVendor vendor = DBVendor.valueOf(connection.getMetaData());
final Compiler compiler = Compiler.getCompiler(vendor);
if (isPrepared && !compiler.supportsPreparedBatch()) {
if (logger.isWarnEnabled())
logger.warn(vendor + " does not support prepared statement batch execution");
isPrepared = false;
}
final boolean returnGeneratedKeys;
if (command instanceof InsertImpl && ((InsertImpl<?>) command).autos.length > 0) {
if (!compiler.supportsReturnGeneratedKeysBatch()) {
if (logger.isWarnEnabled())
logger.warn(vendor + " does not support return of generated keys during batch execution");
returnGeneratedKeys = false;
} else if (returnGeneratedKeys = isPrepared) {
insertsWithGeneratedKeys[statementIndex] = (InsertImpl<?>) command;
} else if (logger.isWarnEnabled()) {
logger.warn("Generated keys can only be provided with prepared statement batch execution");
}
} else {
returnGeneratedKeys = false;
}
final Compilation compilation = compilations[statementIndex] = new Compilation(command, vendor, isPrepared);
command.compile(compilation, false);
final String sql = compilation.toString();
if (isPrepared) {
if (!(statement instanceof PreparedStatement) || !sql.equals(last)) {
if (statement != null) {
try {
final int[] counts = statement.executeBatch();
total = aggregate(counts, statement, insertsWithGeneratedKeys, index, total);
index += counts.length;
countRef.set(counts);
countRef = new AtomicReference<>();
notifyListenerEvent(Transaction.Event.EXECUTE, eventListeners, listenerIndex, statementIndex);
afterExecute(compilations, listenerIndex, statementIndex);
addListenerCommit(transaction, eventListeners, listenerIndex, statementIndex);
listenerIndex = statementIndex;
eventIndex = 0;
} finally {
suppressed = Throwables.addSuppressed(suppressed, AuditStatement.close(statement));
}
}
statement = returnGeneratedKeys ? connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS) : connection.prepareStatement(sql);
last = sql;
}
final List<data.Column<?>> parameters = compilation.getParameters();
if (parameters != null)
for (int p = 0, len = parameters.size(); p < len; ) parameters.get(p).get((PreparedStatement) statement, ++p);
((PreparedStatement) statement).addBatch();
} else {
if (statement == null) {
statement = connection.createStatement();
} else if (statement instanceof PreparedStatement) {
try {
final int[] counts = statement.executeBatch();
total = aggregate(counts, statement, insertsWithGeneratedKeys, index, total);
index += counts.length;
countRef.set(counts);
countRef = new AtomicReference<>();
notifyListenerEvent(Transaction.Event.EXECUTE, eventListeners, listenerIndex, statementIndex);
afterExecute(compilations, listenerIndex, statementIndex);
addListenerCommit(transaction, eventListeners, listenerIndex, statementIndex);
listenerIndex = statementIndex;
eventIndex = 0;
} finally {
suppressed = Throwables.addSuppressed(suppressed, AuditStatement.close(statement));
}
statement = connection.createStatement();
}
statement.addBatch(sql);
}
addEventListener(connector, connection, command, eventListeners, countRef, statementIndex, eventIndex++);
}
final int[] counts = statement.executeBatch();
total = aggregate(counts, statement, insertsWithGeneratedKeys, index, total);
index += counts.length;
countRef.set(counts);
notifyListenerEvent(Transaction.Event.EXECUTE, eventListeners, listenerIndex, noStatements);
afterExecute(compilations, listenerIndex, noStatements);
addListenerCommit(transaction, eventListeners, listenerIndex, noStatements);
return total;
} finally {
SQLException e = Throwables.addSuppressed(statement == null ? null : AuditStatement.close(statement), suppressed);
if (transaction == null && connection != null)
e = Throwables.addSuppressed(e, AuditConnection.close(connection));
if (e != null)
throw e;
}
} catch (final SQLException e) {
throw SQLExceptions.toStrongType(e);
}
}
use of org.jaxdb.vendor.DBVendor in project jaxdb by jaxdb.
the class Decompiler method createDDL.
public static Schema createDDL(final Connection connection) throws SQLException {
final DBVendor vendor = DBVendor.valueOf(connection.getMetaData());
final Decompiler decompiler = Decompiler.getDecompiler(vendor);
final DatabaseMetaData metaData = connection.getMetaData();
try (final ResultSet tableRows = metaData.getTables(null, null, null, new String[] { "TABLE" })) {
final Schema schema = new Schema();
final Map<String, List<$CheckReference>> tableNameToChecks = decompiler.getCheckConstraints(connection);
final Map<String, List<$Table.Constraints.Unique>> tableNameToUniques = decompiler.getUniqueConstraints(connection);
final Map<String, $Table.Indexes> tableNameToIndexes = decompiler.getIndexes(connection);
final Map<String, Map<String, $ForeignKeyUnary>> tableNameToForeignKeys = decompiler.getForeignKeys(connection);
final Map<String, $Column> columnNameToColumn = new HashMap<>();
final Map<Integer, $Column> columnNumberToColumn = new TreeMap<>();
final Map<String, TreeMap<Short, String>> indexNameToIndex = new HashMap<>();
final Map<String, String> indexNameToType = new HashMap<>();
final Map<String, Boolean> indexNameToUnique = new HashMap<>();
while (tableRows.next()) {
final String tableName = tableRows.getString(3);
final $Table table = new Schema.Table();
table.setName$(new $Named.Name$(tableName.toLowerCase()));
schema.addTable(table);
try (final ResultSet columnRows = metaData.getColumns(null, null, tableName, null)) {
while (columnRows.next()) {
final String columnName = columnRows.getString("COLUMN_NAME").toLowerCase();
final String typeName = columnRows.getString("TYPE_NAME");
final int columnSize = columnRows.getInt("COLUMN_SIZE");
final String _default = columnRows.getString("COLUMN_DEF");
final int index = columnRows.getInt("ORDINAL_POSITION");
final String nullable = columnRows.getString("IS_NULLABLE");
final String autoIncrement = columnRows.getString("IS_AUTOINCREMENT");
final int decimalDigits = columnRows.getInt("DECIMAL_DIGITS");
final $Column column = decompiler.makeColumn(columnName.toLowerCase(), typeName, columnSize, decimalDigits, _default, nullable.length() == 0 ? null : "YES".equals(nullable), autoIncrement.length() == 0 ? null : "YES".equals(autoIncrement));
columnNameToColumn.put(columnName, column);
columnNumberToColumn.put(index, column);
}
columnNumberToColumn.values().forEach(table::addColumn);
try (final ResultSet primaryKeyRows = metaData.getPrimaryKeys(null, null, tableName)) {
while (primaryKeyRows.next()) {
final String columnName = primaryKeyRows.getString("COLUMN_NAME").toLowerCase();
if (table.getConstraints() == null)
table.setConstraints(new $Table.Constraints());
if (table.getConstraints().getPrimaryKey() == null)
table.getConstraints().setPrimaryKey(new $Table.Constraints.PrimaryKey());
final $Table.Constraints.PrimaryKey.Column column = new $Table.Constraints.PrimaryKey.Column();
column.setName$(new $Table.Constraints.PrimaryKey.Column.Name$(columnName));
table.getConstraints().getPrimaryKey().addColumn(column);
}
}
final List<$Table.Constraints.Unique> uniques = tableNameToUniques == null ? null : tableNameToUniques.get(tableName);
if (uniques != null && uniques.size() > 0) {
if (table.getConstraints() == null)
table.setConstraints(new $Table.Constraints());
for (final $Table.Constraints.Unique unique : uniques) table.getConstraints().addUnique(unique);
}
try (final ResultSet indexRows = metaData.getIndexInfo(null, null, tableName, false, true)) {
while (indexRows.next()) {
final String columnName = indexRows.getString("COLUMN_NAME").toLowerCase();
if (columnName == null)
continue;
final String indexName = indexRows.getString("INDEX_NAME").toLowerCase();
TreeMap<Short, String> indexes = indexNameToIndex.get(indexName);
if (indexes == null)
indexNameToIndex.put(indexName, indexes = new TreeMap<>());
final short ordinalPosition = indexRows.getShort("ORDINAL_POSITION");
indexes.put(ordinalPosition, columnName);
final String type = getType(indexRows.getShort("TYPE"));
final String currentType = indexNameToType.get(indexName);
if (currentType == null)
indexNameToType.put(indexName, type);
else if (!type.equals(currentType))
throw new IllegalStateException("Expected " + type + " = " + currentType);
final boolean unique = !indexRows.getBoolean("NON_UNIQUE");
final Boolean currentUnique = indexNameToUnique.get(indexName);
if (currentUnique == null)
indexNameToUnique.put(indexName, unique);
else if (unique != currentUnique)
throw new IllegalStateException("Expected " + unique + " = " + currentType);
}
}
final $Table.Indexes indexes = tableNameToIndexes == null ? null : tableNameToIndexes.get(tableName);
if (indexes != null)
table.setIndexes(indexes);
final List<$CheckReference> checks = tableNameToChecks == null ? null : tableNameToChecks.get(tableName);
if (checks != null)
for (final $CheckReference check : checks) addCheck(columnNameToColumn.get(check.getColumn$().text()), check);
final Map<String, $ForeignKeyUnary> foreignKeys = tableNameToForeignKeys == null ? null : tableNameToForeignKeys.get(tableName);
if (foreignKeys != null)
for (final Map.Entry<String, $ForeignKeyUnary> entry : foreignKeys.entrySet()) columnNameToColumn.get(entry.getKey().toLowerCase()).setForeignKey(entry.getValue());
}
columnNameToColumn.clear();
columnNumberToColumn.clear();
indexNameToIndex.clear();
indexNameToType.clear();
}
return schema;
}
}
Aggregations