Join GitHub today
GitHub is home to over 20 million developers working together to host and review code, manage projects, and build software together.
Metadata migration Closes #789 #1277
Conversation
Horneth
added the
in review
label
Aug 9, 2016
geoffjentry
commented on an outdated diff
Aug 10, 2016
| @@ -0,0 +1,114 @@ | ||
| +package cromwell.database.migration.metadata | ||
| + | ||
| +import java.sql.{Types, PreparedStatement, Timestamp} | ||
| +import java.time.{ZoneOffset, OffsetDateTime} | ||
| +import java.time.format.DateTimeFormatter | ||
| + | ||
| +import cromwell.database.SqlConverters._ | ||
| +import liquibase.database.jvm.JdbcConnection | ||
| +import org.slf4j.LoggerFactory | ||
| +import wdl4s.values.{WdlBoolean, WdlFloat, WdlInteger, WdlValue} | ||
| + | ||
| +object MetadataStatement { | ||
| + val workflowIdIdx = 1 |
|
|
mcovarr
self-assigned this
Aug 10, 2016
mcovarr
commented on an outdated diff
Aug 10, 2016
| @@ -0,0 +1,22 @@ | ||
| +<?xml version="1.0" encoding="UTF-8" standalone="no"?> | ||
| +<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" | ||
| + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
| + xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.3.xsd"> | ||
| + | ||
| + <property name="clob.type" value="LONGTEXT" dbms="mysql"/> | ||
| + <property name="clob.type" value="LONGVARCHAR" dbms="hsqldb"/> | ||
| + | ||
| + <changeSet author="tjeandet" id="METADATA_MIGRATION"> | ||
| + <comment> | ||
| + Metadata migration from 0.19 to 0.20. |
|
|
mcovarr
and 1 other
commented on an outdated diff
Aug 10, 2016
| + val executionDataResultSet = connection.createStatement().executeQuery(selectQuery) | ||
| + val metadataInsertStatement = MetadataStatement.makeStatement(connection) | ||
| + | ||
| + val executionIterator = new ResultSetIterator(executionDataResultSet) | ||
| + | ||
| + executionIterator.zipWithIndex foreach { | ||
| + case (row, idx) => | ||
| + migrateRow(connection, collectors, metadataInsertStatement, row, idx) | ||
| + if (idx % 100 == 0) { | ||
| + metadataInsertStatement.executeBatch() | ||
| + connection.commit() | ||
| + } | ||
| + } | ||
| + | ||
| + metadataInsertStatement.executeBatch() | ||
| + connection.commit() |
Horneth
Contributor
|
mcovarr
commented on an outdated diff
Aug 10, 2016
| + | ||
| + private def findCollectorIds(connection: JdbcConnection) = { | ||
| + val collectorsIdQuery = | ||
| + """ | ||
| + |SELECT EXECUTION_ID | ||
| + |FROM EXECUTION | ||
| + |GROUP BY CALL_FQN, ATTEMPT, WORKFLOW_EXECUTION_ID | ||
| + |HAVING COUNT(*) > 1 | ||
| + """.stripMargin | ||
| + | ||
| + val collectorsRS = new ResultSetIterator(connection.createStatement().executeQuery(collectorsIdQuery)) | ||
| + collectorsRS map { _.getInt("EXECUTION_ID") } toSet | ||
| + } | ||
| + | ||
| + override def execute(database: Database): Unit = { | ||
| + val dbConn = database.getConnection.asInstanceOf[JdbcConnection] |
|
|
mcovarr
commented on an outdated diff
Aug 10, 2016
| + } | ||
| + | ||
| + override def addEmptyValue(key: String): Unit = { | ||
| + preparedStatement.setTimestamp(MetadataStatement.timestampIdx, dawn) | ||
| + add(key, null, s"Failed to add empty value with key $key for workflow $workflowId") | ||
| + } | ||
| +} | ||
| + | ||
| +class MetadataStatementForCall(preparedStatement: PreparedStatement, workflowId: String, callFqn: String, index: Int, attempt: Int) extends MetadataStatementForWorkflow(preparedStatement, workflowId) { | ||
| + override def setStatement() = { | ||
| + preparedStatement.setString(MetadataStatement.workflowIdIdx, workflowId) | ||
| + preparedStatement.setString(MetadataStatement.callFqnIdx, callFqn) | ||
| + preparedStatement.setInt(MetadataStatement.callIndexIdx, index) | ||
| + preparedStatement.setInt(MetadataStatement.callAttemptIdx, attempt) | ||
| + } | ||
| +} |
|
|
mcovarr
and 1 other
commented on an outdated diff
Aug 10, 2016
| + val collectorsRS = new ResultSetIterator(connection.createStatement().executeQuery(collectorsIdQuery)) | ||
| + collectorsRS map { _.getInt("EXECUTION_ID") } toSet | ||
| + } | ||
| + | ||
| + override def execute(database: Database): Unit = { | ||
| + val dbConn = database.getConnection.asInstanceOf[JdbcConnection] | ||
| + try { | ||
| + dbConn.setAutoCommit(false) | ||
| + migrate(dbConn, findCollectorIds(dbConn)) | ||
| + } catch { | ||
| + case t: CustomChangeException => throw t | ||
| + case t: Throwable => throw new CustomChangeException("Could not apply migration script for metadata", t) | ||
| + } | ||
| + } | ||
| + | ||
| + override def setUp(): Unit = { } |
geoffjentry
Member
|
mcovarr
commented on an outdated diff
Aug 10, 2016
| + protected def setStatement() = { | ||
| + preparedStatement.setString(MetadataStatement.workflowIdIdx, workflowId) | ||
| + preparedStatement.setNull(MetadataStatement.callFqnIdx, Types.VARCHAR) | ||
| + preparedStatement.setNull(MetadataStatement.callIndexIdx, Types.INTEGER) | ||
| + preparedStatement.setNull(MetadataStatement.callAttemptIdx, Types.INTEGER) | ||
| + } | ||
| + | ||
| + protected def addDataAndBatch(key: String, value: Any) = { | ||
| + preparedStatement.setString(MetadataStatement.keyIdx, key) | ||
| + | ||
| + // Set the value and type | ||
| + value match { | ||
| + case null => | ||
| + preparedStatement.setNull(MetadataStatement.valueIdx, Types.VARCHAR) | ||
| + preparedStatement.setNull(MetadataStatement.valueTypeIdx, Types.VARCHAR) // Null values have null type | ||
| + case v => |
|
|
mcovarr
commented on an outdated diff
Aug 10, 2016
| + |SELECT DESCRIPTION, EXECUTION.EXECUTION_ID, EXECUTION_EVENT.START_DT, EXECUTION_EVENT.END_DT, EXECUTION.CALL_FQN, | ||
| + | EXECUTION.IDX, EXECUTION.ATTEMPT, EXECUTION.EXECUTION_ID, WORKFLOW_EXECUTION.WORKFLOW_EXECUTION_UUID | ||
| + |FROM EXECUTION_EVENT | ||
| + | LEFT JOIN EXECUTION ON EXECUTION.EXECUTION_ID = EXECUTION_EVENT.EXECUTION_ID | ||
| + | LEFT JOIN WORKFLOW_EXECUTION ON WORKFLOW_EXECUTION.WORKFLOW_EXECUTION_ID = EXECUTION.WORKFLOW_EXECUTION_ID; | ||
| + """.stripMargin | ||
| + | ||
| + override protected def migrateRow(connection: JdbcConnection, collectors: Set[Int], | ||
| + statement: PreparedStatement, row: ResultSet, idx: Int): Unit = { | ||
| + if (!collectors.contains(row.getInt("EXECUTION_ID"))) { | ||
| + val metadataStatement = new MetadataStatementForCall(statement, | ||
| + row.getString("WORKFLOW_EXECUTION_UUID"), | ||
| + row.getString("CALL_FQN"), | ||
| + row.getInt("IDX"), | ||
| + row.getInt("ATTEMPT") | ||
| + ) |
mcovarr
Contributor
|
mcovarr
commented on an outdated diff
Aug 10, 2016
| + val executionIterator = new ResultSetIterator(executionDataResultSet) | ||
| + | ||
| + executionIterator.zipWithIndex foreach { | ||
| + case (row, idx) => | ||
| + migrateRow(connection, collectors, metadataInsertStatement, row, idx) | ||
| + if (idx % 100 == 0) { | ||
| + metadataInsertStatement.executeBatch() | ||
| + connection.commit() | ||
| + } | ||
| + } | ||
| + | ||
| + metadataInsertStatement.executeBatch() | ||
| + connection.commit() | ||
| + } | ||
| + | ||
| + private var resourceAccessor: ResourceAccessor = null |
|
|
mcovarr
commented on an outdated diff
Aug 10, 2016
| + """ | ||
| + |SELECT EXECUTION_ID | ||
| + |FROM EXECUTION | ||
| + |GROUP BY CALL_FQN, ATTEMPT, WORKFLOW_EXECUTION_ID | ||
| + |HAVING COUNT(*) > 1 | ||
| + """.stripMargin | ||
| + | ||
| + val collectorsRS = new ResultSetIterator(connection.createStatement().executeQuery(collectorsIdQuery)) | ||
| + collectorsRS map { _.getInt("EXECUTION_ID") } toSet | ||
| + } | ||
| + | ||
| + override def execute(database: Database): Unit = { | ||
| + val dbConn = database.getConnection.asInstanceOf[JdbcConnection] | ||
| + try { | ||
| + dbConn.setAutoCommit(false) | ||
| + migrate(dbConn, findCollectorIds(dbConn)) |
mcovarr
Contributor
|
mcovarr
added the
needs rebase ⚔
label
Aug 10, 2016
mcovarr
assigned geoffjentry and unassigned mcovarr
Aug 10, 2016
Horneth
removed the
needs rebase ⚔
label
Aug 10, 2016
|
This is such a cool branch Thibault, I didn't realize Liquibase could do so much! |
|
Yeah I didn't know either but it's pretty useful in this case ! |
mcovarr
assigned Horneth and unassigned geoffjentry
Aug 12, 2016
mcovarr
added ⭐ Two Thumbs-Up ⭐ Back With Originator ♻️
labels
Aug 12, 2016
mcovarr
commented on an outdated diff
Aug 22, 2016
| +import wdl4s.types.{WdlPrimitiveType, WdlType} | ||
| +import wdl4s.values._ | ||
| + | ||
| +import scala.util.{Failure, Success, Try} | ||
| + | ||
| +abstract class SymbolTableMigration extends MetadataMigration { | ||
| + override protected def migrateRow(connection: JdbcConnection, statement: PreparedStatement, row: ResultSet, idx: Int): Unit = { | ||
| + // Try to coerce the value to a WdlValue | ||
| + val value = for { | ||
| + wdlTypeValue <- Try(row.getString("WDL_TYPE")) | ||
| + wdlType <- Try(WdlType.fromWdlString(wdlTypeValue)) | ||
| + wdlValueValue <- Try(row.getString("WDL_VALUE")) | ||
| + inflated <- inflate(wdlValueValue) | ||
| + | ||
| + wdlValue <- wdlType match { | ||
| + case p: WdlPrimitiveType => p.coerceRawValue(inflated) |
mcovarr
Contributor
|
mcovarr
added the
needs rebase ⚔
label
Aug 23, 2016
mcovarr
and 1 other
commented on an outdated diff
Aug 23, 2016
| + SELECT SYMBOL.SCOPE, SYMBOL.NAME, MaxExecution.IDX, IO, WDL_TYPE, | ||
| + WDL_VALUE, WORKFLOW_EXECUTION_UUID, ExecutionId.EXECUTION_ID, REPORTABLE_RESULT, | ||
| + MaxExecution.MaxAttempt | ||
| + FROM SYMBOL | ||
| + LEFT JOIN WORKFLOW_EXECUTION ON SYMBOL.WORKFLOW_EXECUTION_ID = WORKFLOW_EXECUTION.WORKFLOW_EXECUTION_ID | ||
| + LEFT JOIN( | ||
| + SELECT CALL_FQN, IDX, WORKFLOW_EXECUTION_ID, MAX(EXECUTION.ATTEMPT) AS MaxAttempt | ||
| + FROM EXECUTION | ||
| + GROUP BY EXECUTION.CALL_FQN, EXECUTION.IDX, EXECUTION.WORKFLOW_EXECUTION_ID | ||
| + ) MaxExecution | ||
| + ON SYMBOL.SCOPE = MaxExecution.CALL_FQN | ||
| + AND SYMBOL.WORKFLOW_EXECUTION_ID = MaxExecution.WORKFLOW_EXECUTION_ID | ||
| + AND SYMBOL.IDX = MaxExecution.IDX | ||
| + LEFT JOIN(SELECT EXECUTION_ID, CALL_FQN, IDX, WORKFLOW_EXECUTION_ID, ATTEMPT | ||
| + FROM EXECUTION | ||
| + ) ExecutionId |
|
|
mcovarr
commented on an outdated diff
Aug 23, 2016
| + } else executionIterator | ||
| + | ||
| + filtered.zipWithIndex foreach { | ||
| + case (row, idx) => | ||
| + migrateRow(connection, metadataInsertStatement, row, idx) | ||
| + if (idx % 100 == 0) { | ||
| + metadataInsertStatement.executeBatch() | ||
| + connection.commit() | ||
| + } | ||
| + } | ||
| + | ||
| + metadataInsertStatement.executeBatch() | ||
| + connection.commit() | ||
| + } | ||
| + | ||
| + private var resourceAccessor: ResourceAccessor = _ |
|
|
mcovarr
and 1 other
commented on an outdated diff
Aug 23, 2016
| @@ -0,0 +1,49 @@ | ||
| +package cromwell.database.migration.metadata.table | ||
| + | ||
| +import java.sql.{PreparedStatement, ResultSet} | ||
| + | ||
| +import cromwell.database.migration.metadata.MetadataStatementForCall | ||
| +import wdl4s.values._ | ||
| + | ||
| +class CallOutputSymbolTableMigration extends SymbolTableMigration { | ||
| + override protected def selectQuery: String = """ | ||
| + SELECT SYMBOL.SCOPE, SYMBOL.NAME, MaxExecution.IDX, IO, WDL_TYPE, | ||
| + WDL_VALUE, WORKFLOW_EXECUTION_UUID, ExecutionId.EXECUTION_ID, REPORTABLE_RESULT, | ||
| + MaxExecution.MaxAttempt | ||
| + FROM SYMBOL | ||
| + LEFT JOIN WORKFLOW_EXECUTION ON SYMBOL.WORKFLOW_EXECUTION_ID = WORKFLOW_EXECUTION.WORKFLOW_EXECUTION_ID |
Horneth
Contributor
|
mcovarr
commented on an outdated diff
Aug 23, 2016
| + | ||
| +import cromwell.database.migration.metadata.MetadataStatementForCall | ||
| +import wdl4s.values._ | ||
| + | ||
| +class CallOutputSymbolTableMigration extends SymbolTableMigration { | ||
| + override protected def selectQuery: String = """ | ||
| + SELECT SYMBOL.SCOPE, SYMBOL.NAME, MaxExecution.IDX, IO, WDL_TYPE, | ||
| + WDL_VALUE, WORKFLOW_EXECUTION_UUID, ExecutionId.EXECUTION_ID, REPORTABLE_RESULT, | ||
| + MaxExecution.MaxAttempt | ||
| + FROM SYMBOL | ||
| + LEFT JOIN WORKFLOW_EXECUTION ON SYMBOL.WORKFLOW_EXECUTION_ID = WORKFLOW_EXECUTION.WORKFLOW_EXECUTION_ID | ||
| + LEFT JOIN( | ||
| + SELECT CALL_FQN, IDX, WORKFLOW_EXECUTION_ID, MAX(EXECUTION.ATTEMPT) AS MaxAttempt | ||
| + FROM EXECUTION | ||
| + GROUP BY EXECUTION.CALL_FQN, EXECUTION.IDX, EXECUTION.WORKFLOW_EXECUTION_ID | ||
| + ) MaxExecution |
mcovarr
Contributor
|
kshakir
commented on an outdated diff
Aug 25, 2016
|
Re: the |
|
@kshakir I tagged everything with |
mcovarr
added needs rebase ⚔ and removed needs rebase ⚔
labels
Aug 31, 2016
mcovarr
and 1 other
commented on an outdated diff
Sep 2, 2016
| @@ -26,6 +27,7 @@ object WdlValueSimpleton { | ||
| implicit class WdlValueSimplifier(wdlValue: WdlValue) { | ||
| def simplify(name: String): Iterable[WdlValueSimpleton] = wdlValue match { | ||
| case prim: WdlPrimitive => List(WdlValueSimpleton(name, prim)) | ||
| + case expr: WdlExpression => List(WdlValueSimpleton(name, WdlString(expr.valueString))) |
mcovarr
Contributor
|
mcovarr
commented on an outdated diff
Sep 2, 2016
| @@ -0,0 +1,19 @@ | ||
| +CREATE TABLE TMP_COLLECTOR | ||
| +( | ||
| + TMP_COLLECTOR_ID INT PRIMARY KEY NOT NULL AUTO_INCREMENT, | ||
| + EXECUTION_ID INT NOT NULL | ||
| +); | ||
| + | ||
| +INSERT INTO TMP_COLLECTOR ( | ||
| + EXECUTION_ID | ||
| +) | ||
| + SELECT | ||
| + EXECUTION_ID | ||
| + FROM EXECUTION e | ||
| + WHERE e.CALL_FQN LIKE '%$%' OR -- filter out scatters |
mcovarr
Contributor
|
mcovarr
commented on an outdated diff
Sep 2, 2016
| + METADATA_TIMESTAMP | ||
| + ) | ||
| + SELECT | ||
| + WORKFLOW_EXECUTION_UUID, | ||
| + 'start', | ||
| + CALL_FQN, | ||
| + IDX, | ||
| + ATTEMPT, | ||
| + DATE_FORMAT(e.START_DT, '%Y-%m-%dT%T.%f$Offset'), | ||
| + 'string', | ||
| + NOW() | ||
| + FROM EXECUTION e | ||
| + JOIN WORKFLOW_EXECUTION we ON we.WORKFLOW_EXECUTION_ID = e.WORKFLOW_EXECUTION_ID | ||
| + WHERE | ||
| + e.START_DT IS NOT NULL AND | ||
| + e.EXECUTION_ID NOT IN (SELECT EXECUTION_ID FROM TMP_COLLECTOR);""".stripMargin |
mcovarr
Contributor
|
mcovarr
and 1 other
commented on an outdated diff
Sep 2, 2016
| + s.SCOPE, | ||
| + e.IDX, | ||
| + e.ATTEMPT, | ||
| + s.WDL_VALUE, | ||
| + s.WDL_TYPE | ||
| + FROM SYMBOL s | ||
| + JOIN WORKFLOW_EXECUTION we ON | ||
| + we.WORKFLOW_EXECUTION_ID = s.WORKFLOW_EXECUTION_ID | ||
| + LEFT JOIN EXECUTION e ON | ||
| + e.CALL_FQN = s.SCOPE AND | ||
| + e.WORKFLOW_EXECUTION_ID = s.WORKFLOW_EXECUTION_ID | ||
| + -- Don't join on index here because inputs have index null (-1), but we want to duplicate them as many times as there are indices for a given execution | ||
| + WHERE | ||
| + s.IO = 'INPUT' AND | ||
| + ( | ||
| + e.EXECUTION_ID IS NULL OR -- If it's a workflow output the execution ID will be null but we want to keep it |
|
|
mcovarr
and 1 other
commented on an outdated diff
Sep 2, 2016
| + override def queries: Array[String] = { | ||
| + Array( | ||
| + """ | ||
| + |INSERT INTO METADATA_JOURNAL ( | ||
| + | WORKFLOW_EXECUTION_UUID, | ||
| + | METADATA_KEY, | ||
| + | CALL_FQN, | ||
| + | JOB_SCATTER_INDEX, | ||
| + | JOB_RETRY_ATTEMPT, | ||
| + | METADATA_VALUE, | ||
| + | METADATA_VALUE_TYPE, | ||
| + | METADATA_TIMESTAMP | ||
| + |) | ||
| + | SELECT | ||
| + | WORKFLOW_EXECUTION_UUID, | ||
| + | CONCAT('executionEvents[', ev.EVENT_ID ,']:description'), |
mcovarr
Contributor
|
mcovarr
commented on an outdated diff
Sep 2, 2016
| + override def queries: Array[String] = { | ||
| + Array( | ||
| + """ | ||
| + |INSERT INTO METADATA_JOURNAL ( | ||
| + | WORKFLOW_EXECUTION_UUID, | ||
| + | METADATA_KEY, | ||
| + | CALL_FQN, | ||
| + | JOB_SCATTER_INDEX, | ||
| + | JOB_RETRY_ATTEMPT, | ||
| + | METADATA_VALUE, | ||
| + | METADATA_VALUE_TYPE, | ||
| + | METADATA_TIMESTAMP | ||
| + |) | ||
| + |SELECT | ||
| + | WORKFLOW_EXECUTION_UUID, | ||
| + | CONCAT('failures[', fe.FAILURE_EVENT_ID ,']:failure'), |
mcovarr
Contributor
|
mcovarr
and 1 other
commented on an outdated diff
Sep 2, 2016
| + WORKFLOW_EXECUTION_UUID, | ||
| + METADATA_KEY, | ||
| + CALL_FQN, | ||
| + JOB_SCATTER_INDEX, | ||
| + JOB_RETRY_ATTEMPT, | ||
| + METADATA_VALUE, | ||
| + METADATA_VALUE_TYPE, | ||
| + METADATA_TIMESTAMP | ||
| + ) | ||
| + SELECT | ||
| + WORKFLOW_EXECUTION_UUID, | ||
| + 'start', | ||
| + CALL_FQN, | ||
| + IDX, | ||
| + ATTEMPT, | ||
| + DATE_FORMAT(e.START_DT, '%Y-%m-%dT%T.%f$Offset'), |
mcovarr
Contributor
|
mcovarr
and 1 other
commented on an outdated diff
Sep 2, 2016
| @@ -0,0 +1,37 @@ | ||
| +package cromwell.database.migration.metadata.table.executionevent | ||
| + | ||
| +import cromwell.database.migration.metadata.MetadataCustomSql | ||
| + | ||
| +class ExecutionEventTableDescriptionMigration extends MetadataCustomSql { |
Horneth
Contributor
|
Horneth
removed the
needs rebase ⚔
label
Sep 6, 2016
kshakir
and 1 other
commented on an outdated diff
Sep 6, 2016
| @@ -362,7 +362,7 @@ database { | ||
| driver = "slick.driver.HsqldbDriver$" | ||
| db { | ||
| driver = "org.hsqldb.jdbcDriver" | ||
| - url = "jdbc:hsqldb:mem:${uniqueSchema};shutdown=false;hsqldb.tx=mvcc" | ||
| + url = "jdbc:hsqldb:mem:${uniqueSchema};shutdown=false;hsqldb.tx=mvcc;allow_empty_batch=true" |
kshakir
Contributor
|
geoffjentry
commented on an outdated diff
Sep 6, 2016
| + START_DT, | ||
| + END_DT, | ||
| + ALLOWS_RESULT_REUSE, | ||
| + DOCKER_IMAGE_HASH, | ||
| + EXECUTION_HASH, | ||
| + ATTEMPT, | ||
| + BACKEND_TYPE | ||
| + FROM EXECUTION e | ||
| + WHERE e.CALL_FQN NOT LIKE '%$%' AND -- filter out scatters | ||
| + NOT (e.IDX = -1 AND EXISTS ( -- filter out collectors | ||
| + SELECT 1 FROM EXECUTION e2 WHERE | ||
| + e2.WORKFLOW_EXECUTION_ID = e.WORKFLOW_EXECUTION_ID AND | ||
| + e2.CALL_FQN = e.CALL_FQN AND | ||
| + e2.IDX != -1) | ||
| + ); | ||
| + |
|
|
kshakir
commented on the diff
Sep 7, 2016
| + </comment> | ||
| + <renameColumn columnDataType="VARCHAR(255)" | ||
| + newColumnName="CALL_FQN" | ||
| + oldColumnName="METADATA_CALL_FQN" | ||
| + tableName="METADATA_JOURNAL"/> | ||
| + <renameColumn columnDataType="INT" | ||
| + newColumnName="JOB_SCATTER_INDEX" | ||
| + oldColumnName="METADATA_CALL_INDEX" | ||
| + tableName="METADATA_JOURNAL"/> | ||
| + <renameColumn columnDataType="INT" | ||
| + newColumnName="JOB_RETRY_ATTEMPT" | ||
| + oldColumnName="METADATA_CALL_ATTEMPT" | ||
| + tableName="METADATA_JOURNAL"/> | ||
| + </changeSet> | ||
| + | ||
| +</databaseChangeLog> |
kshakir
Contributor
|
Horneth
merged commit 74c058d
into
develop
Sep 9, 2016
|
@Horneth woohoo! |
Horneth commentedAug 9, 2016
•
edited
Uses liquibase custom change to write classes that transform pre-0.20 existing data into 0.20 metadata.