同步最新的达梦适配
This commit is contained in:
parent
a47cd877f8
commit
4e83cef189
@ -0,0 +1,598 @@
|
|||||||
|
package liquibase.database.core;
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.sql.Connection;
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.sql.Statement;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Properties;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
import liquibase.CatalogAndSchema;
|
||||||
|
import liquibase.Scope;
|
||||||
|
import liquibase.database.AbstractJdbcDatabase;
|
||||||
|
import liquibase.database.DatabaseConnection;
|
||||||
|
import liquibase.database.OfflineConnection;
|
||||||
|
import liquibase.database.jvm.JdbcConnection;
|
||||||
|
import liquibase.exception.DatabaseException;
|
||||||
|
import liquibase.exception.UnexpectedLiquibaseException;
|
||||||
|
import liquibase.exception.ValidationErrors;
|
||||||
|
import liquibase.executor.ExecutorService;
|
||||||
|
import liquibase.statement.DatabaseFunction;
|
||||||
|
import liquibase.statement.SequenceCurrentValueFunction;
|
||||||
|
import liquibase.statement.SequenceNextValueFunction;
|
||||||
|
import liquibase.statement.core.RawCallStatement;
|
||||||
|
import liquibase.statement.core.RawSqlStatement;
|
||||||
|
import liquibase.structure.DatabaseObject;
|
||||||
|
import liquibase.structure.core.Catalog;
|
||||||
|
import liquibase.structure.core.Index;
|
||||||
|
import liquibase.structure.core.PrimaryKey;
|
||||||
|
import liquibase.structure.core.Schema;
|
||||||
|
import liquibase.util.JdbcUtils;
|
||||||
|
import liquibase.util.StringUtil;
|
||||||
|
|
||||||
|
public class DmDatabase extends AbstractJdbcDatabase {
|
||||||
|
private static final String PRODUCT_NAME = "DM DBMS";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getDefaultDatabaseProductName() {
|
||||||
|
return PRODUCT_NAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is this AbstractDatabase subclass the correct one to use for the given connection.
|
||||||
|
*
|
||||||
|
* @param conn
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean isCorrectDatabaseImplementation(DatabaseConnection conn) throws DatabaseException {
|
||||||
|
return PRODUCT_NAME.equalsIgnoreCase(conn.getDatabaseProductName());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If this database understands the given url, return the default driver class name. Otherwise return null.
|
||||||
|
*
|
||||||
|
* @param url
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String getDefaultDriver(String url) {
|
||||||
|
if(url.startsWith("jdbc:dm")) {
|
||||||
|
return "dm.jdbc.driver.DmDriver";
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an all-lower-case short name of the product. Used for end-user selecting of database type
|
||||||
|
* such as the DBMS precondition.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String getShortName() {
|
||||||
|
return "dm";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Integer getDefaultPort() {
|
||||||
|
return 5236;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether this database support initially deferrable columns.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean supportsInitiallyDeferrableColumns() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean supportsTablespaces() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getPriority() {
|
||||||
|
return PRIORITY_DEFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final Pattern PROXY_USER = Pattern.compile(".*(?:thin|oci)\\:(.+)/@.*");
|
||||||
|
|
||||||
|
protected final int SHORT_IDENTIFIERS_LENGTH = 30;
|
||||||
|
protected final int LONG_IDENTIFIERS_LEGNTH = 128;
|
||||||
|
public static final int ORACLE_12C_MAJOR_VERSION = 12;
|
||||||
|
|
||||||
|
private Set<String> reservedWords = new HashSet<>();
|
||||||
|
private Set<String> userDefinedTypes;
|
||||||
|
private Map<String, String> savedSessionNlsSettings;
|
||||||
|
|
||||||
|
private Boolean canAccessDbaRecycleBin;
|
||||||
|
private Integer databaseMajorVersion;
|
||||||
|
private Integer databaseMinorVersion;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default constructor for an object that represents the Oracle Database DBMS.
|
||||||
|
*/
|
||||||
|
public DmDatabase() {
|
||||||
|
super.unquotedObjectsAreUppercased = true;
|
||||||
|
//noinspection HardCodedStringLiteral
|
||||||
|
super.setCurrentDateTimeFunction("SYSTIMESTAMP");
|
||||||
|
// Setting list of Oracle's native functions
|
||||||
|
//noinspection HardCodedStringLiteral
|
||||||
|
dateFunctions.add(new DatabaseFunction("SYSDATE"));
|
||||||
|
//noinspection HardCodedStringLiteral
|
||||||
|
dateFunctions.add(new DatabaseFunction("SYSTIMESTAMP"));
|
||||||
|
//noinspection HardCodedStringLiteral
|
||||||
|
dateFunctions.add(new DatabaseFunction("CURRENT_TIMESTAMP"));
|
||||||
|
//noinspection HardCodedStringLiteral
|
||||||
|
super.sequenceNextValueFunction = "%s.nextval";
|
||||||
|
//noinspection HardCodedStringLiteral
|
||||||
|
super.sequenceCurrentValueFunction = "%s.currval";
|
||||||
|
}
|
||||||
|
|
||||||
|
private void tryProxySession(final String url, final Connection con) {
|
||||||
|
Matcher m = PROXY_USER.matcher(url);
|
||||||
|
if (m.matches()) {
|
||||||
|
Properties props = new Properties();
|
||||||
|
props.put("PROXY_USER_NAME", m.group(1));
|
||||||
|
try {
|
||||||
|
Method method = con.getClass().getMethod("openProxySession", int.class, Properties.class);
|
||||||
|
method.setAccessible(true);
|
||||||
|
method.invoke(con, 1, props);
|
||||||
|
} catch (Exception e) {
|
||||||
|
Scope.getCurrentScope().getLog(getClass()).info("Could not open proxy session on OracleDatabase: " + e.getCause().getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getDatabaseMajorVersion() throws DatabaseException {
|
||||||
|
if (databaseMajorVersion == null) {
|
||||||
|
return super.getDatabaseMajorVersion();
|
||||||
|
} else {
|
||||||
|
return databaseMajorVersion;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getDatabaseMinorVersion() throws DatabaseException {
|
||||||
|
if (databaseMinorVersion == null) {
|
||||||
|
return super.getDatabaseMinorVersion();
|
||||||
|
} else {
|
||||||
|
return databaseMinorVersion;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getJdbcCatalogName(CatalogAndSchema schema) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getJdbcSchemaName(CatalogAndSchema schema) {
|
||||||
|
return correctObjectName((schema.getCatalogName() == null) ? schema.getSchemaName() : schema.getCatalogName(), Schema.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getAutoIncrementClause(final String generationType, final Boolean defaultOnNull) {
|
||||||
|
if (StringUtil.isEmpty(generationType)) {
|
||||||
|
return super.getAutoIncrementClause();
|
||||||
|
}
|
||||||
|
|
||||||
|
String autoIncrementClause = "GENERATED %s AS IDENTITY"; // %s -- [ ALWAYS | BY DEFAULT [ ON NULL ] ]
|
||||||
|
String generationStrategy = generationType;
|
||||||
|
if (Boolean.TRUE.equals(defaultOnNull) && generationType.toUpperCase().equals("BY DEFAULT")) {
|
||||||
|
generationStrategy += " ON NULL";
|
||||||
|
}
|
||||||
|
return String.format(autoIncrementClause, generationStrategy);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String generatePrimaryKeyName(String tableName) {
|
||||||
|
if (tableName.length() > 27) {
|
||||||
|
//noinspection HardCodedStringLiteral
|
||||||
|
return "PK_" + tableName.toUpperCase(Locale.US).substring(0, 27);
|
||||||
|
} else {
|
||||||
|
//noinspection HardCodedStringLiteral
|
||||||
|
return "PK_" + tableName.toUpperCase(Locale.US);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isReservedWord(String objectName) {
|
||||||
|
return reservedWords.contains(objectName.toUpperCase());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean supportsSequences() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Oracle supports catalogs in liquibase terms
|
||||||
|
*
|
||||||
|
* @return false
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean supportsSchemas() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getConnectionCatalogName() throws DatabaseException {
|
||||||
|
if (getConnection() instanceof OfflineConnection) {
|
||||||
|
return getConnection().getCatalog();
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
//noinspection HardCodedStringLiteral
|
||||||
|
return Scope.getCurrentScope().getSingleton(ExecutorService.class).getExecutor("jdbc", this).queryForObject(new RawCallStatement("select sys_context( 'userenv', 'current_schema' ) from dual"), String.class);
|
||||||
|
} catch (Exception e) {
|
||||||
|
//noinspection HardCodedStringLiteral
|
||||||
|
Scope.getCurrentScope().getLog(getClass()).info("Error getting default schema", e);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDefaultCatalogName() {//NOPMD
|
||||||
|
return (super.getDefaultCatalogName() == null) ? null : super.getDefaultCatalogName().toUpperCase(Locale.US);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Returns an Oracle date literal with the same value as a string formatted using ISO 8601.</p>
|
||||||
|
*
|
||||||
|
* <p>Convert an ISO8601 date string to one of the following results:
|
||||||
|
* to_date('1995-05-23', 'YYYY-MM-DD')
|
||||||
|
* to_date('1995-05-23 09:23:59', 'YYYY-MM-DD HH24:MI:SS')</p>
|
||||||
|
* <p>
|
||||||
|
* Implementation restriction:<br>
|
||||||
|
* Currently, only the following subsets of ISO8601 are supported:<br>
|
||||||
|
* <ul>
|
||||||
|
* <li>YYYY-MM-DD</li>
|
||||||
|
* <li>YYYY-MM-DDThh:mm:ss</li>
|
||||||
|
* </ul>
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String getDateLiteral(String isoDate) {
|
||||||
|
String normalLiteral = super.getDateLiteral(isoDate);
|
||||||
|
|
||||||
|
if (isDateOnly(isoDate)) {
|
||||||
|
return "TO_DATE(" + normalLiteral + ", 'YYYY-MM-DD')";
|
||||||
|
} else if (isTimeOnly(isoDate)) {
|
||||||
|
return "TO_DATE(" + normalLiteral + ", 'HH24:MI:SS')";
|
||||||
|
} else if (isTimestamp(isoDate)) {
|
||||||
|
return "TO_TIMESTAMP(" + normalLiteral + ", 'YYYY-MM-DD HH24:MI:SS.FF')";
|
||||||
|
} else if (isDateTime(isoDate)) {
|
||||||
|
int seppos = normalLiteral.lastIndexOf('.');
|
||||||
|
if (seppos != -1) {
|
||||||
|
normalLiteral = normalLiteral.substring(0, seppos) + "'";
|
||||||
|
}
|
||||||
|
return "TO_DATE(" + normalLiteral + ", 'YYYY-MM-DD HH24:MI:SS')";
|
||||||
|
}
|
||||||
|
return "UNSUPPORTED:" + isoDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isSystemObject(DatabaseObject example) {
|
||||||
|
if (example == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.isLiquibaseObject(example)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (example instanceof Schema) {
|
||||||
|
//noinspection HardCodedStringLiteral,HardCodedStringLiteral,HardCodedStringLiteral,HardCodedStringLiteral
|
||||||
|
if ("SYSTEM".equals(example.getName()) || "SYS".equals(example.getName()) || "CTXSYS".equals(example.getName()) || "XDB".equals(example.getName())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
//noinspection HardCodedStringLiteral,HardCodedStringLiteral,HardCodedStringLiteral,HardCodedStringLiteral
|
||||||
|
if ("SYSTEM".equals(example.getSchema().getCatalogName()) || "SYS".equals(example.getSchema().getCatalogName()) || "CTXSYS".equals(example.getSchema().getCatalogName()) || "XDB".equals(example.getSchema().getCatalogName())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else if (isSystemObject(example.getSchema())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (example instanceof Catalog) {
|
||||||
|
//noinspection HardCodedStringLiteral,HardCodedStringLiteral,HardCodedStringLiteral,HardCodedStringLiteral
|
||||||
|
if (("SYSTEM".equals(example.getName()) || "SYS".equals(example.getName()) || "CTXSYS".equals(example.getName()) || "XDB".equals(example.getName()))) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else if (example.getName() != null) {
|
||||||
|
//noinspection HardCodedStringLiteral
|
||||||
|
if (example.getName().startsWith("BIN$")) { //oracle deleted table
|
||||||
|
boolean filteredInOriginalQuery = this.canAccessDbaRecycleBin();
|
||||||
|
if (!filteredInOriginalQuery) {
|
||||||
|
filteredInOriginalQuery = StringUtil.trimToEmpty(example.getSchema().getName()).equalsIgnoreCase(this.getConnection().getConnectionUserName());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filteredInOriginalQuery) {
|
||||||
|
return !((example instanceof PrimaryKey) || (example instanceof Index) || (example instanceof
|
||||||
|
liquibase.statement.UniqueConstraint));
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else //noinspection HardCodedStringLiteral
|
||||||
|
if (example.getName().startsWith("AQ$")) { //oracle AQ tables
|
||||||
|
return true;
|
||||||
|
} else //noinspection HardCodedStringLiteral
|
||||||
|
if (example.getName().startsWith("DR$")) { //oracle index tables
|
||||||
|
return true;
|
||||||
|
} else //noinspection HardCodedStringLiteral
|
||||||
|
if (example.getName().startsWith("SYS_IOT_OVER")) { //oracle system table
|
||||||
|
return true;
|
||||||
|
} else //noinspection HardCodedStringLiteral,HardCodedStringLiteral
|
||||||
|
if ((example.getName().startsWith("MDRT_") || example.getName().startsWith("MDRS_")) && example.getName().endsWith("$")) {
|
||||||
|
// CORE-1768 - Oracle creates these for spatial indices and will remove them when the index is removed.
|
||||||
|
return true;
|
||||||
|
} else //noinspection HardCodedStringLiteral
|
||||||
|
if (example.getName().startsWith("MLOG$_")) { //Created by materliaized view logs for every table that is part of a materialized view. Not available for DDL operations.
|
||||||
|
return true;
|
||||||
|
} else //noinspection HardCodedStringLiteral
|
||||||
|
if (example.getName().startsWith("RUPD$_")) { //Created by materialized view log tables using primary keys. Not available for DDL operations.
|
||||||
|
return true;
|
||||||
|
} else //noinspection HardCodedStringLiteral
|
||||||
|
if (example.getName().startsWith("WM$_")) { //Workspace Manager backup tables.
|
||||||
|
return true;
|
||||||
|
} else //noinspection HardCodedStringLiteral
|
||||||
|
if ("CREATE$JAVA$LOB$TABLE".equals(example.getName())) { //This table contains the name of the Java object, the date it was loaded, and has a BLOB column to store the Java object.
|
||||||
|
return true;
|
||||||
|
} else //noinspection HardCodedStringLiteral
|
||||||
|
if ("JAVA$CLASS$MD5$TABLE".equals(example.getName())) { //This is a hash table that tracks the loading of Java objects into a schema.
|
||||||
|
return true;
|
||||||
|
} else //noinspection HardCodedStringLiteral
|
||||||
|
if (example.getName().startsWith("ISEQ$$_")) { //System-generated sequence
|
||||||
|
return true;
|
||||||
|
} else //noinspection HardCodedStringLiteral
|
||||||
|
if (example.getName().startsWith("USLOG$")) { //for update materialized view
|
||||||
|
return true;
|
||||||
|
} else if (example.getName().startsWith("SYS_FBA")) { //for Flashback tables
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return super.isSystemObject(example);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean supportsAutoIncrement() {
|
||||||
|
// Oracle supports Identity beginning with version 12c
|
||||||
|
boolean isAutoIncrementSupported = false;
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (getDatabaseMajorVersion() >= 12) {
|
||||||
|
isAutoIncrementSupported = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returning true will generate create table command with 'IDENTITY' clause, example:
|
||||||
|
// CREATE TABLE AutoIncTest (IDPrimaryKey NUMBER(19) GENERATED BY DEFAULT AS IDENTITY NOT NULL, TypeID NUMBER(3) NOT NULL, Description NVARCHAR2(50), CONSTRAINT PK_AutoIncTest PRIMARY KEY (IDPrimaryKey));
|
||||||
|
|
||||||
|
// While returning false will continue to generate create table command without 'IDENTITY' clause, example:
|
||||||
|
// CREATE TABLE AutoIncTest (IDPrimaryKey NUMBER(19) NOT NULL, TypeID NUMBER(3) NOT NULL, Description NVARCHAR2(50), CONSTRAINT PK_AutoIncTest PRIMARY KEY (IDPrimaryKey));
|
||||||
|
|
||||||
|
} catch (DatabaseException ex) {
|
||||||
|
isAutoIncrementSupported = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return isAutoIncrementSupported;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// public Set<UniqueConstraint> findUniqueConstraints(String schema) throws DatabaseException {
|
||||||
|
// Set<UniqueConstraint> returnSet = new HashSet<UniqueConstraint>();
|
||||||
|
//
|
||||||
|
// List<Map> maps = new Executor(this).queryForList(new RawSqlStatement("SELECT UC.CONSTRAINT_NAME, UCC.TABLE_NAME, UCC.COLUMN_NAME FROM USER_CONSTRAINTS UC, USER_CONS_COLUMNS UCC WHERE UC.CONSTRAINT_NAME=UCC.CONSTRAINT_NAME AND CONSTRAINT_TYPE='U' ORDER BY UC.CONSTRAINT_NAME"));
|
||||||
|
//
|
||||||
|
// UniqueConstraint constraint = null;
|
||||||
|
// for (Map map : maps) {
|
||||||
|
// if (constraint == null || !constraint.getName().equals(constraint.getName())) {
|
||||||
|
// returnSet.add(constraint);
|
||||||
|
// Table table = new Table((String) map.get("TABLE_NAME"));
|
||||||
|
// constraint = new UniqueConstraint(map.get("CONSTRAINT_NAME").toString(), table);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// if (constraint != null) {
|
||||||
|
// returnSet.add(constraint);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// return returnSet;
|
||||||
|
// }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean supportsRestrictForeignKeys() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getDataTypeMaxParameters(String dataTypeName) {
|
||||||
|
//noinspection HardCodedStringLiteral
|
||||||
|
if ("BINARY_FLOAT".equals(dataTypeName.toUpperCase())) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
//noinspection HardCodedStringLiteral
|
||||||
|
if ("BINARY_DOUBLE".equals(dataTypeName.toUpperCase())) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return super.getDataTypeMaxParameters(dataTypeName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSystemTableWhereClause(String tableNameColumn) {
|
||||||
|
List<String> clauses = new ArrayList<String>(Arrays.asList("BIN$",
|
||||||
|
"AQ$",
|
||||||
|
"DR$",
|
||||||
|
"SYS_IOT_OVER",
|
||||||
|
"MLOG$_",
|
||||||
|
"RUPD$_",
|
||||||
|
"WM$_",
|
||||||
|
"ISEQ$$_",
|
||||||
|
"USLOG$",
|
||||||
|
"SYS_FBA"));
|
||||||
|
|
||||||
|
for (int i = 0;i<clauses.size(); i++) {
|
||||||
|
clauses.set(i, tableNameColumn+" NOT LIKE '"+clauses.get(i)+"%'");
|
||||||
|
}
|
||||||
|
return "("+ StringUtil.join(clauses, " AND ") + ")";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean jdbcCallsCatalogsSchemas() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<String> getUserDefinedTypes() {
|
||||||
|
if (userDefinedTypes == null) {
|
||||||
|
userDefinedTypes = new HashSet<>();
|
||||||
|
if ((getConnection() != null) && !(getConnection() instanceof OfflineConnection)) {
|
||||||
|
try {
|
||||||
|
try {
|
||||||
|
//noinspection HardCodedStringLiteral
|
||||||
|
userDefinedTypes.addAll(Scope.getCurrentScope().getSingleton(ExecutorService.class).getExecutor("jdbc", this).queryForList(new RawSqlStatement("SELECT DISTINCT TYPE_NAME FROM ALL_TYPES"), String.class));
|
||||||
|
} catch (DatabaseException e) { //fall back to USER_TYPES if the user cannot see ALL_TYPES
|
||||||
|
//noinspection HardCodedStringLiteral
|
||||||
|
userDefinedTypes.addAll(Scope.getCurrentScope().getSingleton(ExecutorService.class).getExecutor("jdbc", this).queryForList(new RawSqlStatement("SELECT TYPE_NAME FROM USER_TYPES"), String.class));
|
||||||
|
}
|
||||||
|
} catch (DatabaseException e) {
|
||||||
|
//ignore error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return userDefinedTypes;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String generateDatabaseFunctionValue(DatabaseFunction databaseFunction) {
|
||||||
|
//noinspection HardCodedStringLiteral
|
||||||
|
if ((databaseFunction != null) && "current_timestamp".equalsIgnoreCase(databaseFunction.toString())) {
|
||||||
|
return databaseFunction.toString();
|
||||||
|
}
|
||||||
|
if ((databaseFunction instanceof SequenceNextValueFunction) || (databaseFunction instanceof
|
||||||
|
SequenceCurrentValueFunction)) {
|
||||||
|
String quotedSeq = super.generateDatabaseFunctionValue(databaseFunction);
|
||||||
|
// replace "myschema.my_seq".nextval with "myschema"."my_seq".nextval
|
||||||
|
return quotedSeq.replaceFirst("\"([^\\.\"]+)\\.([^\\.\"]+)\"", "\"$1\".\"$2\"");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return super.generateDatabaseFunctionValue(databaseFunction);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ValidationErrors validate() {
|
||||||
|
ValidationErrors errors = super.validate();
|
||||||
|
DatabaseConnection connection = getConnection();
|
||||||
|
if ((connection == null) || (connection instanceof OfflineConnection)) {
|
||||||
|
//noinspection HardCodedStringLiteral
|
||||||
|
Scope.getCurrentScope().getLog(getClass()).info("Cannot validate offline database");
|
||||||
|
return errors;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!canAccessDbaRecycleBin()) {
|
||||||
|
errors.addWarning(getDbaRecycleBinWarning());
|
||||||
|
}
|
||||||
|
|
||||||
|
return errors;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDbaRecycleBinWarning() {
|
||||||
|
//noinspection HardCodedStringLiteral,HardCodedStringLiteral,HardCodedStringLiteral,HardCodedStringLiteral,
|
||||||
|
// HardCodedStringLiteral
|
||||||
|
//noinspection HardCodedStringLiteral,HardCodedStringLiteral,HardCodedStringLiteral
|
||||||
|
return "Liquibase needs to access the DBA_RECYCLEBIN table so we can automatically handle the case where " +
|
||||||
|
"constraints are deleted and restored. Since Oracle doesn't properly restore the original table names " +
|
||||||
|
"referenced in the constraint, we use the information from the DBA_RECYCLEBIN to automatically correct this" +
|
||||||
|
" issue.\n" +
|
||||||
|
"\n" +
|
||||||
|
"The user you used to connect to the database (" + getConnection().getConnectionUserName() +
|
||||||
|
") needs to have \"SELECT ON SYS.DBA_RECYCLEBIN\" permissions set before we can perform this operation. " +
|
||||||
|
"Please run the following SQL to set the appropriate permissions, and try running the command again.\n" +
|
||||||
|
"\n" +
|
||||||
|
" GRANT SELECT ON SYS.DBA_RECYCLEBIN TO " + getConnection().getConnectionUserName() + ";";
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean canAccessDbaRecycleBin() {
|
||||||
|
if (canAccessDbaRecycleBin == null) {
|
||||||
|
DatabaseConnection connection = getConnection();
|
||||||
|
if ((connection == null) || (connection instanceof OfflineConnection)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Statement statement = null;
|
||||||
|
try {
|
||||||
|
statement = ((JdbcConnection) connection).createStatement();
|
||||||
|
@SuppressWarnings("HardCodedStringLiteral") ResultSet resultSet = statement.executeQuery("select 1 from dba_recyclebin where 0=1");
|
||||||
|
resultSet.close(); //don't need to do anything with the result set, just make sure statement ran.
|
||||||
|
this.canAccessDbaRecycleBin = true;
|
||||||
|
} catch (Exception e) {
|
||||||
|
//noinspection HardCodedStringLiteral
|
||||||
|
if ((e instanceof SQLException) && e.getMessage().startsWith("ORA-00942")) { //ORA-00942: table or view does not exist
|
||||||
|
this.canAccessDbaRecycleBin = false;
|
||||||
|
} else {
|
||||||
|
//noinspection HardCodedStringLiteral
|
||||||
|
Scope.getCurrentScope().getLog(getClass()).warning("Cannot check dba_recyclebin access", e);
|
||||||
|
this.canAccessDbaRecycleBin = false;
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
JdbcUtils.close(null, statement);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return canAccessDbaRecycleBin;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean supportsNotNullConstraintNames() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests if the given String would be a valid identifier in Oracle DBMS. In Oracle, a valid identifier has
|
||||||
|
* the following form (case-insensitive comparison):
|
||||||
|
* 1st character: A-Z
|
||||||
|
* 2..n characters: A-Z0-9$_#
|
||||||
|
* The maximum length of an identifier differs by Oracle version and object type.
|
||||||
|
*/
|
||||||
|
public boolean isValidOracleIdentifier(String identifier, Class<? extends DatabaseObject> type) {
|
||||||
|
if ((identifier == null) || (identifier.length() < 1))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!identifier.matches("^(i?)[A-Z][A-Z0-9\\$\\_\\#]*$"))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @todo It seems we currently do not have a class for tablespace identifiers, and all other classes
|
||||||
|
* we do know seem to be supported as 12cR2 long identifiers, so:
|
||||||
|
*/
|
||||||
|
return (identifier.length() <= LONG_IDENTIFIERS_LEGNTH);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the maximum number of bytes (NOT: characters) for an identifier. For Oracle <=12c Release 20, this
|
||||||
|
* is 30 bytes, and starting from 12cR2, up to 128 (except for tablespaces, PDB names and some other rather rare
|
||||||
|
* object types).
|
||||||
|
*
|
||||||
|
* @return the maximum length of an object identifier, in bytes
|
||||||
|
*/
|
||||||
|
public int getIdentifierMaximumLength() {
|
||||||
|
try {
|
||||||
|
if (getDatabaseMajorVersion() < ORACLE_12C_MAJOR_VERSION) {
|
||||||
|
return SHORT_IDENTIFIERS_LENGTH;
|
||||||
|
} else if ((getDatabaseMajorVersion() == ORACLE_12C_MAJOR_VERSION) && (getDatabaseMinorVersion() <= 1)) {
|
||||||
|
return SHORT_IDENTIFIERS_LENGTH;
|
||||||
|
} else {
|
||||||
|
return LONG_IDENTIFIERS_LEGNTH;
|
||||||
|
}
|
||||||
|
} catch (DatabaseException ex) {
|
||||||
|
throw new UnexpectedLiquibaseException("Cannot determine the Oracle database version number", ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,165 @@
|
|||||||
|
package liquibase.datatype.core;
|
||||||
|
|
||||||
|
import liquibase.change.core.LoadDataChange;
|
||||||
|
import liquibase.database.Database;
|
||||||
|
import liquibase.database.core.*;
|
||||||
|
import liquibase.datatype.DataTypeInfo;
|
||||||
|
import liquibase.datatype.DatabaseDataType;
|
||||||
|
import liquibase.datatype.LiquibaseDataType;
|
||||||
|
import liquibase.exception.UnexpectedLiquibaseException;
|
||||||
|
import liquibase.statement.DatabaseFunction;
|
||||||
|
import liquibase.util.StringUtil;
|
||||||
|
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
@DataTypeInfo(name = "boolean", aliases = {"java.sql.Types.BOOLEAN", "java.lang.Boolean", "bit", "bool"}, minParameters = 0, maxParameters = 0, priority = LiquibaseDataType.PRIORITY_DEFAULT)
|
||||||
|
public class BooleanType extends LiquibaseDataType {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DatabaseDataType toDatabaseDataType(Database database) {
|
||||||
|
String originalDefinition = StringUtil.trimToEmpty(getRawDefinition());
|
||||||
|
if ((database instanceof Firebird3Database)) {
|
||||||
|
return new DatabaseDataType("BOOLEAN");
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((database instanceof Db2zDatabase) || (database instanceof FirebirdDatabase)) {
|
||||||
|
return new DatabaseDataType("SMALLINT");
|
||||||
|
} else if (database instanceof MSSQLDatabase) {
|
||||||
|
return new DatabaseDataType(database.escapeDataTypeName("bit"));
|
||||||
|
} else if (database instanceof MySQLDatabase) {
|
||||||
|
if (originalDefinition.toLowerCase(Locale.US).startsWith("bit")) {
|
||||||
|
return new DatabaseDataType("BIT", getParameters());
|
||||||
|
}
|
||||||
|
return new DatabaseDataType("BIT", 1);
|
||||||
|
} else if (database instanceof OracleDatabase) {
|
||||||
|
return new DatabaseDataType("NUMBER", 1);
|
||||||
|
} else if ((database instanceof SybaseASADatabase) || (database instanceof SybaseDatabase)) {
|
||||||
|
return new DatabaseDataType("BIT");
|
||||||
|
} else if (database instanceof DerbyDatabase) {
|
||||||
|
if (((DerbyDatabase) database).supportsBooleanDataType()) {
|
||||||
|
return new DatabaseDataType("BOOLEAN");
|
||||||
|
} else {
|
||||||
|
return new DatabaseDataType("SMALLINT");
|
||||||
|
}
|
||||||
|
} else if (database instanceof DB2Database) {
|
||||||
|
if (((DB2Database) database).supportsBooleanDataType())
|
||||||
|
return new DatabaseDataType("BOOLEAN");
|
||||||
|
else
|
||||||
|
return new DatabaseDataType("SMALLINT");
|
||||||
|
} else if (database instanceof HsqlDatabase) {
|
||||||
|
return new DatabaseDataType("BOOLEAN");
|
||||||
|
} else if (database instanceof PostgresDatabase) {
|
||||||
|
if (originalDefinition.toLowerCase(Locale.US).startsWith("bit")) {
|
||||||
|
return new DatabaseDataType("BIT", getParameters());
|
||||||
|
}
|
||||||
|
} else if (database instanceof DmDatabase) { // dhb52: DM Support
|
||||||
|
return new DatabaseDataType("bit");
|
||||||
|
}
|
||||||
|
|
||||||
|
return super.toDatabaseDataType(database);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String objectToSql(Object value, Database database) {
|
||||||
|
if ((value == null) || "null".equals(value.toString().toLowerCase(Locale.US))) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
String returnValue;
|
||||||
|
if (value instanceof String) {
|
||||||
|
value = ((String) value).replaceAll("'", "");
|
||||||
|
if ("true".equals(((String) value).toLowerCase(Locale.US)) || "1".equals(value) || "b'1'".equals(((String) value).toLowerCase(Locale.US)) || "t".equals(((String) value).toLowerCase(Locale.US)) || ((String) value).toLowerCase(Locale.US).equals(this.getTrueBooleanValue(database).toLowerCase(Locale.US))) {
|
||||||
|
returnValue = this.getTrueBooleanValue(database);
|
||||||
|
} else if ("false".equals(((String) value).toLowerCase(Locale.US)) || "0".equals(value) || "b'0'".equals(
|
||||||
|
((String) value).toLowerCase(Locale.US)) || "f".equals(((String) value).toLowerCase(Locale.US)) || ((String) value).toLowerCase(Locale.US).equals(this.getFalseBooleanValue(database).toLowerCase(Locale.US))) {
|
||||||
|
returnValue = this.getFalseBooleanValue(database);
|
||||||
|
} else if (database instanceof PostgresDatabase && Pattern.matches("b?([01])\\1*(::bit|::\"bit\")?", (String) value)) {
|
||||||
|
returnValue = "b'"
|
||||||
|
+ value.toString()
|
||||||
|
.replace("b", "")
|
||||||
|
.replace("\"", "")
|
||||||
|
.replace("::it", "")
|
||||||
|
+ "'::\"bit\"";
|
||||||
|
} else {
|
||||||
|
throw new UnexpectedLiquibaseException("Unknown boolean value: " + value);
|
||||||
|
}
|
||||||
|
} else if (value instanceof Long) {
|
||||||
|
if (Long.valueOf(1).equals(value)) {
|
||||||
|
returnValue = this.getTrueBooleanValue(database);
|
||||||
|
} else {
|
||||||
|
returnValue = this.getFalseBooleanValue(database);
|
||||||
|
}
|
||||||
|
} else if (value instanceof Number) {
|
||||||
|
if (value.equals(1) || "1".equals(value.toString()) || "1.0".equals(value.toString())) {
|
||||||
|
returnValue = this.getTrueBooleanValue(database);
|
||||||
|
} else {
|
||||||
|
returnValue = this.getFalseBooleanValue(database);
|
||||||
|
}
|
||||||
|
} else if (value instanceof DatabaseFunction) {
|
||||||
|
return value.toString();
|
||||||
|
} else if (value instanceof Boolean) {
|
||||||
|
if (((Boolean) value)) {
|
||||||
|
returnValue = this.getTrueBooleanValue(database);
|
||||||
|
} else {
|
||||||
|
returnValue = this.getFalseBooleanValue(database);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new UnexpectedLiquibaseException("Cannot convert type " + value.getClass() + " to a boolean value");
|
||||||
|
}
|
||||||
|
|
||||||
|
return returnValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean isNumericBoolean(Database database) {
|
||||||
|
if (database instanceof Firebird3Database) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (database instanceof DerbyDatabase) {
|
||||||
|
return !((DerbyDatabase) database).supportsBooleanDataType();
|
||||||
|
} else if (database instanceof DB2Database) {
|
||||||
|
return !((DB2Database) database).supportsBooleanDataType();
|
||||||
|
}
|
||||||
|
return (database instanceof Db2zDatabase)
|
||||||
|
|| (database instanceof FirebirdDatabase)
|
||||||
|
|| (database instanceof MSSQLDatabase)
|
||||||
|
|| (database instanceof MySQLDatabase)
|
||||||
|
|| (database instanceof OracleDatabase)
|
||||||
|
|| (database instanceof SQLiteDatabase)
|
||||||
|
|| (database instanceof SybaseASADatabase)
|
||||||
|
|| (database instanceof SybaseDatabase)
|
||||||
|
|| (database instanceof DmDatabase); // dhb52: DM Support
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The database-specific value to use for "false" "boolean" columns.
|
||||||
|
*/
|
||||||
|
public String getFalseBooleanValue(Database database) {
|
||||||
|
if (isNumericBoolean(database)) {
|
||||||
|
return "0";
|
||||||
|
}
|
||||||
|
if (database instanceof InformixDatabase) {
|
||||||
|
return "'f'";
|
||||||
|
}
|
||||||
|
return "FALSE";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The database-specific value to use for "true" "boolean" columns.
|
||||||
|
*/
|
||||||
|
public String getTrueBooleanValue(Database database) {
|
||||||
|
if (isNumericBoolean(database)) {
|
||||||
|
return "1";
|
||||||
|
}
|
||||||
|
if (database instanceof InformixDatabase) {
|
||||||
|
return "'t'";
|
||||||
|
}
|
||||||
|
return "TRUE";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LoadDataChange.LOAD_DATA_TYPE getLoadTypeName() {
|
||||||
|
return LoadDataChange.LOAD_DATA_TYPE.BOOLEAN;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1 @@
|
|||||||
|
防止IDEA将`.`和`/`混为一谈
|
@ -0,0 +1,21 @@
|
|||||||
|
liquibase.database.core.CockroachDatabase
|
||||||
|
liquibase.database.core.DB2Database
|
||||||
|
liquibase.database.core.Db2zDatabase
|
||||||
|
liquibase.database.core.DerbyDatabase
|
||||||
|
liquibase.database.core.Firebird3Database
|
||||||
|
liquibase.database.core.FirebirdDatabase
|
||||||
|
liquibase.database.core.H2Database
|
||||||
|
liquibase.database.core.HsqlDatabase
|
||||||
|
liquibase.database.core.InformixDatabase
|
||||||
|
liquibase.database.core.Ingres9Database
|
||||||
|
liquibase.database.core.MSSQLDatabase
|
||||||
|
liquibase.database.core.MariaDBDatabase
|
||||||
|
liquibase.database.core.MockDatabase
|
||||||
|
liquibase.database.core.MySQLDatabase
|
||||||
|
liquibase.database.core.OracleDatabase
|
||||||
|
liquibase.database.core.PostgresDatabase
|
||||||
|
liquibase.database.core.SQLiteDatabase
|
||||||
|
liquibase.database.core.SybaseASADatabase
|
||||||
|
liquibase.database.core.SybaseDatabase
|
||||||
|
liquibase.database.core.DmDatabase
|
||||||
|
liquibase.database.core.UnsupportedDatabase
|
@ -2292,7 +2292,7 @@ INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_i
|
|||||||
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2302, '支付通知查询', 'pay:notify:query', 3, 1, 2301, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-07-20 04:41:32', '', '2023-07-20 04:41:32', b'0');
|
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2302, '支付通知查询', 'pay:notify:query', 3, 1, 2301, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-07-20 04:41:32', '', '2023-07-20 04:41:32', b'0');
|
||||||
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2303, '拼团活动', '', 2, 3, 2030, 'combination', 'fa:group', '', '', 0, b'1', b'1', b'1', '1', '2023-08-12 17:19:54', '1', '2023-08-12 17:20:05', b'0');
|
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2303, '拼团活动', '', 2, 3, 2030, 'combination', 'fa:group', '', '', 0, b'1', b'1', b'1', '1', '2023-08-12 17:19:54', '1', '2023-08-12 17:20:05', b'0');
|
||||||
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2304, '拼团商品', '', 2, 1, 2303, 'acitivity', 'ep:apple', 'mall/promotion/combination/activity/index', 'PromotionCombinationActivity', 0, b'1', b'1', b'1', '1', '2023-08-12 17:22:03', '1', '2023-08-12 17:22:29', b'0');
|
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2304, '拼团商品', '', 2, 1, 2303, 'acitivity', 'ep:apple', 'mall/promotion/combination/activity/index', 'PromotionCombinationActivity', 0, b'1', b'1', b'1', '1', '2023-08-12 17:22:03', '1', '2023-08-12 17:22:29', b'0');
|
||||||
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2305, '拼团活动查询', 'promotion:combination-activity:query ', 3, 1, 2304, '', '', '', '', 0, b'1', b'1', b'1', '1', '2023-08-12 17:54:32', '1', '2023-08-12 17:54:32', b'0');
|
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2305, '拼团活动查询', 'promotion:combination-activity:query', 3, 1, 2304, '', '', '', '', 0, b'1', b'1', b'1', '1', '2023-08-12 17:54:32', '1', '2023-08-12 17:54:32', b'0');
|
||||||
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2306, '拼团活动创建', 'promotion:combination-activity:create', 3, 2, 2304, '', '', '', '', 0, b'1', b'1', b'1', '1', '2023-08-12 17:54:49', '1', '2023-08-12 17:54:49', b'0');
|
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2306, '拼团活动创建', 'promotion:combination-activity:create', 3, 2, 2304, '', '', '', '', 0, b'1', b'1', b'1', '1', '2023-08-12 17:54:49', '1', '2023-08-12 17:54:49', b'0');
|
||||||
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2307, '拼团活动更新', 'promotion:combination-activity:update', 3, 3, 2304, '', '', '', '', 0, b'1', b'1', b'1', '1', '2023-08-12 17:55:04', '1', '2023-08-12 17:55:04', b'0');
|
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2307, '拼团活动更新', 'promotion:combination-activity:update', 3, 3, 2304, '', '', '', '', 0, b'1', b'1', b'1', '1', '2023-08-12 17:55:04', '1', '2023-08-12 17:55:04', b'0');
|
||||||
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2308, '拼团活动删除', 'promotion:combination-activity:delete', 3, 4, 2304, '', '', '', '', 0, b'1', b'1', b'1', '1', '2023-08-12 17:55:23', '1', '2023-08-12 17:55:23', b'0');
|
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2308, '拼团活动删除', 'promotion:combination-activity:delete', 3, 4, 2304, '', '', '', '', 0, b'1', b'1', b'1', '1', '2023-08-12 17:55:23', '1', '2023-08-12 17:55:23', b'0');
|
||||||
|
@ -0,0 +1,28 @@
|
|||||||
|
package cn.iocoder.yudao.framework.common.validation;
|
||||||
|
|
||||||
|
import javax.validation.Constraint;
|
||||||
|
import javax.validation.Payload;
|
||||||
|
import java.lang.annotation.*;
|
||||||
|
|
||||||
|
@Target({
|
||||||
|
ElementType.METHOD,
|
||||||
|
ElementType.FIELD,
|
||||||
|
ElementType.ANNOTATION_TYPE,
|
||||||
|
ElementType.CONSTRUCTOR,
|
||||||
|
ElementType.PARAMETER,
|
||||||
|
ElementType.TYPE_USE
|
||||||
|
})
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Documented
|
||||||
|
@Constraint(
|
||||||
|
validatedBy = TelephoneValidator.class
|
||||||
|
)
|
||||||
|
public @interface Telephone {
|
||||||
|
|
||||||
|
String message() default "电话格式不正确";
|
||||||
|
|
||||||
|
Class<?>[] groups() default {};
|
||||||
|
|
||||||
|
Class<? extends Payload>[] payload() default {};
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
package cn.iocoder.yudao.framework.common.validation;
|
||||||
|
|
||||||
|
import cn.hutool.core.text.CharSequenceUtil;
|
||||||
|
import cn.hutool.core.util.PhoneUtil;
|
||||||
|
|
||||||
|
import javax.validation.ConstraintValidator;
|
||||||
|
import javax.validation.ConstraintValidatorContext;
|
||||||
|
|
||||||
|
public class TelephoneValidator implements ConstraintValidator<Telephone, String> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initialize(Telephone annotation) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isValid(String value, ConstraintValidatorContext context) {
|
||||||
|
// 如果手机号为空,默认不校验,即校验通过
|
||||||
|
if (CharSequenceUtil.isEmpty(value)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// 校验手机
|
||||||
|
return PhoneUtil.isTel(value) || PhoneUtil.isPhone(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,55 +0,0 @@
|
|||||||
package cn.iocoder.yudao.framework.sms.core.client.impl.aliyun;
|
|
||||||
|
|
||||||
import cn.iocoder.yudao.framework.common.core.KeyValue;
|
|
||||||
import cn.iocoder.yudao.framework.sms.core.client.SmsCommonResult;
|
|
||||||
import cn.iocoder.yudao.framework.sms.core.client.dto.SmsSendRespDTO;
|
|
||||||
import cn.iocoder.yudao.framework.sms.core.client.dto.SmsTemplateRespDTO;
|
|
||||||
import cn.iocoder.yudao.framework.sms.core.client.impl.aliyun.AliyunSmsClient;
|
|
||||||
import cn.iocoder.yudao.framework.sms.core.enums.SmsChannelEnum;
|
|
||||||
import cn.iocoder.yudao.framework.sms.core.property.SmsChannelProperties;
|
|
||||||
import org.junit.jupiter.api.BeforeAll;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@link AliyunSmsClient} 的集成测试
|
|
||||||
*/
|
|
||||||
public class AliyunSmsClientIntegrationTest {
|
|
||||||
|
|
||||||
private static AliyunSmsClient smsClient;
|
|
||||||
|
|
||||||
@BeforeAll
|
|
||||||
public static void before() {
|
|
||||||
// 创建配置类
|
|
||||||
SmsChannelProperties properties = new SmsChannelProperties();
|
|
||||||
properties.setId(1L);
|
|
||||||
properties.setSignature("Ballcat");
|
|
||||||
properties.setCode(SmsChannelEnum.ALIYUN.getCode());
|
|
||||||
properties.setApiKey(System.getenv("ALIYUN_ACCESS_KEY"));
|
|
||||||
properties.setApiSecret(System.getenv("ALIYUN_SECRET_KEY"));
|
|
||||||
// 创建客户端
|
|
||||||
smsClient = new AliyunSmsClient(properties);
|
|
||||||
smsClient.init();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testSendSms() {
|
|
||||||
List<KeyValue<String, Object>> templateParams = new ArrayList<>();
|
|
||||||
templateParams.add(new KeyValue<>("code", "1024"));
|
|
||||||
// templateParams.put("operation", "嘿嘿");
|
|
||||||
// SmsResult result = smsClient.send(1L, "15601691399", "4372216", templateParams);
|
|
||||||
SmsCommonResult<SmsSendRespDTO> result = smsClient.sendSms(1L, "15601691399",
|
|
||||||
"SMS_207945135", templateParams);
|
|
||||||
System.out.println(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testGetSmsTemplate() {
|
|
||||||
String apiTemplateId = "SMS_2079451351";
|
|
||||||
SmsCommonResult<SmsTemplateRespDTO> result = smsClient.getSmsTemplate(apiTemplateId);
|
|
||||||
System.out.println(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,46 +0,0 @@
|
|||||||
package cn.iocoder.yudao.framework.sms.core.client.impl.debug;
|
|
||||||
|
|
||||||
import cn.iocoder.yudao.framework.common.core.KeyValue;
|
|
||||||
import cn.iocoder.yudao.framework.sms.core.client.SmsCommonResult;
|
|
||||||
import cn.iocoder.yudao.framework.sms.core.client.dto.SmsSendRespDTO;
|
|
||||||
import cn.iocoder.yudao.framework.sms.core.client.impl.debug.DebugDingTalkSmsClient;
|
|
||||||
import cn.iocoder.yudao.framework.sms.core.enums.SmsChannelEnum;
|
|
||||||
import cn.iocoder.yudao.framework.sms.core.property.SmsChannelProperties;
|
|
||||||
import org.junit.jupiter.api.BeforeAll;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@link DebugDingTalkSmsClient} 的集成测试
|
|
||||||
*/
|
|
||||||
public class DebugDingTalkSmsClientIntegrationTest {
|
|
||||||
|
|
||||||
private static DebugDingTalkSmsClient smsClient;
|
|
||||||
|
|
||||||
@BeforeAll
|
|
||||||
public static void init() {
|
|
||||||
// 创建配置类
|
|
||||||
SmsChannelProperties properties = new SmsChannelProperties();
|
|
||||||
properties.setId(1L);
|
|
||||||
properties.setSignature("芋道");
|
|
||||||
properties.setCode(SmsChannelEnum.DEBUG_DING_TALK.getCode());
|
|
||||||
properties.setApiKey("696b5d8ead48071237e4aa5861ff08dbadb2b4ded1c688a7b7c9afc615579859");
|
|
||||||
properties.setApiSecret("SEC5c4e5ff888bc8a9923ae47f59e7ccd30af1f14d93c55b4e2c9cb094e35aeed67");
|
|
||||||
// 创建客户端
|
|
||||||
smsClient = new DebugDingTalkSmsClient(properties);
|
|
||||||
smsClient.init();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testSendSms() {
|
|
||||||
List<KeyValue<String, Object>> templateParams = new ArrayList<>();
|
|
||||||
templateParams.add(new KeyValue<>("code", "1024"));
|
|
||||||
templateParams.add(new KeyValue<>("operation", "嘿嘿"));
|
|
||||||
// SmsResult result = smsClient.send(1L, "15601691399", "4372216", templateParams);
|
|
||||||
SmsCommonResult<SmsSendRespDTO> result = smsClient.sendSms(1L, "15601691399", "4383920", templateParams);
|
|
||||||
System.out.println(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,12 +1,12 @@
|
|||||||
package cn.iocoder.yudao.module.bpm.dal.dataobject.oa;
|
package cn.iocoder.yudao.module.bpm.dal.dataobject.oa;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||||
import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum;
|
import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
import lombok.*;
|
import lombok.*;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.util.*;
|
|
||||||
import com.baomidou.mybatisplus.annotation.*;
|
|
||||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* OA 请假申请 DO
|
* OA 请假申请 DO
|
||||||
@ -39,7 +39,6 @@ public class BpmOALeaveDO extends BaseDO {
|
|||||||
/**
|
/**
|
||||||
* 请假类型
|
* 请假类型
|
||||||
*/
|
*/
|
||||||
@TableField("`type`")
|
|
||||||
private String type;
|
private String type;
|
||||||
/**
|
/**
|
||||||
* 原因
|
* 原因
|
||||||
|
Loading…
Reference in New Issue
Block a user