You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by vb...@apache.org on 2015/06/14 11:10:57 UTC
ambari git commit: AMBARI-11905. Fix idempotent issue for
Oracle.(vbrodetskyi)
Repository: ambari
Updated Branches:
refs/heads/trunk 458e7094e -> 93a93c1ef
AMBARI-11905. Fix idempotent issue for Oracle.(vbrodetskyi)
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/93a93c1e
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/93a93c1e
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/93a93c1e
Branch: refs/heads/trunk
Commit: 93a93c1ef71d30c274d31b9eda5c83b926b34fb8
Parents: 458e709
Author: Vitaly Brodetskyi <vb...@hortonworks.com>
Authored: Sun Jun 14 12:10:41 2015 +0300
Committer: Vitaly Brodetskyi <vb...@hortonworks.com>
Committed: Sun Jun 14 12:10:41 2015 +0300
----------------------------------------------------------------------
.../apache/ambari/server/orm/DBAccessor.java | 44 ++++++++++
.../ambari/server/orm/DBAccessorImpl.java | 84 +++++++++++++++++---
.../server/orm/helpers/dbms/OracleHelper.java | 11 +++
.../server/upgrade/UpgradeCatalog210.java | 6 +-
.../server/upgrade/UpgradeCatalog210Test.java | 68 +++++++++-------
5 files changed, 172 insertions(+), 41 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ambari/blob/93a93c1e/ambari-server/src/main/java/org/apache/ambari/server/orm/DBAccessor.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/DBAccessor.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/DBAccessor.java
index 27dd320..997aeb8 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/DBAccessor.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/DBAccessor.java
@@ -239,6 +239,23 @@ public interface DBAccessor {
void executeScript(String filePath) throws SQLException, IOException;
/**
+ *
+ * @param query update query
+ * @return same like {@code java.sql.Statement}
+ * @throws SQLException
+ */
+ int executeUpdate(String query) throws SQLException;
+
+ /**
+ *
+ * @param query update query
+ * @param ignoreErrors true to ignore errors
+ * @return same like {@code java.sql.Statement}
+ * @throws SQLException
+ */
+ int executeUpdate(String query, boolean ignoreErrors) throws SQLException;
+
+ /**
* Conditional ad-hoc query on DB
* @param query
* @param tableName
@@ -488,9 +505,26 @@ public interface DBAccessor {
int getColumnType(String tableName, String columnName)
throws SQLException;
+ /**
+ * Get type class of the column
+ * @param tableName name of the table
+ * @param columnName name of the column
+ * @return
+ * @throws SQLException
+ * @throws ClassNotFoundException
+ */
Class getColumnClass(String tableName, String columnName) throws SQLException, ClassNotFoundException;
/**
+ * Check if column could be nullable
+ * @param tableName name of the table
+ * @param columnName name of the column
+ * @return true if column could be nullable
+ * @throws SQLException
+ */
+ boolean isColumnNullable(String tableName, String columnName) throws SQLException;
+
+ /**
* Sets the specified column to either allow or prohibit {@code NULL}.
*
* @param tableName
@@ -508,6 +542,16 @@ public interface DBAccessor {
void setColumnNullable(String tableName, String columnName, boolean nullable)
throws SQLException;
+ /**
+ * Alter column wrapper, which handle DB specific type conversion
+ * @param tableName name of the table
+ * @param columnName name of the column
+ * @param fromType previous type
+ * @param toType new desired type
+ * @throws SQLException
+ */
+ void changeColumnType(String tableName, String columnName, Class fromType, Class toType) throws SQLException;
+
enum DbType {
ORACLE,
MYSQL,
http://git-wip-us.apache.org/repos/asf/ambari/blob/93a93c1e/ambari-server/src/main/java/org/apache/ambari/server/orm/DBAccessorImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/DBAccessorImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/DBAccessorImpl.java
index 4823179..c891691 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/DBAccessorImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/DBAccessorImpl.java
@@ -611,6 +611,26 @@ public class DBAccessorImpl implements DBAccessor {
}
@Override
+ public int executeUpdate(String query) throws SQLException{
+ return executeUpdate(query, false);
+ }
+
+ @Override
+ public int executeUpdate(String query, boolean ignoreErrors) throws SQLException{
+ Statement statement = getConnection().createStatement();
+ try {
+ return statement.executeUpdate(query);
+ } catch (SQLException e){
+ LOG.warn("Error executing query: " + query + ", " +
+ "errorCode = " + e.getErrorCode() + ", message = " + e.getMessage());
+ if (!ignoreErrors){
+ throw e;
+ }
+ }
+ return 0; // If error appears and ignoreError is set, return 0 (no changes was made)
+ }
+
+ @Override
public void executeQuery(String query, String tableName, String hasColumnName) throws SQLException{
if (tableHasColumn(tableName, hasColumnName)){
executeQuery(query);
@@ -755,7 +775,6 @@ public class DBAccessorImpl implements DBAccessor {
login.setDatabaseURL(configuration.getDatabaseUrl());
login.setDriverClassName(configuration.getDatabaseDriver());
-
return new DatabaseSessionImpl(login);
}
@@ -771,7 +790,6 @@ public class DBAccessorImpl implements DBAccessor {
} else if (rs != null){
return rs.next();
}
-
return false;
}
@@ -781,27 +799,35 @@ public class DBAccessorImpl implements DBAccessor {
// We doesn't require any actual result except metadata, so WHERE clause shouldn't match
String query = String.format("SELECT %s FROM %s WHERE 1=2", columnName, convertObjectName(tableName));
ResultSet rs = executeSelect(query);
-
ResultSetMetaData rsmd = rs.getMetaData();
return rsmd.getColumnType(1);
}
+ private ResultSetMetaData getColumnMetadata(String tableName, String columnName) throws SQLException{
+ // We doesn't require any actual result except metadata, so WHERE clause shouldn't match
+ String query = String.format("SELECT %s FROM %s WHERE 1=2", convertObjectName(columnName), convertObjectName(tableName));
+ ResultSet rs = executeSelect(query);
+ return rs.getMetaData();
+ }
+
@Override
public Class getColumnClass(String tableName, String columnName)
throws SQLException, ClassNotFoundException{
- // We doesn't require any actual result except metadata, so WHERE clause shouldn't match
- String query = String.format("SELECT %s FROM %s WHERE 1=2", columnName, convertObjectName(tableName));
- ResultSet rs = executeSelect(query);
-
- ResultSetMetaData rsmd = rs.getMetaData();
+ ResultSetMetaData rsmd = getColumnMetadata(tableName, columnName);
return Class.forName(rsmd.getColumnClassName(1));
}
@Override
+ public boolean isColumnNullable(String tableName, String columnName) throws SQLException{
+ ResultSetMetaData rsmd = getColumnMetadata(tableName, columnName);
+ return !(rsmd.isNullable(1) == ResultSetMetaData.columnNoNulls);
+ }
+
+ @Override
public void setColumnNullable(String tableName, DBAccessor.DBColumnInfo columnInfo, boolean nullable)
throws SQLException {
- String statement = dbmsHelper.getSetNullableStatement(tableName, columnInfo, nullable);
+ String statement = dbmsHelper.getSetNullableStatement(tableName, columnInfo, nullable);
executeQuery(statement);
}
@@ -809,12 +835,46 @@ public class DBAccessorImpl implements DBAccessor {
public void setColumnNullable(String tableName, String columnName, boolean nullable)
throws SQLException {
try {
- Class columnClass = getColumnClass(tableName, columnName);
- String query = dbmsHelper.getSetNullableStatement(tableName, new DBColumnInfo(columnName, columnClass), nullable);
- executeQuery(query);
+ // if column is already in nullable state, we shouldn't do anything. This is important for Oracle
+ if (isColumnNullable(tableName, columnName) != nullable) {
+ Class columnClass = getColumnClass(tableName, columnName);
+ String query = dbmsHelper.getSetNullableStatement(tableName, new DBColumnInfo(columnName, columnClass), nullable);
+ executeQuery(query);
+ } else {
+ LOG.info("Column nullability property is not changed due to {} column from {} table is already in {} state, skipping",
+ columnName, tableName, (nullable)?"nullable":"not nullable");
+ }
} catch (ClassNotFoundException e) {
LOG.error("Could not modify table=[], column={}, error={}", tableName, columnName, e.getMessage());
}
}
+ @Override
+ public void changeColumnType(String tableName, String columnName, Class fromType, Class toType) throws SQLException {
+ // ToDo: create column with more random name
+ String tempColumnName = columnName + "_temp";
+
+ switch (configuration.getDatabaseType()){
+ case ORACLE:
+ // ToDo: add check, if target column is a part of constraint.
+ // oracle doesn't support direct type change from varchar2 -> clob
+ if (String.class.equals(fromType) && (Character[].class.equals(toType) || char[].class.equals(toType))){
+ addColumn(tableName, new DBColumnInfo(tempColumnName, toType));
+ executeUpdate(String.format("UPDATE %s SET %s = %s", convertObjectName(tableName),
+ convertObjectName(tempColumnName), convertObjectName(columnName)));
+ dropColumn(tableName, columnName);
+ renameColumn(tableName,tempColumnName, new DBColumnInfo(columnName, toType));
+ return;
+ }
+ }
+
+ alterColumn(tableName, new DBColumnInfo(columnName, toType, null));
+ }
+
+
+
+
+
+
+
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/93a93c1e/ambari-server/src/main/java/org/apache/ambari/server/orm/helpers/dbms/OracleHelper.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/helpers/dbms/OracleHelper.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/helpers/dbms/OracleHelper.java
index 0059566..88ef8fe 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/helpers/dbms/OracleHelper.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/helpers/dbms/OracleHelper.java
@@ -52,4 +52,15 @@ public class OracleHelper extends GenericDbmsHelper {
builder.append(nullStatement);
return builder;
}
+
+ @Override
+ public String writeGetTableConstraints(String databaseName, String tableName) {
+ StringBuilder statement = new StringBuilder()
+ .append("SELECT CONSTRAINT_NAME as constraint_name, CONSTRAINT_TYPE as constraint_type ")
+ .append("FROM USER_CONSTRAINTS ")
+ .append("WHERE ")
+ .append("USER_CONSTRAINTS.TABLE_NAME='").append(tableName.toUpperCase()).append("'");
+ return statement.toString();
+ }
+
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/93a93c1e/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog210.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog210.java b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog210.java
index 51bdd91..9a22aa6 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog210.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog210.java
@@ -269,12 +269,14 @@ public class UpgradeCatalog210 extends AbstractUpgradeCatalog {
private void executeAlertDDLUpdates() throws AmbariException, SQLException {
//Fix latest_text column type to match for all DBMS
Configuration.DatabaseType databaseType = configuration.getDatabaseType();
+
+ // MySQL columns are already TEXT, but we need to be sure in that, since LONGTEXT will really slowdown database when querying the alerts too often
if (Configuration.DatabaseType.MYSQL == databaseType) {
dbAccessor.alterColumn("alert_current", new DBColumnInfo("latest_text", new FieldTypeDefinition("TEXT"), null));
dbAccessor.alterColumn("alert_history", new DBColumnInfo("alert_text", new FieldTypeDefinition("TEXT"), null));
} else {
- dbAccessor.alterColumn("alert_current", new DBColumnInfo("latest_text", Character[].class, null));
- dbAccessor.alterColumn("alert_history", new DBColumnInfo("alert_text", Character[].class, null));
+ dbAccessor.changeColumnType("alert_current", "latest_text", String.class, char[].class);
+ dbAccessor.changeColumnType("alert_history", "alert_text", String.class, char[].class);
}
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/93a93c1e/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog210Test.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog210Test.java b/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog210Test.java
index acc6bed..0515035 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog210Test.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog210Test.java
@@ -623,17 +623,27 @@ public class UpgradeCatalog210Test {
* Verify alert changes
*/
class AlertSectionDDL implements SectionDDL {
+ HashMap<String, Capture<String>> stringCaptures;
+ HashMap<String, Capture<Class>> classCaptures;
- HashMap<String, Capture<DBColumnInfo>> captures;
public AlertSectionDDL() {
- captures = new HashMap<String, Capture<DBColumnInfo>>();
-
- Capture<DBAccessor.DBColumnInfo> alertCurrentColumnCapture = new Capture<DBAccessor.DBColumnInfo>();
- Capture<DBAccessor.DBColumnInfo> alertHistoryColumnCapture = new Capture<DBAccessor.DBColumnInfo>();
-
- captures.put("alert_current", alertCurrentColumnCapture);
- captures.put("alert_history", alertHistoryColumnCapture);
+ stringCaptures = new HashMap<String, Capture<String>>();
+ classCaptures = new HashMap<String, Capture<Class>>();
+
+ Capture<String> textCaptureC = new Capture<String>();
+ Capture<String> textCaptureH = new Capture<String>();
+ Capture<Class> classFromC = new Capture<Class>();
+ Capture<Class> classFromH = new Capture<Class>();
+ Capture<Class> classToC = new Capture<Class>();
+ Capture<Class> classToH = new Capture<Class>();
+
+ stringCaptures.put("textCaptureC", textCaptureC);
+ stringCaptures.put("textCaptureH", textCaptureH);
+ classCaptures.put("classFromC", classFromC);
+ classCaptures.put("classFromH", classFromH);
+ classCaptures.put("classToC", classToC);
+ classCaptures.put("classToH", classToH);
}
/**
@@ -641,11 +651,15 @@ public class UpgradeCatalog210Test {
*/
@Override
public void execute(DBAccessor dbAccessor) throws SQLException {
- Capture<DBColumnInfo> alertCurrentColumnCapture = captures.get("alert_current");
- Capture<DBColumnInfo> alertHistoryColumnCapture = captures.get("alert_history");
-
- dbAccessor.alterColumn(eq("alert_current"), capture(alertCurrentColumnCapture));
- dbAccessor.alterColumn(eq("alert_history"), capture(alertHistoryColumnCapture));
+ Capture<String> textCaptureC = stringCaptures.get("textCaptureC");
+ Capture<String> textCaptureH = stringCaptures.get("textCaptureH");
+ Capture<Class> classFromC = classCaptures.get("classFromC");
+ Capture<Class> classFromH = classCaptures.get("classFromH");
+ Capture<Class> classToC = classCaptures.get("classToC");
+ Capture<Class> classToH = classCaptures.get("classToH");
+
+ dbAccessor.changeColumnType(eq("alert_current"), capture(textCaptureC), capture(classFromC), capture(classToC));
+ dbAccessor.changeColumnType(eq("alert_history"), capture(textCaptureH), capture(classFromH), capture(classToH));
}
/**
@@ -653,20 +667,20 @@ public class UpgradeCatalog210Test {
*/
@Override
public void verify(DBAccessor dbAccessor) throws SQLException {
- verifyAlertCurrent(captures.get("alert_current"));
- verifyAlertHistory(captures.get("alert_history"));
- }
-
- private void verifyAlertCurrent(Capture<DBAccessor.DBColumnInfo> alertCurrentColumnCapture) {
- DBColumnInfo latestTextColumn = alertCurrentColumnCapture.getValue();
- Assert.assertEquals(Character[].class, latestTextColumn.getType());
- Assert.assertEquals("latest_text", latestTextColumn.getName());
- }
-
- private void verifyAlertHistory(Capture<DBAccessor.DBColumnInfo> alertHistoryColumnCapture) {
- DBColumnInfo alertTextColumn = alertHistoryColumnCapture.getValue();
- Assert.assertEquals(Character[].class, alertTextColumn.getType());
- Assert.assertEquals("alert_text", alertTextColumn.getName());
+ Capture<String> textCaptureC = stringCaptures.get("textCaptureC");
+ Capture<String> textCaptureH = stringCaptures.get("textCaptureH");
+ Capture<Class> classFromC = classCaptures.get("classFromC");
+ Capture<Class> classFromH = classCaptures.get("classFromH");
+ Capture<Class> classToC = classCaptures.get("classToC");
+ Capture<Class> classToH = classCaptures.get("classToH");
+
+ Assert.assertEquals("latest_text", textCaptureC.getValue());
+ Assert.assertEquals(String.class, classFromC.getValue());
+ Assert.assertEquals(char[].class, classToC.getValue());
+
+ Assert.assertEquals("alert_text", textCaptureH.getValue());
+ Assert.assertEquals(String.class, classFromH.getValue());
+ Assert.assertEquals(char[].class, classToH.getValue());
}
}
}