Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id A1A7F200B7C for ; Thu, 8 Sep 2016 10:22:11 +0200 (CEST) Received: by cust-asf.ponee.io (Postfix) id A0167160ABD; Thu, 8 Sep 2016 08:22:11 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id 460EA160AA5 for ; Thu, 8 Sep 2016 10:22:09 +0200 (CEST) Received: (qmail 30173 invoked by uid 500); 8 Sep 2016 08:22:08 -0000 Mailing-List: contact commits-help@eagle.incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@eagle.incubator.apache.org Delivered-To: mailing list commits@eagle.incubator.apache.org Received: (qmail 30164 invoked by uid 99); 8 Sep 2016 08:22:08 -0000 Received: from pnap-us-west-generic-nat.apache.org (HELO spamd1-us-west.apache.org) (209.188.14.142) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 08 Sep 2016 08:22:08 +0000 Received: from localhost (localhost [127.0.0.1]) by spamd1-us-west.apache.org (ASF Mail Server at spamd1-us-west.apache.org) with ESMTP id E77CAC1053 for ; Thu, 8 Sep 2016 08:22:07 +0000 (UTC) X-Virus-Scanned: Debian amavisd-new at spamd1-us-west.apache.org X-Spam-Flag: NO X-Spam-Score: -4.344 X-Spam-Level: X-Spam-Status: No, score=-4.344 tagged_above=-999 required=6.31 tests=[KAM_ASCII_DIVIDERS=0.8, KAM_LAZY_DOMAIN_SECURITY=1, RCVD_IN_DNSWL_HI=-5, RCVD_IN_MSPIKE_H3=-0.01, RCVD_IN_MSPIKE_WL=-0.01, RP_MATCHES_RCVD=-1.124] autolearn=disabled Received: from mx2-lw-eu.apache.org ([10.40.0.8]) by localhost (spamd1-us-west.apache.org [10.40.0.7]) (amavisd-new, port 10024) with ESMTP id 2qV9QHcKsbTP for ; Thu, 8 Sep 2016 08:22:03 +0000 (UTC) Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by mx2-lw-eu.apache.org (ASF Mail Server at mx2-lw-eu.apache.org) with SMTP id E76FC5FACF for ; Thu, 8 Sep 2016 08:22:00 +0000 (UTC) Received: (qmail 28219 invoked by uid 99); 8 Sep 2016 08:22:00 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 08 Sep 2016 08:22:00 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 0C028DFE80; Thu, 8 Sep 2016 08:22:00 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: hao@apache.org To: commits@eagle.incubator.apache.org Message-Id: <6a8ae6133232487dae40fcaa7b2773ab@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: incubator-eagle git commit: [EAGLE-516] Implement application entity service by jdbc Date: Thu, 8 Sep 2016 08:22:00 +0000 (UTC) archived-at: Thu, 08 Sep 2016 08:22:11 -0000 Repository: incubator-eagle Updated Branches: refs/heads/master f45ec4370 -> 3db5cdbac [EAGLE-516] Implement application entity service by jdbc - Implement application entity service by jdbc - Implement site entity service by jdbc - Add query/queryWithCond/update method in JDBCMetadataQueryService https://issues.apache.org/jira/browse/EAGLE-516 Author: r7raul1984 Closes #418 from r7raul1984/EAGLE-516. (cherry picked from commit 8270bd2e5a2484138bfa2e293a4e77ccb804e91b) Signed-off-by: Hao Chen Project: http://git-wip-us.apache.org/repos/asf/incubator-eagle/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-eagle/commit/3db5cdba Tree: http://git-wip-us.apache.org/repos/asf/incubator-eagle/tree/3db5cdba Diff: http://git-wip-us.apache.org/repos/asf/incubator-eagle/diff/3db5cdba Branch: refs/heads/master Commit: 3db5cdbacd8a6976e853c1128e8476972f378403 Parents: f45ec43 Author: r7raul1984 Authored: Thu Sep 8 16:21:02 2016 +0800 Committer: Hao Chen Committed: Thu Sep 8 16:21:46 2016 +0800 ---------------------------------------------------------------------- .../eagle/metadata/model/ApplicationEntity.java | 40 +++- .../apache/eagle/metadata/model/SiteEntity.java | 12 +- .../JDBCMetadataMetadataStoreServiceImpl.java | 183 ++++++++++++---- .../store/jdbc/JDBCMetadataQueryService.java | 29 ++- .../metadata/store/jdbc/JDBCMetadataStore.java | 10 +- .../ApplicationEntityServiceJDBCImpl.java | 162 ++++++++++++++ .../jdbc/service/SiteEntityServiceJDBCImpl.java | 165 ++++++++++++++ .../orm/ApplicationEntityToRelation.java | 69 ++++++ .../orm/RelationToApplicationEntity.java | 59 +++++ .../jdbc/service/orm/RelationToSiteEntity.java | 37 ++++ .../jdbc/service/orm/SiteEntityToRelation.java | 58 +++++ .../ApplicationEntityServiceJDBCImplTest.java | 153 +++++++++++++ .../store/jdbc/JDBCDataSourceProviderTest.java | 2 +- .../jdbc/SiteEntityServiceJDBCImplTest.java | 216 +++++++++++++++++++ .../src/test/resources/application.conf | 2 +- .../src/test/resources/init.sql | 39 ++++ 16 files changed, 1173 insertions(+), 63 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/3db5cdba/eagle-core/eagle-metadata/eagle-metadata-base/src/main/java/org/apache/eagle/metadata/model/ApplicationEntity.java ---------------------------------------------------------------------- diff --git a/eagle-core/eagle-metadata/eagle-metadata-base/src/main/java/org/apache/eagle/metadata/model/ApplicationEntity.java b/eagle-core/eagle-metadata/eagle-metadata-base/src/main/java/org/apache/eagle/metadata/model/ApplicationEntity.java index 5f3adb1..7943491 100644 --- a/eagle-core/eagle-metadata/eagle-metadata-base/src/main/java/org/apache/eagle/metadata/model/ApplicationEntity.java +++ b/eagle-core/eagle-metadata/eagle-metadata-base/src/main/java/org/apache/eagle/metadata/model/ApplicationEntity.java @@ -34,13 +34,36 @@ public class ApplicationEntity extends PersistenceEntity { private ApplicationDesc descriptor; - private Map configuration = new HashMap<>(); - private Map context = new HashMap<>(); + private Map configuration = new HashMap<>(); + private Map context = new HashMap<>(); private List streams; private Mode mode = Mode.CLUSTER; private String jarPath; private Status status = Status.INITIALIZED; + public ApplicationEntity() { + } + + public ApplicationEntity(String siteId, String appType) { + SiteEntity siteEntity = new SiteEntity("", siteId); + this.site = siteEntity; + ApplicationDesc applicationDesc = new ApplicationDesc(); + applicationDesc.setType(appType); + this.descriptor = applicationDesc; + this.mode = null; + this.status = null; + } + + public ApplicationEntity(SiteEntity site, ApplicationDesc descriptor, Mode mode, Status status, String uuid, String appId) { + this.site = site; + this.descriptor = descriptor; + this.mode = mode; + this.status = status; + this.setUuid(uuid); + this.appId = appId; + } + + public SiteEntity getSite() { return site; } @@ -76,10 +99,10 @@ public class ApplicationEntity extends PersistenceEntity { @Override public void ensureDefault() { super.ensureDefault(); - if(this.appId == null){ + if (this.appId == null) { this.appId = String.format("%s-%s", this.getDescriptor().getType(), this.getSite().getSiteId()); } - if(this.status == null){ + if (this.status == null) { this.status = Status.INITIALIZED; } } @@ -124,7 +147,7 @@ public class ApplicationEntity extends PersistenceEntity { this.streams = streams; } - public static enum Status{ + public static enum Status { INITIALIZED("INITIALIZED"), STARTING("STARTING"), RUNNING("RUNNING"), @@ -132,7 +155,8 @@ public class ApplicationEntity extends PersistenceEntity { STOPPED("STOPPED"); private final String status; - Status(String status){ + + Status(String status) { this.status = status; } @@ -142,12 +166,12 @@ public class ApplicationEntity extends PersistenceEntity { } } - public static enum Mode{ + public static enum Mode { LOCAL("LOCAL"), CLUSTER("CLUSTER"); private final String name; - Mode(String name){ + Mode(String name) { this.name = name; } http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/3db5cdba/eagle-core/eagle-metadata/eagle-metadata-base/src/main/java/org/apache/eagle/metadata/model/SiteEntity.java ---------------------------------------------------------------------- diff --git a/eagle-core/eagle-metadata/eagle-metadata-base/src/main/java/org/apache/eagle/metadata/model/SiteEntity.java b/eagle-core/eagle-metadata/eagle-metadata-base/src/main/java/org/apache/eagle/metadata/model/SiteEntity.java index 5421c87..4ab197e 100644 --- a/eagle-core/eagle-metadata/eagle-metadata-base/src/main/java/org/apache/eagle/metadata/model/SiteEntity.java +++ b/eagle-core/eagle-metadata/eagle-metadata-base/src/main/java/org/apache/eagle/metadata/model/SiteEntity.java @@ -27,7 +27,15 @@ public class SiteEntity extends PersistenceEntity { private String siteId; private String siteName; private String description; - private Map context; + private Map context; + + public SiteEntity() { + } + + public SiteEntity(String uuid, String siteId) { + super.setUuid(uuid); + this.siteId = siteId; + } public String getDescription() { return description; @@ -39,7 +47,7 @@ public class SiteEntity extends PersistenceEntity { @Override public String toString() { - return String.format("SiteEntity[siteId = %s, siteName =%s, description = %s, uuid = %s]",getSiteId(),getSiteName(),getDescription(),getUuid()); + return String.format("SiteEntity[siteId = %s, siteName =%s, description = %s, uuid = %s]", getSiteId(), getSiteName(), getDescription(), getUuid()); } public String getSiteId() { http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/3db5cdba/eagle-core/eagle-metadata/eagle-metadata-jdbc/src/main/java/org/apache/eagle/metadata/store/jdbc/JDBCMetadataMetadataStoreServiceImpl.java ---------------------------------------------------------------------- diff --git a/eagle-core/eagle-metadata/eagle-metadata-jdbc/src/main/java/org/apache/eagle/metadata/store/jdbc/JDBCMetadataMetadataStoreServiceImpl.java b/eagle-core/eagle-metadata/eagle-metadata-jdbc/src/main/java/org/apache/eagle/metadata/store/jdbc/JDBCMetadataMetadataStoreServiceImpl.java index 442f0be..1ed4980 100644 --- a/eagle-core/eagle-metadata/eagle-metadata-jdbc/src/main/java/org/apache/eagle/metadata/store/jdbc/JDBCMetadataMetadataStoreServiceImpl.java +++ b/eagle-core/eagle-metadata/eagle-metadata-jdbc/src/main/java/org/apache/eagle/metadata/store/jdbc/JDBCMetadataMetadataStoreServiceImpl.java @@ -16,20 +16,23 @@ */ package org.apache.eagle.metadata.store.jdbc; -import com.google.inject.Inject; + import org.apache.eagle.common.function.ThrowableConsumer2; import org.apache.eagle.common.function.ThrowableFunction; + +import com.google.inject.Inject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import javax.sql.DataSource; import java.sql.*; import java.util.Collection; import java.util.LinkedList; import java.util.List; +import javax.sql.DataSource; + public class JDBCMetadataMetadataStoreServiceImpl implements JDBCMetadataQueryService { - private final static Logger LOGGER = LoggerFactory.getLogger(JDBCMetadataMetadataStoreServiceImpl.class); + private static final Logger LOGGER = LoggerFactory.getLogger(JDBCMetadataMetadataStoreServiceImpl.class); @Inject private DataSource dataSource; @@ -45,54 +48,65 @@ public class JDBCMetadataMetadataStoreServiceImpl implements JDBCMetadataQuerySe } catch (SQLException e) { throw e; } finally { - if(statement!=null) try { - statement.close(); - } catch (SQLException e) { - LOGGER.error(e.getMessage(),e); + if (statement != null) { + try { + statement.close(); + } catch (SQLException e) { + LOGGER.error(e.getMessage(), e); + } } - if(connection!=null) try { - connection.close(); - } catch (SQLException e) { - LOGGER.error(e.getMessage(),e); + if (connection != null) { + try { + connection.close(); + } catch (SQLException e) { + LOGGER.error(e.getMessage(), e); + } } } } @Override public boolean dropTable(String tableName) throws SQLException { - LOGGER.debug("Dropping table {}",tableName); - return execute(String.format("DROP TABLE %s",tableName)); + LOGGER.debug("Dropping table {}", tableName); + return execute(String.format("DROP TABLE %s", tableName)); } @Override - public int insert(String insertSql, Collection entities, ThrowableConsumer2 mapper) throws E, SQLException { + public int insert(String insertSql, Collection entities, ThrowableConsumer2 mapper) throws E, SQLException { Connection connection = null; PreparedStatement statement = null; - try{ + try { connection = dataSource.getConnection(); statement = connection.prepareStatement(insertSql); connection.setAutoCommit(false); - for(T entity : entities){ - mapper.accept(statement,entity); + for (T entity : entities) { + mapper.accept(statement, entity); statement.addBatch(); } int[] num = statement.executeBatch(); connection.commit(); - int sum = 0; for(int i:num) sum += i; + int sum = 0; + for (int i : num) { + sum += i; + } return sum; - } catch(SQLException ex){ + } catch (SQLException ex) { LOGGER.error("Error to insert batch: {}", insertSql, ex); throw ex; } finally { - if(statement!=null) try { - statement.close(); - } catch (SQLException e) { - LOGGER.error(e.getMessage(),e); + if (statement != null) { + try { + statement.close(); + } catch (SQLException e) { + LOGGER.error(e.getMessage(), e); + } } - if(connection!=null) try { - connection.close(); - } catch (SQLException e) { - LOGGER.error(e.getMessage(),e); + if (connection != null) { + try { + connection.close(); + } catch (SQLException e) { + LOGGER.error(e.getMessage(), e); + } } } } @@ -102,13 +116,13 @@ public class JDBCMetadataMetadataStoreServiceImpl implements JDBCMetadataQuerySe try { return dropTable(tableName); } catch (SQLException e) { - LOGGER.debug(e.getMessage(),e); + LOGGER.debug(e.getMessage(), e); } return true; } @Override - public List query(String sqlQuery, ThrowableFunction mapper) throws SQLException,E { + public List query(String sqlQuery, ThrowableFunction mapper) throws SQLException, E { Connection connection = null; PreparedStatement statement = null; ResultSet resultSet = null; @@ -117,26 +131,107 @@ public class JDBCMetadataMetadataStoreServiceImpl implements JDBCMetadataQuerySe statement = connection.prepareStatement(sqlQuery); resultSet = statement.executeQuery(); List result = new LinkedList<>(); - while(resultSet.next()) result.add(mapper.apply(resultSet)); + while (resultSet.next()) { + result.add(mapper.apply(resultSet)); + } return result; } catch (SQLException e) { LOGGER.error("Error to query batch: {}", sqlQuery, e); throw e; } finally { - if(resultSet!=null) try{ - resultSet.close(); - } catch (SQLException e) { - LOGGER.error(e.getMessage(),e); - } - if(statement!=null) try { - statement.close(); - } catch (SQLException e) { - LOGGER.error(e.getMessage(),e); - } - if(connection!=null) try { - connection.close(); - } catch (SQLException e) { - LOGGER.error(e.getMessage(),e); + if (resultSet != null) { + try { + resultSet.close(); + } catch (SQLException e) { + LOGGER.error(e.getMessage(), e); + } + } + if (statement != null) { + try { + statement.close(); + } catch (SQLException e) { + LOGGER.error(e.getMessage(), e); + } + } + if (connection != null) { + try { + connection.close(); + } catch (SQLException e) { + LOGGER.error(e.getMessage(), e); + } + } + } + } + + @Override + public List queryWithCond(String sqlQuery, T entity, ThrowableConsumer2 mapper1, ThrowableFunction mapper) throws SQLException, E { + Connection connection = null; + PreparedStatement statement = null; + ResultSet resultSet = null; + try { + connection = dataSource.getConnection(); + statement = connection.prepareStatement(sqlQuery); + mapper1.accept(statement, entity); + resultSet = statement.executeQuery(); + List result = new LinkedList<>(); + while (resultSet.next()) { + result.add(mapper.apply(resultSet)); + } + return result; + } catch (SQLException e) { + LOGGER.error("Error to query cond: {}", sqlQuery, e); + throw e; + } finally { + if (resultSet != null) { + try { + resultSet.close(); + } catch (SQLException e) { + LOGGER.error(e.getMessage(), e); + } + } + if (statement != null) { + try { + statement.close(); + } catch (SQLException e) { + LOGGER.error(e.getMessage(), e); + } + } + if (connection != null) { + try { + connection.close(); + } catch (SQLException e) { + LOGGER.error(e.getMessage(), e); + } + } + } + } + + @Override + public int update(String updateSql, T entity, ThrowableConsumer2 mapper) throws SQLException, E { + Connection connection = null; + PreparedStatement statement = null; + try { + connection = dataSource.getConnection(); + statement = connection.prepareStatement(updateSql); + mapper.accept(statement, entity); + return statement.executeUpdate(); + } catch (SQLException e) { + LOGGER.error("Error to update: {}", updateSql, e); + throw e; + } finally { + if (statement != null) { + try { + statement.close(); + } catch (SQLException e) { + LOGGER.error(e.getMessage(), e); + } + } + if (connection != null) { + try { + connection.close(); + } catch (SQLException e) { + LOGGER.error(e.getMessage(), e); + } } } } http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/3db5cdba/eagle-core/eagle-metadata/eagle-metadata-jdbc/src/main/java/org/apache/eagle/metadata/store/jdbc/JDBCMetadataQueryService.java ---------------------------------------------------------------------- diff --git a/eagle-core/eagle-metadata/eagle-metadata-jdbc/src/main/java/org/apache/eagle/metadata/store/jdbc/JDBCMetadataQueryService.java b/eagle-core/eagle-metadata/eagle-metadata-jdbc/src/main/java/org/apache/eagle/metadata/store/jdbc/JDBCMetadataQueryService.java index 82b1b00..b64ef9f 100644 --- a/eagle-core/eagle-metadata/eagle-metadata-jdbc/src/main/java/org/apache/eagle/metadata/store/jdbc/JDBCMetadataQueryService.java +++ b/eagle-core/eagle-metadata/eagle-metadata-jdbc/src/main/java/org/apache/eagle/metadata/store/jdbc/JDBCMetadataQueryService.java @@ -27,7 +27,6 @@ import java.util.List; public interface JDBCMetadataQueryService { /** - * * @param sql * @return * @throws SQLException @@ -35,7 +34,6 @@ public interface JDBCMetadataQueryService { boolean execute(String sql) throws SQLException; /** - * * @param tableName * @return * @throws SQLException @@ -52,10 +50,9 @@ public interface JDBCMetadataQueryService { * @throws E * @throws SQLException */ - int insert(String insertSql, Collection entities, ThrowableConsumer2 mapper) throws E, SQLException; + int insert(String insertSql, Collection entities, ThrowableConsumer2 mapper) throws E, SQLException; /** - * * @param tableName * @return * @throws SQLException @@ -64,9 +61,29 @@ public interface JDBCMetadataQueryService { /** * @param querySql sql query text - * @param mapper result set to entity mapper + * @param mapper result set to entity mapper * @param * @return entity list */ - List query(String querySql, ThrowableFunction mapper) throws SQLException,E; + List query(String querySql, ThrowableFunction mapper) throws SQLException, E; + + /** + * @param querySql sql query text + * @param entity query condition + * @param mapper1 + * @param mapper result set to entity mapper + * @param + * @return entity list + */ + List queryWithCond(String querySql, T entity, ThrowableConsumer2 mapper1, ThrowableFunction mapper) throws SQLException, E; + + /** + * @param updateSql update query text + * @param entity update condition + * @param mapper + * @param + * @return entity list + */ + int update(String updateSql, T entity, ThrowableConsumer2 mapper) throws SQLException, E; + } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/3db5cdba/eagle-core/eagle-metadata/eagle-metadata-jdbc/src/main/java/org/apache/eagle/metadata/store/jdbc/JDBCMetadataStore.java ---------------------------------------------------------------------- diff --git a/eagle-core/eagle-metadata/eagle-metadata-jdbc/src/main/java/org/apache/eagle/metadata/store/jdbc/JDBCMetadataStore.java b/eagle-core/eagle-metadata/eagle-metadata-jdbc/src/main/java/org/apache/eagle/metadata/store/jdbc/JDBCMetadataStore.java index 239b240..933e5e3 100644 --- a/eagle-core/eagle-metadata/eagle-metadata-jdbc/src/main/java/org/apache/eagle/metadata/store/jdbc/JDBCMetadataStore.java +++ b/eagle-core/eagle-metadata/eagle-metadata-jdbc/src/main/java/org/apache/eagle/metadata/store/jdbc/JDBCMetadataStore.java @@ -16,12 +16,18 @@ */ package org.apache.eagle.metadata.store.jdbc; -import com.google.inject.Singleton; + import org.apache.eagle.alert.metadata.IMetadataDao; import org.apache.eagle.alert.metadata.impl.JdbcMetadataDaoImpl; import org.apache.eagle.metadata.persistence.MetadataStore; +import org.apache.eagle.metadata.service.ApplicationEntityService; +import org.apache.eagle.metadata.service.SiteEntityService; import org.apache.eagle.metadata.store.jdbc.provider.JDBCDataSourceProvider; import org.apache.eagle.metadata.store.jdbc.provider.JDBCMetadataStoreConfigProvider; +import org.apache.eagle.metadata.store.jdbc.service.ApplicationEntityServiceJDBCImpl; +import org.apache.eagle.metadata.store.jdbc.service.SiteEntityServiceJDBCImpl; + +import com.google.inject.Singleton; import javax.sql.DataSource; @@ -32,5 +38,7 @@ public class JDBCMetadataStore extends MetadataStore { bind(DataSource.class).toProvider(JDBCDataSourceProvider.class).in(Singleton.class); bind(JDBCDataSourceConfig.class).toProvider(JDBCMetadataStoreConfigProvider.class).in(Singleton.class); bind(JDBCMetadataQueryService.class).to(JDBCMetadataMetadataStoreServiceImpl.class).in(Singleton.class); + bind(ApplicationEntityService.class).to(ApplicationEntityServiceJDBCImpl.class).in(Singleton.class); + bind(SiteEntityService.class).to(SiteEntityServiceJDBCImpl.class).in(Singleton.class); } } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/3db5cdba/eagle-core/eagle-metadata/eagle-metadata-jdbc/src/main/java/org/apache/eagle/metadata/store/jdbc/service/ApplicationEntityServiceJDBCImpl.java ---------------------------------------------------------------------- diff --git a/eagle-core/eagle-metadata/eagle-metadata-jdbc/src/main/java/org/apache/eagle/metadata/store/jdbc/service/ApplicationEntityServiceJDBCImpl.java b/eagle-core/eagle-metadata/eagle-metadata-jdbc/src/main/java/org/apache/eagle/metadata/store/jdbc/service/ApplicationEntityServiceJDBCImpl.java new file mode 100644 index 0000000..8dbc446 --- /dev/null +++ b/eagle-core/eagle-metadata/eagle-metadata-jdbc/src/main/java/org/apache/eagle/metadata/store/jdbc/service/ApplicationEntityServiceJDBCImpl.java @@ -0,0 +1,162 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.eagle.metadata.store.jdbc.service; + + +import org.apache.eagle.metadata.model.ApplicationEntity; +import org.apache.eagle.metadata.service.ApplicationEntityService; +import org.apache.eagle.metadata.store.jdbc.JDBCMetadataQueryService; +import org.apache.eagle.metadata.store.jdbc.service.orm.ApplicationEntityToRelation; +import org.apache.eagle.metadata.store.jdbc.service.orm.RelationToApplicationEntity; + +import com.google.inject.Singleton; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import javax.inject.Inject; + +@Singleton +public class ApplicationEntityServiceJDBCImpl implements ApplicationEntityService { + + private static final Logger LOGGER = LoggerFactory.getLogger(ApplicationEntityServiceJDBCImpl.class); + + private static final String insertSql = "INSERT INTO applicationentity (siteid, apptype, appmode, jarpath, appstatus, createdtime, modifiedtime, uuid, appid ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)"; + private static final String selectSql = "SELECT * FROM applicationentity a INNER JOIN siteentity s on a.siteid = s.siteid"; + private static final String selectSqlBySiteIdAndAppType = "SELECT * FROM applicationentity a INNER JOIN siteentity s on a.siteid = s.siteid where a.siteid = ? and a.apptype = ?"; + private static final String selectSqlBySiteId = "SELECT * FROM applicationentity a INNER JOIN siteentity s on a.siteid = s.siteid where a.siteid = ?"; + private static final String selectSqlByUUId = "SELECT * FROM applicationentity a INNER JOIN siteentity s on a.siteid = s.siteid where a.uuid = ?"; + private static final String selectSqlByAppId = "SELECT * FROM applicationentity a INNER JOIN siteentity s on a.siteid = s.siteid where a.appid = ?"; + private static final String deleteSqlByUUID = "DELETE FROM applicationentity where uuid = ?"; + + @Inject + JDBCMetadataQueryService queryService; + + @Override + public Collection findBySiteId(String siteId) { + ApplicationEntity applicationEntity = new ApplicationEntity(siteId, ""); + List results = new ArrayList<>(); + try { + results = queryService.queryWithCond(selectSqlBySiteId, applicationEntity, new ApplicationEntityToRelation(), new RelationToApplicationEntity()); + } catch (SQLException e) { + LOGGER.error("Error to getBySiteIdAndAppType ApplicationEntity: {}", e); + return results; + } + return results; + } + + @Override + public ApplicationEntity getBySiteIdAndAppType(String siteId, String appType) { + + ApplicationEntity applicationEntity = new ApplicationEntity(siteId, appType); + + List results; + try { + results = queryService.queryWithCond(selectSqlBySiteIdAndAppType, applicationEntity, new ApplicationEntityToRelation(), new RelationToApplicationEntity()); + } catch (SQLException e) { + LOGGER.error("Error to getBySiteIdAndAppType ApplicationEntity: {}", e); + return null; + } + if (results.isEmpty()) { + return null; + } + + return results.get(0); + } + + @Override + public ApplicationEntity getByUUIDOrAppId(String uuid, String appId) { + if (uuid == null && appId == null) { + throw new IllegalArgumentException("uuid and appId are both null"); + } + if (uuid != null) { + return getByUUID(uuid); + } + ApplicationEntity applicationEntity = new ApplicationEntity(null, null, null, null, "", appId); + List results = new ArrayList<>(1); + try { + results = queryService.queryWithCond(selectSqlByAppId, applicationEntity, new ApplicationEntityToRelation(), new RelationToApplicationEntity()); + } catch (SQLException e) { + LOGGER.error("Error to findAll ApplicationEntity: {}", e); + } + if (results.isEmpty()) { + throw new IllegalArgumentException("Application with appId: " + appId + " not found"); + } + return results.get(0); + } + + @Override + public ApplicationEntity delete(ApplicationEntity applicationEntity) { + ApplicationEntity entity = getByUUIDOrAppId(applicationEntity.getUuid(), applicationEntity.getAppId()); + entity = new ApplicationEntity(null, null, null, null, entity.getUuid(), ""); + try { + queryService.update(deleteSqlByUUID, entity, new ApplicationEntityToRelation()); + } catch (SQLException e) { + LOGGER.error("Error to delete ApplicationEntity: {}", entity, e); + } + return entity; + } + + @Override + public Collection findAll() { + List results = new ArrayList<>(); + try { + results = queryService.query(selectSql, new RelationToApplicationEntity()); + } catch (SQLException e) { + LOGGER.error("Error to findAll ApplicationEntity: {}", e); + } + return results; + } + + @Override + public ApplicationEntity getByUUID(String uuid) { + ApplicationEntity applicationEntity = new ApplicationEntity(null, null, null, null, uuid, ""); + List results = new ArrayList<>(1); + try { + results = queryService.queryWithCond(selectSqlByUUId, applicationEntity, new ApplicationEntityToRelation(), new RelationToApplicationEntity()); + } catch (SQLException e) { + LOGGER.error("Error to findAll ApplicationEntity: {}", e); + } + if (results.isEmpty()) { + throw new IllegalArgumentException("Application (UUID: " + uuid + ") is not found"); + } + return results.get(0); + } + + @Override + public ApplicationEntity create(ApplicationEntity entity) { + + entity.ensureDefault(); + if (getBySiteIdAndAppType(entity.getSite().getSiteId(), entity.getDescriptor().getType()) != null) { + throw new IllegalArgumentException("Duplicated appId: " + entity.getAppId()); + } + + List entities = new ArrayList<>(1); + entities.add(entity); + try { + queryService.insert(insertSql, entities, new ApplicationEntityToRelation()); + } catch (SQLException e) { + LOGGER.error("Error to insert ApplicationEntity: {}", entity, e); + } + return entity; + } +} http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/3db5cdba/eagle-core/eagle-metadata/eagle-metadata-jdbc/src/main/java/org/apache/eagle/metadata/store/jdbc/service/SiteEntityServiceJDBCImpl.java ---------------------------------------------------------------------- diff --git a/eagle-core/eagle-metadata/eagle-metadata-jdbc/src/main/java/org/apache/eagle/metadata/store/jdbc/service/SiteEntityServiceJDBCImpl.java b/eagle-core/eagle-metadata/eagle-metadata-jdbc/src/main/java/org/apache/eagle/metadata/store/jdbc/service/SiteEntityServiceJDBCImpl.java new file mode 100644 index 0000000..436f416 --- /dev/null +++ b/eagle-core/eagle-metadata/eagle-metadata-jdbc/src/main/java/org/apache/eagle/metadata/store/jdbc/service/SiteEntityServiceJDBCImpl.java @@ -0,0 +1,165 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.eagle.metadata.store.jdbc.service; + +import org.apache.eagle.metadata.exceptions.EntityNotFoundException; +import org.apache.eagle.metadata.model.SiteEntity; +import org.apache.eagle.metadata.service.SiteEntityService; +import org.apache.eagle.metadata.store.jdbc.JDBCMetadataQueryService; +import org.apache.eagle.metadata.store.jdbc.service.orm.RelationToSiteEntity; +import org.apache.eagle.metadata.store.jdbc.service.orm.SiteEntityToRelation; + +import com.google.common.base.Preconditions; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import javax.inject.Inject; + + +public class SiteEntityServiceJDBCImpl implements SiteEntityService { + + private static final Logger LOGGER = LoggerFactory.getLogger(SiteEntityServiceJDBCImpl.class); + private static final String insertSql = "INSERT INTO siteentity (siteid, sitename, description, createdtime, modifiedtime, uuid) VALUES (?, ?, ?, ?, ?, ?)"; + private static final String selectSql = "SELECT * FROM siteentity"; + private static final String selectSqlByUUID = "SELECT * FROM siteentity where uuid = ?"; + private static final String selectSqlBySiteId = "SELECT * FROM siteentity where siteid = ?"; + private static final String deleteSqlByUUID = "DELETE FROM siteentity where uuid = ?"; + private static final String deleteSqlBySiteId = "DELETE FROM siteentity where siteid = ?"; + private static final String updateSqlByUUID = "UPDATE siteentity SET siteid = ? , sitename = ? , description = ? , createdtime = ? , modifiedtime = ? where uuid = ?"; + @Inject + JDBCMetadataQueryService queryService; + + @Override + public SiteEntity getBySiteId(String siteId) throws EntityNotFoundException { + List results; + SiteEntity siteEntity = new SiteEntity("", siteId); + try { + results = queryService.queryWithCond(selectSqlBySiteId, siteEntity, new SiteEntityToRelation(), new RelationToSiteEntity()); + } catch (SQLException e) { + LOGGER.error("Error to getBySiteId SiteEntity: {}", e); + throw new EntityNotFoundException(e); + } + if (results.isEmpty()) { + throw new EntityNotFoundException("getBySiteId " + siteId + " Not Found"); + } + return results.get(0); + } + + @Override + public SiteEntity deleteBySiteId(String siteId) throws EntityNotFoundException { + SiteEntity siteEntity = new SiteEntity("", siteId); + int result; + try { + result = queryService.update(deleteSqlBySiteId, siteEntity, new SiteEntityToRelation()); + } catch (SQLException e) { + LOGGER.error("Error to deleteBySiteId SiteEntity: {}", siteEntity, e); + throw new EntityNotFoundException(e); + } + if (result == 0) { + throw new EntityNotFoundException("deleteBySiteId " + siteEntity + "Not Found"); + } + return siteEntity; + } + + @Override + public SiteEntity deleteByUUID(String uuid) throws EntityNotFoundException { + SiteEntity siteEntity = new SiteEntity(uuid, ""); + int result; + try { + result = queryService.update(deleteSqlByUUID, siteEntity, new SiteEntityToRelation()); + } catch (SQLException e) { + LOGGER.error("Error to deleteByUUID SiteEntity: {}", siteEntity, e); + throw new EntityNotFoundException(e); + } + if (result == 0) { + throw new EntityNotFoundException("deleteByUUID " + siteEntity + "Not Found"); + } + return siteEntity; + } + + @Override + public SiteEntity update(SiteEntity siteEntity) throws EntityNotFoundException { + + if (siteEntity.getSiteId() == null && siteEntity.getUuid() == null) { + throw new IllegalArgumentException("siteId and UUID are both null, don't know how to update"); + } + int result; + try { + SiteEntity oldEntity = getBySiteId(siteEntity.getSiteId()); + siteEntity.setUuid(oldEntity.getUuid()); + siteEntity.setCreatedTime(oldEntity.getCreatedTime()); + siteEntity.ensureDefault(); + result = queryService.update(updateSqlByUUID, siteEntity, new SiteEntityToRelation()); + } catch (SQLException e) { + LOGGER.error("Error to update SiteEntity: {}", siteEntity, e); + throw new EntityNotFoundException(e); + } + if (result == 0) { + throw new EntityNotFoundException("update " + siteEntity + "Not Found"); + } + + return siteEntity; + } + + @Override + public Collection findAll() { + List results = new ArrayList<>(); + try { + results = queryService.query(selectSql, new RelationToSiteEntity()); + } catch (SQLException e) { + LOGGER.error("Error to findAll SiteEntity: {}", e); + } + return results; + } + + @Override + public SiteEntity getByUUID(String uuid) throws EntityNotFoundException { + List results; + SiteEntity siteEntity = new SiteEntity(uuid, ""); + try { + results = queryService.queryWithCond(selectSqlByUUID, siteEntity, new SiteEntityToRelation(), new RelationToSiteEntity()); + } catch (SQLException e) { + LOGGER.error("Error to getByUUID SiteEntity: {}", e); + throw new EntityNotFoundException(e); + } + if (results.isEmpty()) { + throw new EntityNotFoundException("getByUUID " + uuid + " Not Found"); + } + return results.get(0); + } + + @Override + public SiteEntity create(SiteEntity entity) { + Preconditions.checkNotNull(entity.getSiteId(), "SiteId is null: " + entity.getSiteId()); + List entities = new ArrayList<>(1); + entity.ensureDefault(); + entities.add(entity); + try { + queryService.insert(insertSql, entities, new SiteEntityToRelation()); + } catch (SQLException e) { + LOGGER.error("Error to insert SiteEntity: {}", entity, e); + throw new IllegalArgumentException("MayBe Duplicated siteId: " + entity.getSiteId()); + } + return entity; + } +} http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/3db5cdba/eagle-core/eagle-metadata/eagle-metadata-jdbc/src/main/java/org/apache/eagle/metadata/store/jdbc/service/orm/ApplicationEntityToRelation.java ---------------------------------------------------------------------- diff --git a/eagle-core/eagle-metadata/eagle-metadata-jdbc/src/main/java/org/apache/eagle/metadata/store/jdbc/service/orm/ApplicationEntityToRelation.java b/eagle-core/eagle-metadata/eagle-metadata-jdbc/src/main/java/org/apache/eagle/metadata/store/jdbc/service/orm/ApplicationEntityToRelation.java new file mode 100644 index 0000000..69577e4 --- /dev/null +++ b/eagle-core/eagle-metadata/eagle-metadata-jdbc/src/main/java/org/apache/eagle/metadata/store/jdbc/service/orm/ApplicationEntityToRelation.java @@ -0,0 +1,69 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.eagle.metadata.store.jdbc.service.orm; + +import org.apache.eagle.common.function.ThrowableConsumer2; +import org.apache.eagle.metadata.model.ApplicationEntity; + +import org.apache.commons.lang.StringUtils; + +import java.sql.PreparedStatement; +import java.sql.SQLException; + +public class ApplicationEntityToRelation implements ThrowableConsumer2 { + @Override + public void accept(PreparedStatement statement, ApplicationEntity entity) throws SQLException { + int parameterIndex = 1; + if (entity.getSite() != null && StringUtils.isNotBlank(entity.getSite().getSiteId())) { + statement.setString(parameterIndex, entity.getSite().getSiteId()); + parameterIndex++; + } + if (entity.getDescriptor() != null && StringUtils.isNotBlank(entity.getDescriptor().getType())) { + statement.setString(parameterIndex, entity.getDescriptor().getType()); + parameterIndex++; + } + if (entity.getMode() != null && StringUtils.isNotBlank(entity.getMode().name())) { + statement.setString(parameterIndex, entity.getMode().name()); + parameterIndex++; + } + if (StringUtils.isNotBlank(entity.getJarPath())) { + statement.setString(parameterIndex, entity.getJarPath()); + parameterIndex++; + } + if (entity.getStatus() != null && StringUtils.isNotBlank(entity.getStatus().name())) { + statement.setString(parameterIndex, entity.getStatus().name()); + parameterIndex++; + } + if (entity.getCreatedTime() > 0) { + statement.setLong(parameterIndex, entity.getCreatedTime()); + parameterIndex++; + } + if (entity.getModifiedTime() > 0) { + statement.setLong(parameterIndex, entity.getModifiedTime()); + parameterIndex++; + } + if (StringUtils.isNotBlank(entity.getUuid())) { + statement.setString(parameterIndex, entity.getUuid()); + parameterIndex++; + } + if (StringUtils.isNotBlank(entity.getAppId())) { + statement.setString(parameterIndex, entity.getAppId()); + parameterIndex++; + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/3db5cdba/eagle-core/eagle-metadata/eagle-metadata-jdbc/src/main/java/org/apache/eagle/metadata/store/jdbc/service/orm/RelationToApplicationEntity.java ---------------------------------------------------------------------- diff --git a/eagle-core/eagle-metadata/eagle-metadata-jdbc/src/main/java/org/apache/eagle/metadata/store/jdbc/service/orm/RelationToApplicationEntity.java b/eagle-core/eagle-metadata/eagle-metadata-jdbc/src/main/java/org/apache/eagle/metadata/store/jdbc/service/orm/RelationToApplicationEntity.java new file mode 100644 index 0000000..1b705a9 --- /dev/null +++ b/eagle-core/eagle-metadata/eagle-metadata-jdbc/src/main/java/org/apache/eagle/metadata/store/jdbc/service/orm/RelationToApplicationEntity.java @@ -0,0 +1,59 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.eagle.metadata.store.jdbc.service.orm; + +import org.apache.eagle.common.function.ThrowableFunction; +import org.apache.eagle.metadata.model.ApplicationDesc; +import org.apache.eagle.metadata.model.ApplicationEntity; +import org.apache.eagle.metadata.model.SiteEntity; + +import java.sql.ResultSet; +import java.sql.SQLException; + + +public class RelationToApplicationEntity implements ThrowableFunction { + @Override + public ApplicationEntity apply(ResultSet resultSet) throws SQLException { + + ApplicationDesc applicationDesc = new ApplicationDesc(); + String appType = resultSet.getString(4); + applicationDesc.setType(appType); + + SiteEntity siteEntity = new SiteEntity(); + siteEntity.setUuid(resultSet.getString(10)); + siteEntity.setSiteId(resultSet.getString(11)); + siteEntity.setSiteName(resultSet.getString(12)); + siteEntity.setDescription(resultSet.getString(13)); + siteEntity.setCreatedTime(resultSet.getLong(14)); + siteEntity.setModifiedTime(resultSet.getLong(15)); + + + ApplicationEntity resultEntity = new ApplicationEntity(); + resultEntity.setUuid(resultSet.getString(1)); + resultEntity.setAppId(resultSet.getString(2)); + resultEntity.setSite(siteEntity); + resultEntity.setDescriptor(applicationDesc); + resultEntity.setMode(ApplicationEntity.Mode.valueOf(resultSet.getString(5))); + resultEntity.setJarPath(resultSet.getString(6)); + resultEntity.setStatus(ApplicationEntity.Status.valueOf(resultSet.getString(7))); + resultEntity.setCreatedTime(resultSet.getLong(8)); + resultEntity.setModifiedTime(resultSet.getLong(9)); + + return resultEntity; + } +} http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/3db5cdba/eagle-core/eagle-metadata/eagle-metadata-jdbc/src/main/java/org/apache/eagle/metadata/store/jdbc/service/orm/RelationToSiteEntity.java ---------------------------------------------------------------------- diff --git a/eagle-core/eagle-metadata/eagle-metadata-jdbc/src/main/java/org/apache/eagle/metadata/store/jdbc/service/orm/RelationToSiteEntity.java b/eagle-core/eagle-metadata/eagle-metadata-jdbc/src/main/java/org/apache/eagle/metadata/store/jdbc/service/orm/RelationToSiteEntity.java new file mode 100644 index 0000000..1c8c795 --- /dev/null +++ b/eagle-core/eagle-metadata/eagle-metadata-jdbc/src/main/java/org/apache/eagle/metadata/store/jdbc/service/orm/RelationToSiteEntity.java @@ -0,0 +1,37 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.eagle.metadata.store.jdbc.service.orm; + +import org.apache.eagle.common.function.ThrowableFunction; +import org.apache.eagle.metadata.model.SiteEntity; + +import java.sql.ResultSet; +import java.sql.SQLException; + +public class RelationToSiteEntity implements ThrowableFunction { + @Override + public SiteEntity apply(ResultSet resultSet) throws SQLException { + SiteEntity siteEntityResult = new SiteEntity(); + siteEntityResult.setUuid(resultSet.getString(1)); + siteEntityResult.setSiteId(resultSet.getString(2)); + siteEntityResult.setSiteName(resultSet.getString(3)); + siteEntityResult.setDescription(resultSet.getString(4)); + siteEntityResult.setCreatedTime(resultSet.getLong(5)); + siteEntityResult.setModifiedTime(resultSet.getLong(6)); + return siteEntityResult; + } +} http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/3db5cdba/eagle-core/eagle-metadata/eagle-metadata-jdbc/src/main/java/org/apache/eagle/metadata/store/jdbc/service/orm/SiteEntityToRelation.java ---------------------------------------------------------------------- diff --git a/eagle-core/eagle-metadata/eagle-metadata-jdbc/src/main/java/org/apache/eagle/metadata/store/jdbc/service/orm/SiteEntityToRelation.java b/eagle-core/eagle-metadata/eagle-metadata-jdbc/src/main/java/org/apache/eagle/metadata/store/jdbc/service/orm/SiteEntityToRelation.java new file mode 100644 index 0000000..7f592e3 --- /dev/null +++ b/eagle-core/eagle-metadata/eagle-metadata-jdbc/src/main/java/org/apache/eagle/metadata/store/jdbc/service/orm/SiteEntityToRelation.java @@ -0,0 +1,58 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.eagle.metadata.store.jdbc.service.orm; + + +import org.apache.eagle.common.function.ThrowableConsumer2; +import org.apache.eagle.metadata.model.SiteEntity; + +import org.apache.commons.lang.StringUtils; + +import java.sql.PreparedStatement; +import java.sql.SQLException; + +public class SiteEntityToRelation implements ThrowableConsumer2 { + @Override + public void accept(PreparedStatement statement, SiteEntity entity) throws SQLException { + int parameterIndex = 1; + if (StringUtils.isNotBlank(entity.getSiteId())) { + statement.setString(parameterIndex, entity.getSiteId()); + parameterIndex++; + } + if (StringUtils.isNotBlank(entity.getSiteName())) { + statement.setString(parameterIndex, entity.getSiteName()); + parameterIndex++; + } + if (StringUtils.isNotBlank(entity.getDescription())) { + statement.setString(parameterIndex, entity.getDescription()); + parameterIndex++; + } + if (entity.getCreatedTime() > 0) { + statement.setLong(parameterIndex, entity.getCreatedTime()); + parameterIndex++; + } + if (entity.getModifiedTime() > 0) { + statement.setLong(parameterIndex, entity.getModifiedTime()); + parameterIndex++; + } + if (StringUtils.isNotBlank(entity.getUuid())) { + statement.setString(parameterIndex, entity.getUuid()); + parameterIndex++; + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/3db5cdba/eagle-core/eagle-metadata/eagle-metadata-jdbc/src/test/java/org/apache/eagle/metadata/store/jdbc/ApplicationEntityServiceJDBCImplTest.java ---------------------------------------------------------------------- diff --git a/eagle-core/eagle-metadata/eagle-metadata-jdbc/src/test/java/org/apache/eagle/metadata/store/jdbc/ApplicationEntityServiceJDBCImplTest.java b/eagle-core/eagle-metadata/eagle-metadata-jdbc/src/test/java/org/apache/eagle/metadata/store/jdbc/ApplicationEntityServiceJDBCImplTest.java new file mode 100644 index 0000000..23db1be --- /dev/null +++ b/eagle-core/eagle-metadata/eagle-metadata-jdbc/src/test/java/org/apache/eagle/metadata/store/jdbc/ApplicationEntityServiceJDBCImplTest.java @@ -0,0 +1,153 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "+License"+); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "+AS IS"+ BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.eagle.metadata.store.jdbc; + +import org.apache.eagle.metadata.exceptions.EntityNotFoundException; +import org.apache.eagle.metadata.model.ApplicationDesc; +import org.apache.eagle.metadata.model.ApplicationEntity; +import org.apache.eagle.metadata.model.SiteEntity; +import org.apache.eagle.metadata.service.ApplicationEntityService; +import org.apache.eagle.metadata.service.SiteEntityService; +import org.junit.Assert; +import org.junit.Test; + +import javax.inject.Inject; +import java.sql.SQLException; +import java.util.Collection; + +public class ApplicationEntityServiceJDBCImplTest extends JDBCMetadataTestBase { + + @Inject + ApplicationEntityService applicationEntityService; + + @Inject + SiteEntityService siteEntityService; + + @Test + public void testCRUDApplicationEntity() throws SQLException, EntityNotFoundException { + + SiteEntity siteEntity = new SiteEntity(); + siteEntity.setSiteId("testsiteid"); + siteEntity.setSiteName("testsitename"); + siteEntity.setDescription("testdesc"); + siteEntityService.create(siteEntity); + String siteuuid = siteEntity.getUuid(); + long sitecreateTime = siteEntity.getCreatedTime(); + long sitemodifiedTime = siteEntity.getModifiedTime(); + ApplicationDesc applicationDesc = new ApplicationDesc(); + applicationDesc.setType("testtype"); + + + ApplicationEntity applicationEntity = new ApplicationEntity(); + applicationEntity.setSite(siteEntity); + applicationEntity.setDescriptor(applicationDesc); + applicationEntity.setMode(ApplicationEntity.Mode.LOCAL); + applicationEntity.setJarPath("c://"); + + applicationEntityService.create(applicationEntity); + String appuuid = applicationEntity.getUuid(); + String appId = applicationEntity.getAppId(); + long createTime = applicationEntity.getCreatedTime(); + long modifiedTime = applicationEntity.getModifiedTime(); + + Collection results = applicationEntityService.findAll(); + Assert.assertEquals(1, results.size()); + ApplicationEntity applicationEntityFromDB = applicationEntityService.getBySiteIdAndAppType("testsiteid", "testtype"); + Assert.assertTrue(applicationEntityFromDB != null); + results = applicationEntityService.findBySiteId("testsiteid"); + Assert.assertEquals(1, results.size()); + + applicationEntityFromDB = applicationEntityService.getByUUID(appuuid); + + Assert.assertTrue(applicationEntityFromDB != null); + applicationEntityFromDB = applicationEntityService.getByUUIDOrAppId(null, appId); + + Assert.assertEquals(siteuuid, applicationEntityFromDB.getSite().getUuid()); + Assert.assertEquals("testsiteid", applicationEntityFromDB.getSite().getSiteId()); + Assert.assertEquals("testsitename", applicationEntityFromDB.getSite().getSiteName()); + Assert.assertEquals("testdesc", applicationEntityFromDB.getSite().getDescription()); + Assert.assertEquals(sitecreateTime, applicationEntityFromDB.getSite().getCreatedTime()); + Assert.assertEquals(sitemodifiedTime, applicationEntityFromDB.getSite().getModifiedTime()); + + Assert.assertEquals(appuuid, applicationEntityFromDB.getUuid()); + Assert.assertEquals(appId, applicationEntityFromDB.getAppId()); + Assert.assertEquals("testtype", applicationEntityFromDB.getDescriptor().getType()); + Assert.assertEquals(ApplicationEntity.Mode.LOCAL, applicationEntityFromDB.getMode()); + Assert.assertEquals("c://", applicationEntityFromDB.getJarPath()); + Assert.assertEquals(ApplicationEntity.Status.INITIALIZED, applicationEntityFromDB.getStatus()); + Assert.assertEquals(createTime, applicationEntityFromDB.getCreatedTime()); + Assert.assertEquals(modifiedTime, applicationEntityFromDB.getModifiedTime()); + + + } + + @Test(expected = IllegalArgumentException.class) + public void testInsertApplicationEntityFail() { + SiteEntity siteEntity = new SiteEntity(); + siteEntity.setSiteId("testsiteid"); + siteEntity.setSiteName("testsitename"); + siteEntity.setDescription("testdesc"); + siteEntityService.create(siteEntity); + ApplicationDesc applicationDesc = new ApplicationDesc(); + applicationDesc.setType("testtype"); + + + ApplicationEntity applicationEntity = new ApplicationEntity(); + applicationEntity.setSite(siteEntity); + applicationEntity.setDescriptor(applicationDesc); + applicationEntity.setMode(ApplicationEntity.Mode.LOCAL); + applicationEntity.setJarPath("c://"); + + applicationEntityService.create(applicationEntity); + applicationEntityService.create(applicationEntity); + } + + @Test(expected = IllegalArgumentException.class) + public void testGetByUUIDFail() throws EntityNotFoundException { + applicationEntityService.getByUUID("fake uuid"); + } + + @Test(expected = IllegalArgumentException.class) + public void testGetByUUIDOrAppId() { + applicationEntityService.getByUUIDOrAppId(null, "fake appid"); + } + @Test + public void testDelApplicationEntity() { + SiteEntity siteEntity = new SiteEntity(); + siteEntity.setSiteId("testsiteid"); + siteEntity.setSiteName("testsitename"); + siteEntity.setDescription("testdesc"); + siteEntityService.create(siteEntity); + ApplicationDesc applicationDesc = new ApplicationDesc(); + applicationDesc.setType("testtype"); + + + ApplicationEntity applicationEntity = new ApplicationEntity(); + applicationEntity.setSite(siteEntity); + applicationEntity.setDescriptor(applicationDesc); + applicationEntity.setMode(ApplicationEntity.Mode.LOCAL); + applicationEntity.setJarPath("c://"); + applicationEntityService.create(applicationEntity); + Collection results = applicationEntityService.findAll(); + Assert.assertEquals(1, results.size()); + applicationEntityService.delete(applicationEntity); + results = applicationEntityService.findAll(); + Assert.assertEquals(0, results.size()); + } + +} http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/3db5cdba/eagle-core/eagle-metadata/eagle-metadata-jdbc/src/test/java/org/apache/eagle/metadata/store/jdbc/JDBCDataSourceProviderTest.java ---------------------------------------------------------------------- diff --git a/eagle-core/eagle-metadata/eagle-metadata-jdbc/src/test/java/org/apache/eagle/metadata/store/jdbc/JDBCDataSourceProviderTest.java b/eagle-core/eagle-metadata/eagle-metadata-jdbc/src/test/java/org/apache/eagle/metadata/store/jdbc/JDBCDataSourceProviderTest.java index 9094a57..6574a1b 100644 --- a/eagle-core/eagle-metadata/eagle-metadata-jdbc/src/test/java/org/apache/eagle/metadata/store/jdbc/JDBCDataSourceProviderTest.java +++ b/eagle-core/eagle-metadata/eagle-metadata-jdbc/src/test/java/org/apache/eagle/metadata/store/jdbc/JDBCDataSourceProviderTest.java @@ -42,7 +42,7 @@ public class JDBCDataSourceProviderTest extends JDBCMetadataTestBase{ @Test public void testDataSourceConfig(){ - Assert.assertEquals("jdbc:h2:./eagle4ut",dataSourceConfig.getUrl()); + Assert.assertEquals("jdbc:h2:mem:test;INIT=RUNSCRIPT FROM './src/test/resources/init.sql'",dataSourceConfig.getUrl()); Assert.assertEquals(null,dataSourceConfig.getUsername()); Assert.assertEquals(null,dataSourceConfig.getPassword()); Assert.assertEquals("encoding=UTF8;timeout=60",dataSourceConfig.getConnectionProperties()); http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/3db5cdba/eagle-core/eagle-metadata/eagle-metadata-jdbc/src/test/java/org/apache/eagle/metadata/store/jdbc/SiteEntityServiceJDBCImplTest.java ---------------------------------------------------------------------- diff --git a/eagle-core/eagle-metadata/eagle-metadata-jdbc/src/test/java/org/apache/eagle/metadata/store/jdbc/SiteEntityServiceJDBCImplTest.java b/eagle-core/eagle-metadata/eagle-metadata-jdbc/src/test/java/org/apache/eagle/metadata/store/jdbc/SiteEntityServiceJDBCImplTest.java new file mode 100644 index 0000000..adb730f --- /dev/null +++ b/eagle-core/eagle-metadata/eagle-metadata-jdbc/src/test/java/org/apache/eagle/metadata/store/jdbc/SiteEntityServiceJDBCImplTest.java @@ -0,0 +1,216 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "+License"+); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "+AS IS"+ BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.eagle.metadata.store.jdbc; + +import org.apache.eagle.metadata.exceptions.EntityNotFoundException; +import org.apache.eagle.metadata.model.SiteEntity; +import org.apache.eagle.metadata.service.SiteEntityService; +import org.junit.Assert; +import org.junit.Test; + +import javax.inject.Inject; +import java.sql.SQLException; +import java.util.Collection; + +public class SiteEntityServiceJDBCImplTest extends JDBCMetadataTestBase { + @Inject + SiteEntityService siteEntityService; + + @Test + public void testInsertSiteEntityAndFindAll() throws SQLException { + SiteEntity siteEntity = new SiteEntity(); + siteEntity.setSiteId("testsiteid"); + siteEntity.setSiteName("testsitename"); + siteEntity.setDescription("testdesc"); + + siteEntityService.create(siteEntity); + String uuid = siteEntity.getUuid(); + long createdTime = siteEntity.getCreatedTime(); + long modifiedTime = siteEntity.getModifiedTime(); + + Collection results = siteEntityService.findAll(); + Assert.assertEquals(1, results.size()); + SiteEntity siteEntityFromDB = results.iterator().next(); + Assert.assertEquals(uuid, siteEntityFromDB.getUuid()); + Assert.assertEquals("testsiteid", siteEntityFromDB.getSiteId()); + Assert.assertEquals("testsitename", siteEntityFromDB.getSiteName()); + Assert.assertEquals("testdesc", siteEntityFromDB.getDescription()); + Assert.assertEquals(createdTime, siteEntityFromDB.getCreatedTime()); + Assert.assertEquals(modifiedTime, siteEntityFromDB.getModifiedTime()); + + } + + @Test(expected = IllegalArgumentException.class) + public void testInsertSiteEntitySiteIdUnique() throws SQLException { + SiteEntity siteEntity = new SiteEntity(); + siteEntity.setSiteId("testsiteid"); + siteEntity.setSiteName("testsitename"); + siteEntity.setDescription("testdesc"); + siteEntityService.create(siteEntity); + + + SiteEntity siteEntity1 = new SiteEntity(); + siteEntity1.setSiteId("testsiteid"); + siteEntity1.setSiteName("testsitename"); + siteEntity1.setDescription("testdesc"); + siteEntityService.create(siteEntity1); + + + Collection results = siteEntityService.findAll(); + Assert.assertEquals(1, results.size()); + } + + @Test + public void testInsertSiteEntityAndFindByUUID() throws SQLException, EntityNotFoundException { + SiteEntity siteEntity = new SiteEntity(); + siteEntity.setSiteId("testsiteid"); + siteEntity.setSiteName("testsitename"); + siteEntity.setDescription("testdesc"); + siteEntityService.create(siteEntity); + String uuid = siteEntity.getUuid(); + long createdTime = siteEntity.getCreatedTime(); + long modifiedTime = siteEntity.getModifiedTime(); + + SiteEntity siteEntityFromDB = siteEntityService.getByUUID(uuid); + Assert.assertEquals(uuid, siteEntityFromDB.getUuid()); + Assert.assertEquals("testsiteid", siteEntityFromDB.getSiteId()); + Assert.assertEquals("testsitename", siteEntityFromDB.getSiteName()); + Assert.assertEquals("testdesc", siteEntityFromDB.getDescription()); + Assert.assertEquals(createdTime, siteEntityFromDB.getCreatedTime()); + Assert.assertEquals(modifiedTime, siteEntityFromDB.getModifiedTime()); + + } + + @Test(expected = EntityNotFoundException.class) + public void testFindByUUID() throws SQLException, EntityNotFoundException { + siteEntityService.getByUUID("fake uuid"); + } + + @Test + public void testInsertSiteEntityAndFindBySiteId() throws SQLException, EntityNotFoundException { + SiteEntity siteEntity = new SiteEntity(); + siteEntity.setSiteId("testsiteid"); + siteEntity.setSiteName("testsitename"); + siteEntity.setDescription("testdesc"); + siteEntityService.create(siteEntity); + String uuid = siteEntity.getUuid(); + long createdTime = siteEntity.getCreatedTime(); + long modifiedTime = siteEntity.getModifiedTime(); + + SiteEntity siteEntityFromDB = siteEntityService.getBySiteId("testsiteid"); + Assert.assertEquals(uuid, siteEntityFromDB.getUuid()); + Assert.assertEquals("testsiteid", siteEntityFromDB.getSiteId()); + Assert.assertEquals("testsitename", siteEntityFromDB.getSiteName()); + Assert.assertEquals("testdesc", siteEntityFromDB.getDescription()); + Assert.assertEquals(createdTime, siteEntityFromDB.getCreatedTime()); + Assert.assertEquals(modifiedTime, siteEntityFromDB.getModifiedTime()); + + } + + @Test(expected = EntityNotFoundException.class) + public void testFindBySiteId() throws SQLException, EntityNotFoundException { + siteEntityService.getBySiteId("fake siteId"); + } + + @Test + public void testUpdateSiteEntity() throws SQLException, EntityNotFoundException { + + SiteEntity siteEntity = new SiteEntity(); + siteEntity.setSiteId("testsiteid"); + siteEntity.setSiteName("testsitename"); + siteEntity.setDescription("testdesc"); + siteEntityService.create(siteEntity); + String uuid = siteEntity.getUuid(); + long createdTime = siteEntity.getCreatedTime(); + long modifiedTime = siteEntity.getModifiedTime(); + + siteEntity.setSiteName("testsitenamem"); + siteEntity.setDescription("testdescm"); + siteEntityService.update(siteEntity); + + SiteEntity siteEntityFromDB = siteEntityService.getByUUID(uuid); + Assert.assertEquals(uuid, siteEntityFromDB.getUuid()); + Assert.assertEquals("testsiteid", siteEntityFromDB.getSiteId()); + Assert.assertEquals("testsitenamem", siteEntityFromDB.getSiteName()); + Assert.assertEquals("testdescm", siteEntityFromDB.getDescription()); + Assert.assertEquals(createdTime, siteEntityFromDB.getCreatedTime()); + Assert.assertTrue(siteEntityFromDB.getModifiedTime() > modifiedTime); + + } + + @Test(expected = EntityNotFoundException.class) + public void testUpdateSiteEntityFail() throws SQLException, EntityNotFoundException { + SiteEntity siteEntity = new SiteEntity(); + siteEntity.setSiteId("testsiteid"); + siteEntity.setSiteName("testsitename"); + siteEntity.setDescription("testdesc"); + siteEntityService.update(siteEntity); + } + + @Test(expected = EntityNotFoundException.class) + public void testDeleteSiteEntityByUUID() throws SQLException, EntityNotFoundException { + + SiteEntity siteEntity = new SiteEntity(); + siteEntity.setSiteId("testsiteid"); + siteEntity.setSiteName("testsitename"); + siteEntity.setDescription("testdesc"); + siteEntityService.create(siteEntity); + String uuid = siteEntity.getUuid(); + Collection results = siteEntityService.findAll(); + Assert.assertEquals(1, results.size()); + siteEntityService.deleteByUUID(uuid); + results = siteEntityService.findAll(); + Assert.assertEquals(0, results.size()); + siteEntityService.getByUUID(uuid); + } + + @Test(expected = EntityNotFoundException.class) + public void testDeleteSiteEntityByUUID1() throws SQLException, EntityNotFoundException { + siteEntityService.getByUUID("fake uuid"); + } + + @Test(expected = EntityNotFoundException.class) + public void testDeleteSiteEntityBySiteId() throws SQLException, EntityNotFoundException { + + SiteEntity siteEntity = new SiteEntity(); + siteEntity.setSiteId("testsiteid"); + siteEntity.setSiteName("testsitename"); + siteEntity.setDescription("testdesc"); + String siteId = siteEntity.getSiteId(); + siteEntityService.create(siteEntity); + siteEntityService.findAll(); + Collection results = siteEntityService.findAll(); + Assert.assertEquals(1, results.size()); + siteEntityService.deleteBySiteId(siteId); + siteEntityService.getBySiteId(siteId); + } + + @Test(expected = EntityNotFoundException.class) + public void testDeleteSiteEntityBySiteId1() throws SQLException, EntityNotFoundException { + siteEntityService.getBySiteId("fake siteId"); + } + + @Test + public void testSiteEntity() throws SQLException, EntityNotFoundException { + SiteEntity siteEntity1 = new SiteEntity("uuid", "siteid"); + Assert.assertEquals("uuid", siteEntity1.getUuid()); + Assert.assertEquals("siteid", siteEntity1.getSiteId()); + + } + +} http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/3db5cdba/eagle-core/eagle-metadata/eagle-metadata-jdbc/src/test/resources/application.conf ---------------------------------------------------------------------- diff --git a/eagle-core/eagle-metadata/eagle-metadata-jdbc/src/test/resources/application.conf b/eagle-core/eagle-metadata/eagle-metadata-jdbc/src/test/resources/application.conf index cb2705f..dec8129 100644 --- a/eagle-core/eagle-metadata/eagle-metadata-jdbc/src/test/resources/application.conf +++ b/eagle-core/eagle-metadata/eagle-metadata-jdbc/src/test/resources/application.conf @@ -20,7 +20,7 @@ username = null password = null driverClassName = "org.h2.Driver" - url = "jdbc:h2:./eagle4ut" + url = "jdbc:h2:mem:test;INIT=RUNSCRIPT FROM './src/test/resources/init.sql'" connectionProperties = "encoding=UTF8;timeout=60" } } http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/3db5cdba/eagle-core/eagle-metadata/eagle-metadata-jdbc/src/test/resources/init.sql ---------------------------------------------------------------------- diff --git a/eagle-core/eagle-metadata/eagle-metadata-jdbc/src/test/resources/init.sql b/eagle-core/eagle-metadata/eagle-metadata-jdbc/src/test/resources/init.sql new file mode 100644 index 0000000..32e2e1d --- /dev/null +++ b/eagle-core/eagle-metadata/eagle-metadata-jdbc/src/test/resources/init.sql @@ -0,0 +1,39 @@ +-- /* +-- * Licensed to the Apache Software Foundation (ASF) under one or more +-- * contributor license agreements. See the NOTICE file distributed with +-- * this work for additional information regarding copyright ownership. +-- * The ASF licenses this file to You under the Apache License, Version 2.0 +-- * (the "License"); you may not use this file except in compliance with +-- * the License. You may obtain a copy of the License at +-- * +-- * http://www.apache.org/licenses/LICENSE-2.0 +-- * +-- * Unless required by applicable law or agreed to in writing, software +-- * distributed under the License is distributed on an "AS IS" BASIS, +-- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- * See the License for the specific language governing permissions and +-- * limitations under the License. +-- * +-- */ + +CREATE TABLE IF NOT EXISTS applicationentity ( + uuid varchar(50) PRIMARY KEY, + appid varchar(100) DEFAULT NULL, + siteid varchar(100) DEFAULT NULL, + apptype varchar(10) DEFAULT NULL, + appmode varchar(10) DEFAULT NULL, + jarpath varchar(255) DEFAULT NULL, + appstatus varchar(20) DEFAULT NULL, + createdtime bigint(20) DEFAULT NULL, + modifiedtime bigint(20) DEFAULT NULL +); + +CREATE TABLE IF NOT EXISTS siteentity ( + uuid varchar(50) PRIMARY KEY, + siteid varchar(100) DEFAULT NULL, + sitename varchar(100) DEFAULT NULL, + description varchar(255) DEFAULT NULL, + createdtime bigint(20) DEFAULT NULL, + modifiedtime bigint(20) DEFAULT NULL, + UNIQUE (siteid) +); \ No newline at end of file