CCM NG: Shortcuts module now deploys successfully
git-svn-id: https://svn.libreccm.org/ccm/ccm_ng@4147 8810af33-2d31-482b-a856-94f89814c4dfpull/2/head
parent
572db42a15
commit
e4f8ca3b97
|
|
@ -36,6 +36,9 @@
|
||||||
<Logger name="org.libreccm.core.AbstractEntityRepository"
|
<Logger name="org.libreccm.core.AbstractEntityRepository"
|
||||||
level="debug">
|
level="debug">
|
||||||
</Logger>
|
</Logger>
|
||||||
|
<Logger name="org.libreccm.modules.CcmIntegrator"
|
||||||
|
level="debug">
|
||||||
|
</Logger>
|
||||||
<Logger name="org.libreccm.security.OneTimeAuthTokenCleaner"
|
<Logger name="org.libreccm.security.OneTimeAuthTokenCleaner"
|
||||||
level="debug">
|
level="debug">
|
||||||
</Logger>
|
</Logger>
|
||||||
|
|
|
||||||
|
|
@ -54,14 +54,14 @@ import javax.sql.DataSource;
|
||||||
public class CcmIntegrator implements Integrator {
|
public class CcmIntegrator implements Integrator {
|
||||||
|
|
||||||
private static final Logger LOGGER = LogManager.getLogger(
|
private static final Logger LOGGER = LogManager.getLogger(
|
||||||
CcmIntegrator.class);
|
CcmIntegrator.class);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Name of the property which is used to retrieve the data source in use
|
* Name of the property which is used to retrieve the data source in use
|
||||||
* from Hibernate.
|
* from Hibernate.
|
||||||
*/
|
*/
|
||||||
private static final String DATASOURCE_PROPERTY
|
private static final String DATASOURCE_PROPERTY
|
||||||
= "hibernate.connection.datasource";
|
= "hibernate.connection.datasource";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Service loader containing all modules. Initialised by the
|
* Service loader containing all modules. Initialised by the
|
||||||
|
|
@ -94,14 +94,23 @@ public class CcmIntegrator implements Integrator {
|
||||||
try {
|
try {
|
||||||
//Create dependency tree for the modules
|
//Create dependency tree for the modules
|
||||||
final DependencyTreeManager treeManager
|
final DependencyTreeManager treeManager
|
||||||
= new DependencyTreeManager();
|
= new DependencyTreeManager();
|
||||||
final List<TreeNode> tree = treeManager.generateTree(modules);
|
final List<TreeNode> tree = treeManager.generateTree(modules);
|
||||||
final List<TreeNode> orderedNodes = treeManager.orderModules(tree);
|
final List<TreeNode> orderedNodes = treeManager.orderModules(tree);
|
||||||
|
|
||||||
|
if (LOGGER.isDebugEnabled()) {
|
||||||
|
LOGGER.debug("Ordered list of modules:");
|
||||||
|
orderedNodes.forEach(m -> {
|
||||||
|
LOGGER.debug("\t{}-{}",
|
||||||
|
m.getModuleInfo().getModuleName(),
|
||||||
|
m.getModuleInfo().getModuleVersion());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// //Get DataSource and Connection from the sessionFactory of
|
// //Get DataSource and Connection from the sessionFactory of
|
||||||
// //Hibernate.
|
// //Hibernate.
|
||||||
final DataSource dataSource = (DataSource) sessionFactory.
|
final DataSource dataSource = (DataSource) sessionFactory.
|
||||||
getProperties().get(DATASOURCE_PROPERTY);
|
getProperties().get(DATASOURCE_PROPERTY);
|
||||||
if (dataSource == null) {
|
if (dataSource == null) {
|
||||||
throw new IllegalStateException("No data source available.");
|
throw new IllegalStateException("No data source available.");
|
||||||
}
|
}
|
||||||
|
|
@ -112,13 +121,16 @@ public class CcmIntegrator implements Integrator {
|
||||||
final Flyway flyway = new Flyway();
|
final Flyway flyway = new Flyway();
|
||||||
flyway.setDataSource(dataSource);
|
flyway.setDataSource(dataSource);
|
||||||
final StringBuffer buffer = new StringBuffer(
|
final StringBuffer buffer = new StringBuffer(
|
||||||
"db/migrations/org/libreccm/base");
|
"db/migrations/org/libreccm/base");
|
||||||
appendDbLocation(buffer, connection);
|
appendDbLocation(buffer, connection);
|
||||||
flyway.setLocations(buffer.toString());
|
flyway.setLocations(buffer.toString());
|
||||||
flyway.migrate();
|
flyway.migrate();
|
||||||
|
|
||||||
//Migrate the modules
|
//Migrate the modules
|
||||||
for (final TreeNode node : orderedNodes) {
|
for (final TreeNode node : orderedNodes) {
|
||||||
|
LOGGER.debug("Applying migrations for module {}-{}",
|
||||||
|
node.getModuleInfo().getModuleName(),
|
||||||
|
node.getModuleInfo().getModuleVersion());
|
||||||
migrateModule(node.getModule().getClass(), dataSource);
|
migrateModule(node.getModule().getClass(), dataSource);
|
||||||
|
|
||||||
// for (Class<?> entity : node.getModuleInfo().getModuleEntities()) {
|
// for (Class<?> entity : node.getModuleInfo().getModuleEntities()) {
|
||||||
|
|
@ -187,16 +199,15 @@ public class CcmIntegrator implements Integrator {
|
||||||
* If the database is not supported an {@link IntegrationException} will be
|
* If the database is not supported an {@link IntegrationException} will be
|
||||||
* thrown.
|
* thrown.
|
||||||
*
|
*
|
||||||
* @param buffer Buffer for the location string.
|
* @param buffer Buffer for the location string.
|
||||||
* @param connection The JDBC connection object.
|
* @param connection The JDBC connection object.
|
||||||
*
|
*
|
||||||
* @throws SQLException If an error occurs while accessing the
|
* @throws SQLException If an error occurs while accessing the database.
|
||||||
* database.
|
|
||||||
* @throws IntegrationException If the database is not supported yet.
|
* @throws IntegrationException If the database is not supported yet.
|
||||||
*/
|
*/
|
||||||
private void appendDbLocation(final StringBuffer buffer,
|
private void appendDbLocation(final StringBuffer buffer,
|
||||||
final Connection connection)
|
final Connection connection)
|
||||||
throws SQLException {
|
throws SQLException {
|
||||||
|
|
||||||
switch (connection.getMetaData().getDatabaseProductName()) {
|
switch (connection.getMetaData().getDatabaseProductName()) {
|
||||||
case "H2":
|
case "H2":
|
||||||
|
|
@ -207,9 +218,9 @@ public class CcmIntegrator implements Integrator {
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new IntegrationException(String.format(
|
throw new IntegrationException(String.format(
|
||||||
"Integration failed. Database \"%s\" is not supported yet.",
|
"Integration failed. Database \"%s\" is not supported yet.",
|
||||||
connection.getMetaData().
|
connection.getMetaData().
|
||||||
getDatabaseProductName()));
|
getDatabaseProductName()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -225,10 +236,10 @@ public class CcmIntegrator implements Integrator {
|
||||||
*/
|
*/
|
||||||
private String getLocation(final ModuleInfo moduleInfo,
|
private String getLocation(final ModuleInfo moduleInfo,
|
||||||
final Connection connection)
|
final Connection connection)
|
||||||
throws SQLException {
|
throws SQLException {
|
||||||
|
|
||||||
final StringBuffer buffer = new StringBuffer(
|
final StringBuffer buffer = new StringBuffer(
|
||||||
"classpath:/db/migrations/");
|
"classpath:/db/migrations/");
|
||||||
buffer.append(moduleInfo.getModuleDataPackage());
|
buffer.append(moduleInfo.getModuleDataPackage());
|
||||||
appendDbLocation(buffer, connection);
|
appendDbLocation(buffer, connection);
|
||||||
|
|
||||||
|
|
@ -238,7 +249,7 @@ public class CcmIntegrator implements Integrator {
|
||||||
/**
|
/**
|
||||||
* Helper method for executing the migrations for a module.
|
* Helper method for executing the migrations for a module.
|
||||||
*
|
*
|
||||||
* @param module The module for which the migrations are executed.
|
* @param module The module for which the migrations are executed.
|
||||||
* @param dataSource The JDBC data source for connecting to the database.
|
* @param dataSource The JDBC data source for connecting to the database.
|
||||||
*
|
*
|
||||||
* @throws SQLException If an error occurs while applying the migrations.
|
* @throws SQLException If an error occurs while applying the migrations.
|
||||||
|
|
@ -259,8 +270,8 @@ public class CcmIntegrator implements Integrator {
|
||||||
//different RDBMS handle case different.
|
//different RDBMS handle case different.
|
||||||
if ("H2".equals(connection.getMetaData().getDatabaseProductName())) {
|
if ("H2".equals(connection.getMetaData().getDatabaseProductName())) {
|
||||||
flyway
|
flyway
|
||||||
.setSchemas(getSchemaName(moduleInfo).toUpperCase(
|
.setSchemas(getSchemaName(moduleInfo).toUpperCase(
|
||||||
Locale.ROOT));
|
Locale.ROOT));
|
||||||
} else {
|
} else {
|
||||||
flyway.setSchemas(getSchemaName(moduleInfo));
|
flyway.setSchemas(getSchemaName(moduleInfo));
|
||||||
}
|
}
|
||||||
|
|
@ -292,11 +303,11 @@ public class CcmIntegrator implements Integrator {
|
||||||
if (newModule) {
|
if (newModule) {
|
||||||
try (Statement statement = connection.createStatement()) {
|
try (Statement statement = connection.createStatement()) {
|
||||||
statement.execute(String.format(
|
statement.execute(String.format(
|
||||||
"INSERT INTO ccm_core.installed_modules "
|
"INSERT INTO ccm_core.installed_modules "
|
||||||
+ "(module_id, module_class_name, status) "
|
+ "(module_id, module_class_name, status) "
|
||||||
+ "VALUES (%d, '%s', 'NEW')",
|
+ "VALUES (%d, '%s', 'NEW')",
|
||||||
module.getName().hashCode(),
|
module.getName().hashCode(),
|
||||||
module.getName()));
|
module.getName()));
|
||||||
} catch (SQLException ex) {
|
} catch (SQLException ex) {
|
||||||
throw new IntegrationException("Failed to integrate.", ex);
|
throw new IntegrationException("Failed to integrate.", ex);
|
||||||
}
|
}
|
||||||
|
|
@ -322,7 +333,7 @@ public class CcmIntegrator implements Integrator {
|
||||||
|
|
||||||
//Get JDBC connection
|
//Get JDBC connection
|
||||||
final DataSource dataSource = (DataSource) sessionFactory
|
final DataSource dataSource = (DataSource) sessionFactory
|
||||||
.getProperties().get(DATASOURCE_PROPERTY);
|
.getProperties().get(DATASOURCE_PROPERTY);
|
||||||
connection = dataSource.getConnection();
|
connection = dataSource.getConnection();
|
||||||
System.out.println("checking modules...");
|
System.out.println("checking modules...");
|
||||||
LOGGER.info("Checking modules...");
|
LOGGER.info("Checking modules...");
|
||||||
|
|
@ -333,10 +344,10 @@ public class CcmIntegrator implements Integrator {
|
||||||
try (Statement query = connection.createStatement();
|
try (Statement query = connection.createStatement();
|
||||||
//Check status of each module
|
//Check status of each module
|
||||||
ResultSet result = query.executeQuery(
|
ResultSet result = query.executeQuery(
|
||||||
String.format("SELECT module_class_name, status "
|
String.format("SELECT module_class_name, status "
|
||||||
+ "FROM ccm_core.installed_modules "
|
+ "FROM ccm_core.installed_modules "
|
||||||
+ "WHERE module_class_name = '%s'",
|
+ "WHERE module_class_name = '%s'",
|
||||||
module.getClass().getName()))) {
|
module.getClass().getName()))) {
|
||||||
|
|
||||||
System.out.printf("Checking status of module %s...%n",
|
System.out.printf("Checking status of module %s...%n",
|
||||||
module.getClass().getName());
|
module.getClass().getName());
|
||||||
|
|
@ -344,7 +355,7 @@ public class CcmIntegrator implements Integrator {
|
||||||
//If there modules marked for uninstall remove the schema
|
//If there modules marked for uninstall remove the schema
|
||||||
//of the module from the database.
|
//of the module from the database.
|
||||||
if (result.next() && ModuleStatus.UNINSTALL.toString()
|
if (result.next() && ModuleStatus.UNINSTALL.toString()
|
||||||
.equals(result.getString("status"))) {
|
.equals(result.getString("status"))) {
|
||||||
uninstallModule(connection,
|
uninstallModule(connection,
|
||||||
dataSource,
|
dataSource,
|
||||||
module,
|
module,
|
||||||
|
|
@ -378,7 +389,7 @@ public class CcmIntegrator implements Integrator {
|
||||||
final DataSource dataSource,
|
final DataSource dataSource,
|
||||||
final CcmModule module,
|
final CcmModule module,
|
||||||
final ModuleInfo moduleInfo)
|
final ModuleInfo moduleInfo)
|
||||||
throws SQLException {
|
throws SQLException {
|
||||||
LOGGER.info("Removing schema for module %s...",
|
LOGGER.info("Removing schema for module %s...",
|
||||||
module.getClass().getName());
|
module.getClass().getName());
|
||||||
final Flyway flyway = new Flyway();
|
final Flyway flyway = new Flyway();
|
||||||
|
|
@ -391,16 +402,16 @@ public class CcmIntegrator implements Integrator {
|
||||||
|
|
||||||
//Delete the module from the installed modules table.
|
//Delete the module from the installed modules table.
|
||||||
try (final Statement statement = connection
|
try (final Statement statement = connection
|
||||||
.createStatement()) {
|
.createStatement()) {
|
||||||
statement.addBatch(String.format(
|
statement.addBatch(String.format(
|
||||||
"DELETE FROM ccm_core.installed_modules "
|
"DELETE FROM ccm_core.installed_modules "
|
||||||
+ "WHERE module_class_name = '%s'",
|
+ "WHERE module_class_name = '%s'",
|
||||||
module.getClass().getName()));
|
module.getClass().getName()));
|
||||||
statement.executeBatch();
|
statement.executeBatch();
|
||||||
LOGGER.info("Done.");
|
LOGGER.info("Done.");
|
||||||
} catch (SQLException ex) {
|
} catch (SQLException ex) {
|
||||||
throw new IntegrationException(
|
throw new IntegrationException(
|
||||||
"Failed to desintegrate", ex);
|
"Failed to desintegrate", ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@
|
||||||
package org.libreccm.modules;
|
package org.libreccm.modules;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,50 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2016 LibreCCM Foundation.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||||
|
* MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
package org.libreccm.security;
|
||||||
|
|
||||||
|
import javax.persistence.EntityManager;
|
||||||
|
import org.libreccm.shortcuts.ShortcutsConstants;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
||||||
|
*/
|
||||||
|
public class ShortcutsRolesSetup {
|
||||||
|
|
||||||
|
private final EntityManager entityManager;
|
||||||
|
|
||||||
|
public ShortcutsRolesSetup(final EntityManager entityManager) {
|
||||||
|
this.entityManager = entityManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setupShortcutsRoles() {
|
||||||
|
final Role shortcutsManager = new Role();
|
||||||
|
shortcutsManager.setName("shortcuts-manager");
|
||||||
|
entityManager.persist(shortcutsManager);
|
||||||
|
|
||||||
|
final Permission permission = new Permission();
|
||||||
|
permission.setGrantee(shortcutsManager);
|
||||||
|
permission.setGrantedPrivilege(
|
||||||
|
ShortcutsConstants.SHORTSCUT_MANAGE_PRIVILEGE);
|
||||||
|
permission.setObject(null);
|
||||||
|
|
||||||
|
entityManager.persist(permission);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -18,10 +18,12 @@
|
||||||
*/
|
*/
|
||||||
package org.libreccm.shortcuts;
|
package org.libreccm.shortcuts;
|
||||||
|
|
||||||
|
import org.libreccm.core.CcmCore;
|
||||||
import org.libreccm.modules.CcmModule;
|
import org.libreccm.modules.CcmModule;
|
||||||
import org.libreccm.modules.InitEvent;
|
import org.libreccm.modules.InitEvent;
|
||||||
import org.libreccm.modules.InstallEvent;
|
import org.libreccm.modules.InstallEvent;
|
||||||
import org.libreccm.modules.Module;
|
import org.libreccm.modules.Module;
|
||||||
|
import org.libreccm.modules.RequiredModule;
|
||||||
import org.libreccm.modules.ShutdownEvent;
|
import org.libreccm.modules.ShutdownEvent;
|
||||||
import org.libreccm.modules.UnInstallEvent;
|
import org.libreccm.modules.UnInstallEvent;
|
||||||
import org.libreccm.web.ApplicationType;
|
import org.libreccm.web.ApplicationType;
|
||||||
|
|
@ -30,11 +32,15 @@ import org.libreccm.web.ApplicationType;
|
||||||
*
|
*
|
||||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
||||||
*/
|
*/
|
||||||
@Module(applicationTypes = {
|
@Module(
|
||||||
@ApplicationType(name = ShortcutsConstants.SHORTCUTS_APP_TYPE,
|
requiredModules = {
|
||||||
descBundle = "org.libreccm.shortcuts.ShortcutsResources",
|
@RequiredModule(module = CcmCore.class)
|
||||||
singleton = true,
|
},
|
||||||
creator = ShortcutsApplicationCreator.class)}
|
applicationTypes = {
|
||||||
|
@ApplicationType(name = ShortcutsConstants.SHORTCUTS_APP_TYPE,
|
||||||
|
descBundle = "org.libreccm.shortcuts.ShortcutsResources",
|
||||||
|
singleton = true,
|
||||||
|
creator = ShortcutsApplicationCreator.class)}
|
||||||
)
|
)
|
||||||
public class Shortcuts implements CcmModule {
|
public class Shortcuts implements CcmModule {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -35,4 +35,6 @@ public final class ShortcutsConstants {
|
||||||
*/
|
*/
|
||||||
public static final String SHORTCUTS_PRIMARY_URL = "/shortcuts/";
|
public static final String SHORTCUTS_PRIMARY_URL = "/shortcuts/";
|
||||||
|
|
||||||
|
public static final String SHORTSCUT_MANAGE_PRIVILEGE = "manage_shortcuts";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,16 +18,12 @@
|
||||||
*/
|
*/
|
||||||
package org.libreccm.shortcuts;
|
package org.libreccm.shortcuts;
|
||||||
|
|
||||||
import org.libreccm.cdi.utils.CdiUtil;
|
|
||||||
import org.libreccm.modules.InstallEvent;
|
import org.libreccm.modules.InstallEvent;
|
||||||
import org.libreccm.security.PermissionManager;
|
|
||||||
import org.libreccm.security.Role;
|
|
||||||
import org.libreccm.security.RoleManager;
|
|
||||||
import org.libreccm.security.RoleRepository;
|
|
||||||
import org.libreccm.web.AbstractCcmApplicationSetup;
|
import org.libreccm.web.AbstractCcmApplicationSetup;
|
||||||
import org.libreccm.web.CcmApplication;
|
import org.libreccm.web.CcmApplication;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import org.libreccm.security.ShortcutsRolesSetup;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
|
@ -47,16 +43,17 @@ public class ShortcutsSetup extends AbstractCcmApplicationSetup {
|
||||||
shortcuts.setPrimaryUrl(ShortcutsConstants.SHORTCUTS_PRIMARY_URL);
|
shortcuts.setPrimaryUrl(ShortcutsConstants.SHORTCUTS_PRIMARY_URL);
|
||||||
getEntityManager().persist(shortcuts);
|
getEntityManager().persist(shortcuts);
|
||||||
|
|
||||||
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
|
final ShortcutsRolesSetup rolesSetup = new ShortcutsRolesSetup(
|
||||||
final RoleRepository roleRepository = cdiUtil.findBean(
|
getEntityManager());
|
||||||
RoleRepository.class);
|
rolesSetup.setupShortcutsRoles();
|
||||||
final Role shortcutsManager = new Role();
|
|
||||||
shortcutsManager.setName("shortcuts-manager");
|
|
||||||
roleRepository.save(shortcutsManager);
|
|
||||||
|
|
||||||
final PermissionManager permissionManager = cdiUtil.findBean(
|
// final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
|
||||||
PermissionManager.class);
|
// final RoleRepository roleRepository = cdiUtil.findBean(
|
||||||
permissionManager.grantPrivilege("manage_shortcuts", shortcutsManager);
|
// RoleRepository.class);
|
||||||
|
// roleRepository.save(shortcutsManager);
|
||||||
|
// final PermissionManager permissionManager = cdiUtil.findBean(
|
||||||
|
// PermissionManager.class);
|
||||||
|
// permissionManager.grantPrivilege("manage_shortcuts", shortcutsManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,9 +0,0 @@
|
||||||
create table SHORTCUTS (
|
|
||||||
shortcut_id bigint generated by default as identity,
|
|
||||||
redirect varchar(1024),
|
|
||||||
url_key varchar(1024),
|
|
||||||
primary key (shortcut_id)
|
|
||||||
);
|
|
||||||
|
|
||||||
alter table CCM_SHORTCUTS.SHORTCUTS
|
|
||||||
add constraint UK_4otuwtog6qqdbg4e6p8xdpw8h unique (URL_KEY);
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
|
|
||||||
create table SHORTCUTS (
|
|
||||||
shortcut_id number(19,0) not null,
|
|
||||||
redirect varchar2(1024 char),
|
|
||||||
url_key varchar2(1024 char),
|
|
||||||
primary key (shortcut_id)
|
|
||||||
);
|
|
||||||
|
|
||||||
create table SHORTCUTS_APP (
|
|
||||||
object_id number(19,0) not null,
|
|
||||||
primary key (object_id)
|
|
||||||
);
|
|
||||||
|
|
@ -1,9 +0,0 @@
|
||||||
create table SHORTCUTS (
|
|
||||||
shortcut_id int8 not null,
|
|
||||||
redirect varchar(1024),
|
|
||||||
url_key varchar(1024),
|
|
||||||
primary key (shortcut_id)
|
|
||||||
);
|
|
||||||
|
|
||||||
alter table CCM_SHORTCUTS.SHORTCUTS
|
|
||||||
add constraint UK_4otuwtog6qqdbg4e6p8xdpw8h unique (URL_KEY);
|
|
||||||
Loading…
Reference in New Issue