AMBARI-19872 : HiveView2.0 : added Upload CSV,JSON, XML to create table feature in the new view (nitirajrathore)
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/d3451fb3 Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/d3451fb3 Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/d3451fb3 Branch: refs/heads/branch-2.5 Commit: d3451fb347bf96fceefc6190904f59682a9eb390 Parents: c066fa8 Author: Nitiraj Singh Rathore <[email protected]> Authored: Tue Feb 7 13:02:34 2017 +0530 Committer: Nitiraj Singh Rathore <[email protected]> Committed: Tue Feb 7 13:02:34 2017 +0530 ---------------------------------------------------------------------- .../view/hive20/internal/dto/ColumnInfo.java | 4 + .../generators/InsertFromQueryGenerator.java | 77 ++ .../view/hive20/resources/jobs/JobService.java | 1 + .../hive20/resources/uploads/CSVParams.java | 2 +- .../resources/uploads/TableDataReader.java | 5 +- .../hive20/resources/uploads/TableInput.java | 51 - .../resources/uploads/UploadFromHdfsInput.java | 8 +- .../hive20/resources/uploads/UploadService.java | 107 +-- .../resources/uploads/parsers/Parser.java | 11 +- .../resources/uploads/parsers/PreviewData.java | 9 +- .../uploads/query/InsertFromQueryInput.java | 10 +- .../resources/uploads/query/QueryGenerator.java | 143 --- .../resources/uploads/query/RowFormat.java | 57 -- .../resources/uploads/query/TableInfo.java | 97 -- .../resources/ui/app/adapters/file-uploader.js | 28 + .../resources/ui/app/adapters/upload-table.js | 93 ++ .../ui/app/components/csv-format-params.js | 77 ++ .../resources/ui/app/components/radio-button.js | 40 + .../resources/ui/app/components/simple-table.js | 22 + .../ui/app/components/upload-table-source.js | 48 + .../resources/ui/app/components/upload-table.js | 60 ++ .../ui/app/components/validated-text-field.js | 62 ++ .../main/resources/ui/app/configs/helpers.js | 14 +- .../resources/ui/app/locales/en/translations.js | 111 +++ .../src/main/resources/ui/app/models/column.js | 23 +- .../hive20/src/main/resources/ui/app/router.js | 2 +- .../app/routes/databases/database/tables/new.js | 80 +- .../databases/database/tables/upload-table.js | 925 +++++++++++++++++++ .../src/main/resources/ui/app/services/jobs.js | 3 + .../ui/app/services/table-operations.js | 4 +- .../templates/components/csv-format-params.hbs | 118 +++ .../app/templates/components/radio-button.hbs | 19 + .../app/templates/components/simple-table.hbs | 42 + .../components/upload-table-source.hbs | 112 +++ .../app/templates/components/upload-table.hbs | 59 ++ .../components/validated-text-field.hbs | 23 + .../templates/databases/database/tables/new.hbs | 6 +- .../databases/database/tables/upload-table.hbs | 45 + .../main/resources/ui/app/utils/constants.js | 64 ++ .../hive20/src/main/resources/ui/bower.json | 3 +- .../src/main/resources/ui/config/environment.js | 4 + .../hive20/src/main/resources/ui/package.json | 3 + .../resources/upload/DataParserCSVTest.java | 29 +- .../resources/upload/DataParserJSONTest.java | 37 +- .../resources/upload/DataParserXMLTest.java | 20 +- .../resources/upload/QueryGeneratorTest.java | 108 --- .../resources/upload/TableDataReaderTest.java | 5 +- 47 files changed, 2249 insertions(+), 622 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ambari/blob/d3451fb3/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/internal/dto/ColumnInfo.java ---------------------------------------------------------------------- diff --git a/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/internal/dto/ColumnInfo.java b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/internal/dto/ColumnInfo.java index 44c82a0..5daab91 100644 --- a/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/internal/dto/ColumnInfo.java +++ b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/internal/dto/ColumnInfo.java @@ -30,6 +30,10 @@ public class ColumnInfo { private Integer scale; private String comment; + private ColumnInfo(){ + // for json de-serialization + } + public ColumnInfo(String name, String type, Integer precision, Integer scale, String comment) { this.name = name; this.type = type; http://git-wip-us.apache.org/repos/asf/ambari/blob/d3451fb3/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/internal/query/generators/InsertFromQueryGenerator.java ---------------------------------------------------------------------- diff --git a/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/internal/query/generators/InsertFromQueryGenerator.java b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/internal/query/generators/InsertFromQueryGenerator.java new file mode 100644 index 0000000..42cec0a --- /dev/null +++ b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/internal/query/generators/InsertFromQueryGenerator.java @@ -0,0 +1,77 @@ +/* +* 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.ambari.view.hive20.internal.query.generators; + +import com.google.common.base.Optional; +import org.apache.ambari.view.hive20.client.ColumnDescription; +import org.apache.ambari.view.hive20.exceptions.ServiceException; +import org.apache.ambari.view.hive20.internal.dto.ColumnInfo; +import org.apache.ambari.view.hive20.resources.uploads.query.InsertFromQueryInput; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class InsertFromQueryGenerator implements QueryGenerator{ + protected final static Logger LOG = + LoggerFactory.getLogger(InsertFromQueryGenerator.class); + + private InsertFromQueryInput insertFromQueryInput; + + public InsertFromQueryGenerator(InsertFromQueryInput insertFromQueryInput) { + this.insertFromQueryInput = insertFromQueryInput; + } + + @Override + public Optional<String> getQuery() throws ServiceException { + StringBuilder insertQuery = new StringBuilder("INSERT INTO TABLE `").append(insertFromQueryInput.getToDatabase()).append(".") + .append(insertFromQueryInput.getToTable()).append("`") + .append(" SELECT "); + + boolean first = true; + for(ColumnInfo column : insertFromQueryInput.getHeader()){ + String type = column.getType(); + boolean unhex = insertFromQueryInput.getUnhexInsert() && ( + ColumnDescription.DataTypes.STRING.toString().equals(type) + || ColumnDescription.DataTypes.VARCHAR.toString().equals(type) + || ColumnDescription.DataTypes.CHAR.toString().equals(type) + ); + + if(!first){ + insertQuery.append(", "); + } + + if(unhex) { + insertQuery.append("UNHEX("); + } + + insertQuery.append(column.getName()); + + if(unhex) { + insertQuery.append(")"); + } + + first = false; + } + + insertQuery.append(" FROM ").append("`").append(insertFromQueryInput.getFromDatabase()).append(".") + .append(insertFromQueryInput.getFromTable()).append("` ").append(";"); + String query = insertQuery.toString(); + LOG.info("Insert From Query : {}", query); + return Optional.of(query); + } +} http://git-wip-us.apache.org/repos/asf/ambari/blob/d3451fb3/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/jobs/JobService.java ---------------------------------------------------------------------- diff --git a/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/jobs/JobService.java b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/jobs/JobService.java index 71cedd1..c5479e7 100644 --- a/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/jobs/JobService.java +++ b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/jobs/JobService.java @@ -154,6 +154,7 @@ public class JobService extends BaseService { } catch (ItemNotFound itemNotFound) { throw new NotFoundFormattedException(itemNotFound.getMessage(), itemNotFound); } catch (Exception ex) { + LOG.error("exception while fetching status of job with id : {}", jobId, ex); throw new ServiceFormattedException(ex.getMessage(), ex); } } http://git-wip-us.apache.org/repos/asf/ambari/blob/d3451fb3/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/uploads/CSVParams.java ---------------------------------------------------------------------- diff --git a/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/uploads/CSVParams.java b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/uploads/CSVParams.java index 355ed6a..03ed895 100644 --- a/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/uploads/CSVParams.java +++ b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/uploads/CSVParams.java @@ -16,7 +16,7 @@ * limitations under the License. */ -package org.apache.ambari.view.hive.resources.uploads; +package org.apache.ambari.view.hive20.resources.uploads; import java.io.Serializable; http://git-wip-us.apache.org/repos/asf/ambari/blob/d3451fb3/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/uploads/TableDataReader.java ---------------------------------------------------------------------- diff --git a/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/uploads/TableDataReader.java b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/uploads/TableDataReader.java index ee148b8..2855760 100644 --- a/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/uploads/TableDataReader.java +++ b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/uploads/TableDataReader.java @@ -21,6 +21,7 @@ package org.apache.ambari.view.hive20.resources.uploads; import com.opencsv.CSVWriter; import org.apache.ambari.view.hive20.client.ColumnDescription; import org.apache.ambari.view.hive20.client.Row; +import org.apache.ambari.view.hive20.internal.dto.ColumnInfo; import org.apache.commons.codec.binary.Hex; import java.io.IOException; @@ -38,14 +39,14 @@ import java.util.List; public class TableDataReader extends Reader { private static final int CAPACITY = 1024; - private final List<ColumnDescriptionImpl> header; + private final List<ColumnInfo> header; private StringReader stringReader = new StringReader(""); private Iterator<Row> iterator; private boolean encode = false; public static final char CSV_DELIMITER = '\001'; - public TableDataReader(Iterator<Row> rowIterator, List<ColumnDescriptionImpl> header, boolean encode) { + public TableDataReader(Iterator<Row> rowIterator, List<ColumnInfo> header, boolean encode) { this.iterator = rowIterator; this.encode = encode; this.header = header; http://git-wip-us.apache.org/repos/asf/ambari/blob/d3451fb3/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/uploads/TableInput.java ---------------------------------------------------------------------- diff --git a/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/uploads/TableInput.java b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/uploads/TableInput.java deleted file mode 100644 index 4f15c57..0000000 --- a/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/uploads/TableInput.java +++ /dev/null @@ -1,51 +0,0 @@ -/** - * 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 - * <p/> - * http://www.apache.org/licenses/LICENSE-2.0 - * <p/> - * 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.ambari.view.hive20.resources.uploads; - -import org.apache.ambari.view.hive20.resources.uploads.query.TableInfo; - -/** - * used as input in REST call - */ -class TableInput extends TableInfo { - public Boolean isFirstRowHeader = Boolean.FALSE; - - public TableInput() { - } - - public Boolean getIsFirstRowHeader() { - return isFirstRowHeader; - } - - public void setIsFirstRowHeader(Boolean isFirstRowHeader) { - this.isFirstRowHeader = isFirstRowHeader; - } - - public void validate(){ - if( null == this.getHiveFileType()){ - throw new IllegalArgumentException("fileType parameter cannot be null."); - } - if( null == this.getTableName()){ - throw new IllegalArgumentException("tableName parameter cannot be null."); - } - if( null == this.getDatabaseName()){ - throw new IllegalArgumentException("databaseName parameter cannot be null."); - } - } -} http://git-wip-us.apache.org/repos/asf/ambari/blob/d3451fb3/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/uploads/UploadFromHdfsInput.java ---------------------------------------------------------------------- diff --git a/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/uploads/UploadFromHdfsInput.java b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/uploads/UploadFromHdfsInput.java index c755c02..60955a6 100644 --- a/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/uploads/UploadFromHdfsInput.java +++ b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/uploads/UploadFromHdfsInput.java @@ -18,6 +18,8 @@ package org.apache.ambari.view.hive20.resources.uploads; +import org.apache.ambari.view.hive20.internal.dto.ColumnInfo; + import java.io.Serializable; import java.util.List; @@ -27,7 +29,7 @@ public class UploadFromHdfsInput implements Serializable{ private String hdfsPath; private String tableName; private String databaseName; - private List<ColumnDescriptionImpl> header; + private List<ColumnInfo> header; private boolean containsEndlines; private String csvDelimiter; @@ -41,11 +43,11 @@ public class UploadFromHdfsInput implements Serializable{ return csvDelimiter; } - public List<ColumnDescriptionImpl> getHeader() { + public List<ColumnInfo> getHeader() { return header; } - public void setHeader(List<ColumnDescriptionImpl> header) { + public void setHeader(List<ColumnInfo> header) { this.header = header; } http://git-wip-us.apache.org/repos/asf/ambari/blob/d3451fb3/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/uploads/UploadService.java ---------------------------------------------------------------------- diff --git a/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/uploads/UploadService.java b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/uploads/UploadService.java index 835626d..3164da0 100644 --- a/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/uploads/UploadService.java +++ b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/uploads/UploadService.java @@ -18,16 +18,22 @@ package org.apache.ambari.view.hive20.resources.uploads; +import com.google.common.base.Optional; import com.sun.jersey.core.header.FormDataContentDisposition; import com.sun.jersey.multipart.FormDataParam; import org.apache.ambari.view.ViewContext; -import org.apache.ambari.view.hive.resources.uploads.CSVParams; import org.apache.ambari.view.hive20.BaseService; import org.apache.ambari.view.hive20.ConnectionFactory; import org.apache.ambari.view.hive20.ConnectionSystem; import org.apache.ambari.view.hive20.client.DDLDelegator; import org.apache.ambari.view.hive20.client.DDLDelegatorImpl; import org.apache.ambari.view.hive20.client.Row; +import org.apache.ambari.view.hive20.exceptions.ServiceException; +import org.apache.ambari.view.hive20.internal.dto.ColumnInfo; +import org.apache.ambari.view.hive20.internal.dto.TableMeta; +import org.apache.ambari.view.hive20.internal.query.generators.CreateTableQueryGenerator; +import org.apache.ambari.view.hive20.internal.query.generators.DeleteTableQueryGenerator; +import org.apache.ambari.view.hive20.internal.query.generators.InsertFromQueryGenerator; import org.apache.ambari.view.hive20.resources.jobs.viewJobs.Job; import org.apache.ambari.view.hive20.resources.jobs.viewJobs.JobController; import org.apache.ambari.view.hive20.resources.jobs.viewJobs.JobImpl; @@ -37,8 +43,6 @@ import org.apache.ambari.view.hive20.resources.uploads.parsers.ParseOptions; import org.apache.ambari.view.hive20.resources.uploads.parsers.PreviewData; import org.apache.ambari.view.hive20.resources.uploads.query.DeleteQueryInput; import org.apache.ambari.view.hive20.resources.uploads.query.InsertFromQueryInput; -import org.apache.ambari.view.hive20.resources.uploads.query.QueryGenerator; -import org.apache.ambari.view.hive20.resources.uploads.query.TableInfo; import org.apache.ambari.view.hive20.utils.ServiceFormattedException; import org.apache.ambari.view.hive20.utils.SharedObjectsFactory; import org.apache.ambari.view.utils.ambari.AmbariApi; @@ -52,11 +56,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.inject.Inject; -import javax.ws.rs.Consumes; -import javax.ws.rs.POST; -import javax.ws.rs.Path; -import javax.ws.rs.Produces; -import javax.ws.rs.WebApplicationException; +import javax.ws.rs.*; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import java.io.File; @@ -163,7 +163,7 @@ public class UploadService extends BaseService { } } - @POST + @PUT @Path("/preview") @Consumes(MediaType.MULTIPART_FORM_DATA) public Response uploadForPreview( @@ -225,29 +225,6 @@ public class UploadService extends BaseService { } - @Path("/createTable") - @POST - @Consumes(MediaType.APPLICATION_JSON) - @Produces(MediaType.APPLICATION_JSON) - public Response createTable(TableInput tableInput) { - try { - tableInput.validate(); - String databaseName = tableInput.getDatabaseName(); - String tableCreationQuery = generateCreateQuery(tableInput); - LOG.info("tableCreationQuery : {}", tableCreationQuery); - - Job job = createJob(tableCreationQuery, databaseName); - LOG.info("job created for table creation {}", job); - return Response.ok(job).build(); - } catch (WebApplicationException e) { - LOG.error(getErrorMessage(e), e); - throw e; - } catch (Throwable e) { - LOG.error(e.getMessage(), e); - throw new ServiceFormattedException(e); - } - } - @Path("/uploadFromHDFS") @POST @Consumes(MediaType.APPLICATION_JSON) @@ -281,7 +258,7 @@ public class UploadService extends BaseService { } @Path("/upload") - @POST + @PUT @Consumes(MediaType.MULTIPART_FORM_DATA) @Produces(MediaType.APPLICATION_JSON) public Response uploadFile( @@ -301,7 +278,7 @@ public class UploadService extends BaseService { try { CSVParams csvParams = getCsvParams(csvDelimiter, csvQuote, csvEscape); ObjectMapper mapper = new ObjectMapper(); - List<ColumnDescriptionImpl> columnList = mapper.readValue(header, new TypeReference<List<ColumnDescriptionImpl>>(){}); + List<ColumnInfo> columnList = mapper.readValue(header, new TypeReference<List<ColumnInfo>>(){}); String path = uploadFileFromStream(uploadedInputStream, isFirstRowHeader, inputFileType, tableName, databaseName, columnList, containsEndlines, csvParams); JSONObject jo = new JSONObject(); @@ -325,7 +302,9 @@ public class UploadService extends BaseService { String insertQuery = generateInsertFromQuery(input); LOG.info("insertQuery : {}", insertQuery); - Job job = createJob(insertQuery, "default"); + Job job = createJob(insertQuery, input.getFromDatabase(), "Insert from " + + input.getFromDatabase() + "." + input.getFromTable() + " to " + + input.getToDatabase() + "." + input.getToTable()); LOG.info("Job created for insert from temp table : {}", job); return Response.ok(job).build(); } catch (WebApplicationException e) { @@ -337,27 +316,6 @@ public class UploadService extends BaseService { } } - @Path("/deleteTable") - @POST - @Consumes(MediaType.APPLICATION_JSON) - @Produces(MediaType.APPLICATION_JSON) - public Response deleteTable(DeleteQueryInput input) { - try { - String deleteQuery = generateDeleteQuery(input); - LOG.info("deleteQuery : {}", deleteQuery); - - Job job = createJob(deleteQuery, "default"); - LOG.info("Job created for delete temp table : {} ", job); - return Response.ok(job).build(); - } catch (WebApplicationException e) { - LOG.error(getErrorMessage(e), e); - throw e; - } catch (Throwable e) { - LOG.error(e.getMessage(), e); - throw new ServiceFormattedException(e); - } - } - private String uploadIntoTable(Reader reader, String databaseName, String tempTableName) { try { String fullPath = getHiveMetaStoreLocation(databaseName, tempTableName); @@ -388,23 +346,42 @@ public class UploadService extends BaseService { return ambariApi; } - private String generateCreateQuery(TableInfo ti) { - return new QueryGenerator().generateCreateQuery(ti); + private String generateCreateQuery(TableMeta ti) throws ServiceException { + CreateTableQueryGenerator createTableQueryGenerator = new CreateTableQueryGenerator(ti); + Optional<String> query = createTableQueryGenerator.getQuery(); + if(query.isPresent()){ + return query.get(); + }else{ + throw new ServiceException("Failed to generate create table query."); + } } - private String generateInsertFromQuery(InsertFromQueryInput input) { - return new QueryGenerator().generateInsertFromQuery(input); + private String generateInsertFromQuery(InsertFromQueryInput input) throws ServiceException { + InsertFromQueryGenerator queryGenerator = new InsertFromQueryGenerator(input); + Optional<String> query = queryGenerator.getQuery(); + if(query.isPresent()){ + return query.get(); + }else{ + throw new ServiceException("Failed to generate Insert From Query."); + } } - private String generateDeleteQuery(DeleteQueryInput deleteQueryInput) { - return new QueryGenerator().generateDropTableQuery(deleteQueryInput); + private String generateDeleteQuery(DeleteQueryInput deleteQueryInput) throws ServiceException { + DeleteTableQueryGenerator deleteQuery = new DeleteTableQueryGenerator(deleteQueryInput.getDatabase(), deleteQueryInput.getTable()); + Optional<String> query = deleteQuery.getQuery(); + if(query.isPresent()){ + return query.get(); + }else{ + throw new ServiceException("Failed to generate delete table query."); + } } - private Job createJob(String query, String databaseName) throws Throwable{ + private Job createJob(String query, String databaseName, String jobTitle) throws Throwable{ Map jobInfo = new HashMap<>(); - jobInfo.put("title", "Internal Job"); + jobInfo.put("title", jobTitle); jobInfo.put("forcedContent", query); jobInfo.put("dataBase", databaseName); + jobInfo.put("referrer", JobImpl.REFERRER.INTERNAL.name()); Job job = new JobImpl(jobInfo); LOG.info("creating job : {}", job); @@ -523,7 +500,7 @@ public class UploadService extends BaseService { String inputFileType, // the format of the file uploaded. CSV/JSON etc. String tableName, String databaseName, - List<ColumnDescriptionImpl> header, + List<ColumnInfo> header, boolean containsEndlines, CSVParams csvParams ) throws Exception { http://git-wip-us.apache.org/repos/asf/ambari/blob/d3451fb3/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/uploads/parsers/Parser.java ---------------------------------------------------------------------- diff --git a/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/uploads/parsers/Parser.java b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/uploads/parsers/Parser.java index a012463..5586f8c 100644 --- a/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/uploads/parsers/Parser.java +++ b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/uploads/parsers/Parser.java @@ -20,6 +20,7 @@ package org.apache.ambari.view.hive20.resources.uploads.parsers; import org.apache.ambari.view.hive20.client.ColumnDescription; import org.apache.ambari.view.hive20.client.Row; +import org.apache.ambari.view.hive20.internal.dto.ColumnInfo; import org.apache.ambari.view.hive20.resources.uploads.ColumnDescriptionImpl; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -74,7 +75,7 @@ public abstract class Parser implements IParser { LOG.info("generating preview for : {}", this.parseOptions ); ArrayList<Row> previewRows; - List<ColumnDescription> header; + List<ColumnInfo> header; try { numberOfPreviewRows = (Integer) parseOptions.getOption(ParseOptions.OPTIONS_NUMBER_OF_PREVIEW_ROWS); @@ -137,11 +138,11 @@ public abstract class Parser implements IParser { // find data types. header = generateHeader(headerRow,previewRows,numOfCols); - return new PreviewData(header,previewRows); + return new PreviewData(header, previewRows); } - private List<ColumnDescription> generateHeader(Row headerRow,List<Row> previewRows, int numOfCols) { - List<ColumnDescription> header = new ArrayList<>(); + private List<ColumnInfo> generateHeader(Row headerRow, List<Row> previewRows, int numOfCols) { + List<ColumnInfo> header = new ArrayList<>(); for (int colNum = 0; colNum < numOfCols; colNum++) { ColumnDescription.DataTypes type = getLikelyDataType(previewRows,colNum); @@ -151,7 +152,7 @@ public abstract class Parser implements IParser { if (null != headerRow) colName = (String) headerRow.getRow()[colNum]; - ColumnDescription cd = new ColumnDescriptionImpl(colName, type.toString(), colNum); + ColumnInfo cd = new ColumnInfo(colName, type.toString()); header.add(cd); } http://git-wip-us.apache.org/repos/asf/ambari/blob/d3451fb3/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/uploads/parsers/PreviewData.java ---------------------------------------------------------------------- diff --git a/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/uploads/parsers/PreviewData.java b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/uploads/parsers/PreviewData.java index 50af529..dd31457 100644 --- a/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/uploads/parsers/PreviewData.java +++ b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/uploads/parsers/PreviewData.java @@ -20,6 +20,7 @@ package org.apache.ambari.view.hive20.resources.uploads.parsers; import org.apache.ambari.view.hive20.client.ColumnDescription; import org.apache.ambari.view.hive20.client.Row; +import org.apache.ambari.view.hive20.internal.dto.ColumnInfo; import java.util.List; @@ -27,22 +28,22 @@ import java.util.List; * Encapsulating preview data from parser. */ public class PreviewData { - private List<ColumnDescription> header; + private List<ColumnInfo> header; private List<Row> previewRows; public PreviewData() { } - public PreviewData(List<ColumnDescription> header, List<Row> previewRows) { + public PreviewData(List<ColumnInfo> header, List<Row> previewRows) { this.header = header; this.previewRows = previewRows; } - public List<ColumnDescription> getHeader() { + public List<ColumnInfo> getHeader() { return header; } - public void setHeader(List<ColumnDescription> header) { + public void setHeader(List<ColumnInfo> header) { this.header = header; } http://git-wip-us.apache.org/repos/asf/ambari/blob/d3451fb3/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/uploads/query/InsertFromQueryInput.java ---------------------------------------------------------------------- diff --git a/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/uploads/query/InsertFromQueryInput.java b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/uploads/query/InsertFromQueryInput.java index 027baff..4ff61b4 100644 --- a/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/uploads/query/InsertFromQueryInput.java +++ b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/uploads/query/InsertFromQueryInput.java @@ -18,6 +18,7 @@ package org.apache.ambari.view.hive20.resources.uploads.query; +import org.apache.ambari.view.hive20.internal.dto.ColumnInfo; import org.apache.ambari.view.hive20.resources.uploads.ColumnDescriptionImpl; import java.util.List; @@ -27,13 +28,14 @@ public class InsertFromQueryInput { private String fromTable; private String toDatabase; private String toTable; - private List<ColumnDescriptionImpl> header; + private List<ColumnInfo> header; private Boolean unhexInsert = Boolean.FALSE; public InsertFromQueryInput() { } - public InsertFromQueryInput(String fromDatabase, String fromTable, String toDatabase, String toTable, List<ColumnDescriptionImpl> header, Boolean unhexInsert) { + public InsertFromQueryInput(String fromDatabase, String fromTable, String toDatabase, String toTable, + List<ColumnInfo> header, Boolean unhexInsert) { this.fromDatabase = fromDatabase; this.fromTable = fromTable; this.toDatabase = toDatabase; @@ -42,11 +44,11 @@ public class InsertFromQueryInput { this.unhexInsert = unhexInsert; } - public List<ColumnDescriptionImpl> getHeader() { + public List<ColumnInfo> getHeader() { return header; } - public void setHeader(List<ColumnDescriptionImpl> header) { + public void setHeader(List<ColumnInfo> header) { this.header = header; } http://git-wip-us.apache.org/repos/asf/ambari/blob/d3451fb3/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/uploads/query/QueryGenerator.java ---------------------------------------------------------------------- diff --git a/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/uploads/query/QueryGenerator.java b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/uploads/query/QueryGenerator.java deleted file mode 100644 index dda178d..0000000 --- a/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/uploads/query/QueryGenerator.java +++ /dev/null @@ -1,143 +0,0 @@ -/** - * 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 - * <p/> - * http://www.apache.org/licenses/LICENSE-2.0 - * <p/> - * 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.ambari.view.hive20.resources.uploads.query; - -import org.apache.ambari.view.hive.resources.uploads.query.RowFormat; -import org.apache.ambari.view.hive20.client.ColumnDescription; -import org.apache.ambari.view.hive20.resources.uploads.ColumnDescriptionImpl; -import org.apache.ambari.view.hive20.resources.uploads.HiveFileType; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.Collections; -import java.util.Comparator; -import java.util.List; - -/** - * generates the sql query from given data - */ -public class QueryGenerator { - protected final static Logger LOG = - LoggerFactory.getLogger(QueryGenerator.class); - - public String generateCreateQuery(TableInfo tableInfo) { - String tableName = tableInfo.getTableName(); - List<ColumnDescriptionImpl> cdList = tableInfo.getHeader(); - - StringBuilder query = new StringBuilder(); - query.append("CREATE TABLE ").append(tableName).append(" ("); - Collections.sort(cdList, new Comparator<ColumnDescription>() { - @Override - public int compare(ColumnDescription o1, ColumnDescription o2) { - return o1.getPosition() - o2.getPosition(); - } - }); - - boolean first = true; - for (ColumnDescriptionImpl cd : cdList) { - if (first) { - first = false; - } else { - query.append(", "); - } - - query.append(cd.getName()).append(" ").append(cd.getType()); - if (cd.getPrecision() != null) { - query.append("(").append(cd.getPrecision()); - if (cd.getScale() != null) { - query.append(",").append(cd.getScale()); - } - query.append(")"); - } - - } - - query.append(")"); - - if(tableInfo.getHiveFileType().equals(HiveFileType.TEXTFILE)) { - query.append(getRowFormatQuery(tableInfo.getRowFormat())); - } - query.append(" STORED AS ").append(tableInfo.getHiveFileType().toString()); - String queryString = query.append(";").toString(); - LOG.info("Query : {}", queryString); - return queryString; - } - - private String getRowFormatQuery(RowFormat rowFormat) { - StringBuilder sb = new StringBuilder(); - if(rowFormat != null) { - sb.append(" ROW FORMAT DELIMITED"); - if(rowFormat.getFieldsTerminatedBy() != null ){ - sb.append(" FIELDS TERMINATED BY '").append(rowFormat.getFieldsTerminatedBy()).append('\''); - } - if(rowFormat.getEscapedBy() != null){ - String escape = String.valueOf(rowFormat.getEscapedBy()); - if(rowFormat.getEscapedBy() == '\\'){ - escape = escape + '\\'; // special handling of slash as its escape char for strings in hive as well. - } - sb.append(" ESCAPED BY '").append(escape).append('\''); - } - } - - return sb.toString(); - } - - public String generateInsertFromQuery(InsertFromQueryInput ifqi) { - StringBuilder insertQuery = new StringBuilder("INSERT INTO TABLE ").append(ifqi.getToDatabase()).append(".") - .append(ifqi.getToTable()).append(" SELECT "); - - boolean first = true; - for(ColumnDescriptionImpl column : ifqi.getHeader()){ - String type = column.getType(); - boolean unhex = ifqi.getUnhexInsert() && ( - ColumnDescription.DataTypes.STRING.toString().equals(type) - || ColumnDescription.DataTypes.VARCHAR.toString().equals(type) - || ColumnDescription.DataTypes.CHAR.toString().equals(type) - ); - - if(!first){ - insertQuery.append(", "); - } - - if(unhex) { - insertQuery.append("UNHEX("); - } - - insertQuery.append(column.getName()); - - if(unhex) { - insertQuery.append(")"); - } - - first = false; - } - - insertQuery.append(" FROM ").append(ifqi.getFromDatabase()).append(".").append(ifqi.getFromTable()).append(";"); - String query = insertQuery.toString(); - LOG.info("Insert Query : {}", query); - return query; - } - - public String generateDropTableQuery(DeleteQueryInput deleteQueryInput) { - String dropQuery = new StringBuilder("DROP TABLE ").append(deleteQueryInput.getDatabase()) - .append(".").append(deleteQueryInput.getTable()).append(";").toString(); - LOG.info("Drop Query : {}", dropQuery); - return dropQuery; - } -} http://git-wip-us.apache.org/repos/asf/ambari/blob/d3451fb3/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/uploads/query/RowFormat.java ---------------------------------------------------------------------- diff --git a/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/uploads/query/RowFormat.java b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/uploads/query/RowFormat.java deleted file mode 100644 index 4c1cb2b..0000000 --- a/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/uploads/query/RowFormat.java +++ /dev/null @@ -1,57 +0,0 @@ -/** - * 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 - * <p/> - * http://www.apache.org/licenses/LICENSE-2.0 - * <p/> - * 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.ambari.view.hive.resources.uploads.query; - -public class RowFormat { - private Character fieldsTerminatedBy; - private Character escapedBy; - - private RowFormat() { - } - - public RowFormat(Character fieldsTerminatedBy, Character escapedBy) { - this.fieldsTerminatedBy = fieldsTerminatedBy; - this.escapedBy = escapedBy; - } - - public Character getFieldsTerminatedBy() { - return fieldsTerminatedBy; - } - - public void setFieldsTerminatedBy(Character fieldsTerminatedBy) { - this.fieldsTerminatedBy = fieldsTerminatedBy; - } - - public Character getEscapedBy() { - return escapedBy; - } - - public void setEscapedBy(Character escapedBy) { - this.escapedBy = escapedBy; - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder("RowFormat{ fieldsTerminatedBy='"); - sb.append(fieldsTerminatedBy).append( '\'').append(", escapedBy='") - .append(escapedBy).append("\'}"); - - return sb.toString(); - } -} http://git-wip-us.apache.org/repos/asf/ambari/blob/d3451fb3/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/uploads/query/TableInfo.java ---------------------------------------------------------------------- diff --git a/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/uploads/query/TableInfo.java b/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/uploads/query/TableInfo.java deleted file mode 100644 index bb39271..0000000 --- a/contrib/views/hive20/src/main/java/org/apache/ambari/view/hive20/resources/uploads/query/TableInfo.java +++ /dev/null @@ -1,97 +0,0 @@ -/** - * 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 - * <p/> - * http://www.apache.org/licenses/LICENSE-2.0 - * <p/> - * 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.ambari.view.hive20.resources.uploads.query; - -import org.apache.ambari.view.hive.resources.uploads.query.RowFormat; -import org.apache.ambari.view.hive20.resources.uploads.ColumnDescriptionImpl; -import org.apache.ambari.view.hive20.resources.uploads.HiveFileType; - -import java.io.Serializable; -import java.util.List; - -/** - * used as input in Query generation - */ -public class TableInfo implements Serializable{ - private String tableName; - private String databaseName; - private List<ColumnDescriptionImpl> header; - private HiveFileType hiveFileType; - - private RowFormat rowFormat; - - public String getTableName() { - return tableName; - } - - public void setTableName(String tableName) { - this.tableName = tableName; - } - - public String getDatabaseName() { - return databaseName; - } - - public void setDatabaseName(String databaseName) { - this.databaseName = databaseName; - } - - public List<ColumnDescriptionImpl> getHeader() { - return header; - } - - public void setHeader(List<ColumnDescriptionImpl> header) { - this.header = header; - } - - public HiveFileType getHiveFileType() { - return hiveFileType; - } - - public void setHiveFileType(HiveFileType hiveFileType) { - this.hiveFileType = hiveFileType; - } - - public RowFormat getRowFormat() { - return rowFormat; - } - - public void setRowFormat(RowFormat rowFormat) { - this.rowFormat = rowFormat; - } - - public TableInfo(String databaseName, String tableName, List<ColumnDescriptionImpl> header, HiveFileType hiveFileType, RowFormat rowFormat) { - this.databaseName = databaseName; - this.tableName = tableName; - this.header = header; - this.hiveFileType = hiveFileType; - this.rowFormat = rowFormat; - } - - public TableInfo(TableInfo tableInfo) { - this.tableName = tableInfo.tableName; - this.databaseName = tableInfo.databaseName; - this.header = tableInfo.header; - this.hiveFileType = tableInfo.hiveFileType; - this.rowFormat = tableInfo.rowFormat; - } - - public TableInfo() { - } -} http://git-wip-us.apache.org/repos/asf/ambari/blob/d3451fb3/contrib/views/hive20/src/main/resources/ui/app/adapters/file-uploader.js ---------------------------------------------------------------------- diff --git a/contrib/views/hive20/src/main/resources/ui/app/adapters/file-uploader.js b/contrib/views/hive20/src/main/resources/ui/app/adapters/file-uploader.js new file mode 100644 index 0000000..34f52b1 --- /dev/null +++ b/contrib/views/hive20/src/main/resources/ui/app/adapters/file-uploader.js @@ -0,0 +1,28 @@ +/** + * 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. + */ + +import EmberUploader from 'ember-uploader'; + +export default EmberUploader.Uploader.extend({ + method: 'PUT', + ajaxSettings: { + headers: { + "X-Requested-By":"ambari" + } + } +}); http://git-wip-us.apache.org/repos/asf/ambari/blob/d3451fb3/contrib/views/hive20/src/main/resources/ui/app/adapters/upload-table.js ---------------------------------------------------------------------- diff --git a/contrib/views/hive20/src/main/resources/ui/app/adapters/upload-table.js b/contrib/views/hive20/src/main/resources/ui/app/adapters/upload-table.js new file mode 100644 index 0000000..3bfe15b --- /dev/null +++ b/contrib/views/hive20/src/main/resources/ui/app/adapters/upload-table.js @@ -0,0 +1,93 @@ +/** + * 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. + */ + +import Ember from 'ember'; +import ApplicationAdapter from './application'; +import FileUploader from './file-uploader'; + +export default ApplicationAdapter.extend({ + tableOperations: Ember.inject.service(), + + buildURL: function(){ + return this._super(...arguments); + }, + + buildUploadURL: function (path) { + return this.buildURL() + "/upload/" + path; + }, + + uploadFiles: function (path, files, extras) { + var uploadUrl = this.buildUploadURL(path); + + console.log("uplaoder : uploadURL : ", uploadUrl, " extras : ", extras , "files : ", files); + + var hdrs = Ember.$.extend(true, {},this.get('headers')); + delete hdrs['Content-Type']; + var uploader = FileUploader.create({ + headers: hdrs, + url: uploadUrl + }); + + if (!Ember.isEmpty(files)) { + var promise = uploader.upload(files[0], extras); + return promise; + } + }, + + createTable: function (tableData) { + console.log("creating table with data :", tableData); + return this.doPost("createTable",tableData); + }, + + insertIntoTable: function(insertData){ + console.log("inserting into table with data : ", insertData); + return this.doPost("insertIntoTable",insertData); + }, + + deleteTable: function(deleteData){ + console.log("delete table with info : ", deleteData); + return this.get('tableOperations').deleteTable(deleteData.database, deleteData.table); + }, + + doPost : function(path,inputData){ + var self = this; + return new Ember.RSVP.Promise(function(resolve,reject){ + Ember.$.ajax({ + url : self.buildUploadURL(path), + type : 'post', + data: JSON.stringify(inputData), + headers: self.get('headers'), + dataType : 'json' + }).done(function(data) { + resolve(data); + }).fail(function(error) { + reject(error); + }); + }); + }, + + previewFromHDFS : function(previewFromHdfsData){ + console.log("preview from hdfs with info : ", previewFromHdfsData); + return this.doPost("previewFromHdfs",previewFromHdfsData) + }, + + uploadFromHDFS : function(uploadFromHdfsData){ + console.log("upload from hdfs with info : ", uploadFromHdfsData); + return this.doPost("uploadFromHDFS",uploadFromHdfsData) + } +}); http://git-wip-us.apache.org/repos/asf/ambari/blob/d3451fb3/contrib/views/hive20/src/main/resources/ui/app/components/csv-format-params.js ---------------------------------------------------------------------- diff --git a/contrib/views/hive20/src/main/resources/ui/app/components/csv-format-params.js b/contrib/views/hive20/src/main/resources/ui/app/components/csv-format-params.js new file mode 100644 index 0000000..7a14ba8 --- /dev/null +++ b/contrib/views/hive20/src/main/resources/ui/app/components/csv-format-params.js @@ -0,0 +1,77 @@ +/** + * 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. + */ + +import Ember from 'ember'; +import Helpers from '../configs/helpers'; + +export default Ember.Component.extend({ + showCSVFormatInput: true, + DEFAULT_CSV_DELIMITER: ',', + DEFAULT_CSV_QUOTE: '"', + DEFAULT_CSV_ESCAPE: '\\', + DEFAULT_FILE_TYPE: 'CSV', + isFirstRowHeader: false, // is first row header + csvParams: Ember.Object.create(), + inputFileTypes: Ember.computed(function () { + return Helpers.getUploadFileTypes(); + }), + inputFileTypeCSV : Ember.computed.equal('fileFormatInfo.inputFileType.id',"CSV"), + + terminationChars: Ember.computed(function () { + return Helpers.getAllTerminationCharacters(); + }), + + init: function(){ + this._super(...arguments); + this.set('fileFormatInfo.csvParams.csvDelimiter', this.get("terminationChars").findBy( "name", this.get('DEFAULT_CSV_DELIMITER') )); + this.set('fileFormatInfo.csvParams.csvQuote', this.get("terminationChars").findBy( "name", this.get('DEFAULT_CSV_QUOTE'))); + this.set('fileFormatInfo.csvParams.csvEscape', this.get("terminationChars").findBy( "name", this.get('DEFAULT_CSV_ESCAPE'))); + this.set("fileFormatInfo.inputFileType", this.get("inputFileTypes").findBy("name"), this.get('DEFAULT_FILE_TYPE')); + }, + + actions: { + toggleCSVFormat: function () { + console.log("inside toggleCSVFormat"); + this.toggleProperty('showCSVFormatInput'); + }, + clearColumnDelimter: function(){ + this.set('fileFormatInfo.csvParams.csvDelimiter'); + }, + csvDelimiterSelected: function(terminator){ + this.set('fileFormatInfo.csvParams.csvDelimiter', terminator); + }, + csvEscapeSelected: function(terminator){ + this.set('fileFormatInfo.csvParams.csvEscape', terminator); + }, + clearEscapeCharacter: function(){ + this.set('fileFormatInfo.csvParams.csvEscape'); + }, + csvQuoteSelected: function(terminator){ + this.set('fileFormatInfo.csvParams.csvQuote', terminator); + }, + clearCsvQuote: function(){ + this.set('fileFormatInfo.csvParams.csvQuote'); + }, + inputFileTypeSelected: function(fileType){ + this.set("fileFormatInfo.inputFileType", fileType); + }, + clearInputFileType: function(){ + this.set("fileFormatInfo.inputFileType"); + }, + } +}); http://git-wip-us.apache.org/repos/asf/ambari/blob/d3451fb3/contrib/views/hive20/src/main/resources/ui/app/components/radio-button.js ---------------------------------------------------------------------- diff --git a/contrib/views/hive20/src/main/resources/ui/app/components/radio-button.js b/contrib/views/hive20/src/main/resources/ui/app/components/radio-button.js new file mode 100644 index 0000000..066168c --- /dev/null +++ b/contrib/views/hive20/src/main/resources/ui/app/components/radio-button.js @@ -0,0 +1,40 @@ +/** + * 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. + */ + +import Ember from 'ember'; + +export default Ember.Component.extend({ + tagName: 'input', + type: 'radio', + attributeBindings: ['type', 'htmlChecked:checked', 'value', 'name', 'disabled'], + + htmlChecked: function() { + return this.get('value') === this.get('checked'); + }.property('value', 'checked'), + + change: function() { + console.log("value changed : ", this.get('value')); + this.set('checked', this.get('value')); + }, + + _updateElementValue: function() { + Ember.run.next(this, function() { + this.$().prop('checked', this.get('htmlChecked')); + }); + }.observes('htmlChecked') +}); http://git-wip-us.apache.org/repos/asf/ambari/blob/d3451fb3/contrib/views/hive20/src/main/resources/ui/app/components/simple-table.js ---------------------------------------------------------------------- diff --git a/contrib/views/hive20/src/main/resources/ui/app/components/simple-table.js b/contrib/views/hive20/src/main/resources/ui/app/components/simple-table.js new file mode 100644 index 0000000..8828275 --- /dev/null +++ b/contrib/views/hive20/src/main/resources/ui/app/components/simple-table.js @@ -0,0 +1,22 @@ +/** + * 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. + */ + +import Ember from 'ember'; + +export default Ember.Component.extend({ +}); http://git-wip-us.apache.org/repos/asf/ambari/blob/d3451fb3/contrib/views/hive20/src/main/resources/ui/app/components/upload-table-source.js ---------------------------------------------------------------------- diff --git a/contrib/views/hive20/src/main/resources/ui/app/components/upload-table-source.js b/contrib/views/hive20/src/main/resources/ui/app/components/upload-table-source.js new file mode 100644 index 0000000..36da77d --- /dev/null +++ b/contrib/views/hive20/src/main/resources/ui/app/components/upload-table-source.js @@ -0,0 +1,48 @@ +/** + * 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. + */ + +import Ember from 'ember'; + +export default Ember.Component.extend({ + showFileSourceInput: true, + showHdfsLocationInput: Ember.computed.equal("fileInfo.uploadSource", "hdfs"), + showLocalLocationInput: Ember.computed.equal("fileInfo.uploadSource", "local"), + isLocalUpload: Ember.computed.equal("fileInfo.uploadSource", "local"), + + actions: { + toggleFileSource: function(){ + this.toggleProperty("showFileSourceInput"); + }, + closeHdfsModal: function() { + this.set('showDirectoryViewer', false); + }, + hdfsPathSelected: function(path) { + this.set('fileInfo.hdfsPath', path); + this.set('showDirectoryViewer', false); + }, + + toggleDirectoryViewer: function() { + this.set('showDirectoryViewer', true); + }, + onFileChanged: function(file){ + this.get("fileInfo.files")[0] = file; + console.log("setting fifilesUploadedles as : ", this.get("fileInfo.files")); + this.sendAction("onFileChanged"); + }, + } +}); http://git-wip-us.apache.org/repos/asf/ambari/blob/d3451fb3/contrib/views/hive20/src/main/resources/ui/app/components/upload-table.js ---------------------------------------------------------------------- diff --git a/contrib/views/hive20/src/main/resources/ui/app/components/upload-table.js b/contrib/views/hive20/src/main/resources/ui/app/components/upload-table.js new file mode 100644 index 0000000..29e9891 --- /dev/null +++ b/contrib/views/hive20/src/main/resources/ui/app/components/upload-table.js @@ -0,0 +1,60 @@ +/** + * 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. + */ + +import Ember from 'ember'; + +export default Ember.Component.extend({ + showPreview: false, + fileFormatInfo: Ember.Object.create({ + csvParams: Ember.Object.create(), + inputFileType: null, + }), + fileInfo: Ember.Object.create({ + files: Ember.A(), + hdfsPath: null, + uploadSource: null, + }), + tableMeta: Ember.Object.create(), + actions: { + onFileChanged: function () { + console.log("inside files changed"); + console.log("fileFormatInfo : ", this.get("fileFormatInfo")); + console.log("fileInfo : ", this.get("fileInfo")); + console.log("tableInfo : ", this.get("tableInfo")); + this.send("preview"); + }, + preview: function () { + let sourceObject = Ember.Object.create(); + sourceObject.set("fileFormatInfo", this.get("fileFormatInfo")); + sourceObject.set("fileInfo", this.get("fileInfo")); + this.sendAction("preview", sourceObject); + this.set("showPreview", true); + }, + toggleShowPreview: function(){ + this.toggleProperty("showPreview"); + }, + createAndUpload: function(tableMeta){ + this.set("tableMeta", tableMeta); + let tableData = Ember.Object.create(); + tableData.set("fileFormatInfo", this.get("fileFormatInfo")); + tableData.set("fileInfo", this.get("fileInfo")); + tableData.set("tableMeta", this.get("tableMeta")); + this.sendAction("createAndUpload", tableData); + } + } +}); http://git-wip-us.apache.org/repos/asf/ambari/blob/d3451fb3/contrib/views/hive20/src/main/resources/ui/app/components/validated-text-field.js ---------------------------------------------------------------------- diff --git a/contrib/views/hive20/src/main/resources/ui/app/components/validated-text-field.js b/contrib/views/hive20/src/main/resources/ui/app/components/validated-text-field.js new file mode 100644 index 0000000..2379a15 --- /dev/null +++ b/contrib/views/hive20/src/main/resources/ui/app/components/validated-text-field.js @@ -0,0 +1,62 @@ +/** + * 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. + */ + + +import Ember from 'ember'; + +/** Example : + * {{#validated-text-field + * inputValue=bindedTextValue invalidClass='form-control red-border' validClass='form-control' regex="^[a-z]+$" + * allowEmpty=false tooltip="Enter valid word" errorMessage="Please enter valid word" placeholder="Enter Word"}} + * {{/validated-text-field}} + */ +export default Ember.Component.extend({ + classNameBindings: ['tagClassName'], + tagClassName : false, // set it to non false value if you want a specific class to be assigned + allowEmpty: true, + valid: true, + setValid: function () { + this.set("valid", true); + this.set("inputClass", this.get("validClass")); + this.set("message", this.get("tooltip")); + }, + setInvalid: function () { + this.set("valid", false); + this.set("inputClass", this.get("invalidClass")); + this.set("message", this.get("errorMessage")); + }, + onChangeInputValue: function () { + var regStr = this.get("regex"); + var regExp = new RegExp(regStr, "g"); + if (this.get("inputValue")) { + var arr = this.get("inputValue").match(regExp); + if (arr != null && arr.length == 1) { + this.setValid(); + } + else { + this.setInvalid(); + } + } else { + if (this.get("allowEmpty")) { + this.setValid(); + } else { + this.setInvalid(); + } + } + }.observes("inputValue").on('init') +}); http://git-wip-us.apache.org/repos/asf/ambari/blob/d3451fb3/contrib/views/hive20/src/main/resources/ui/app/configs/helpers.js ---------------------------------------------------------------------- diff --git a/contrib/views/hive20/src/main/resources/ui/app/configs/helpers.js b/contrib/views/hive20/src/main/resources/ui/app/configs/helpers.js index 025caa6..ecefe55 100644 --- a/contrib/views/hive20/src/main/resources/ui/app/configs/helpers.js +++ b/contrib/views/hive20/src/main/resources/ui/app/configs/helpers.js @@ -142,10 +142,22 @@ export default Ember.Object.create({ */ getAllTerminationCharacters() { let arr = Ember.copy(nonPrintableChars); - for(let i=33; i < 127; i++) { + for (let i = 33; i < 127; i++) { arr.pushObject({id: i.toString(), name: String.fromCodePoint(i)}); } return arr; + }, + + /** + * returns file types supported for upload-table feature. + */ + getUploadFileTypes() { + let arr = [ + {id: "CSV", name: "CSV"}, + {id: "JSON", name: "JSON"}, + {id: "XML", name: "XML"} + ]; + return Ember.copy(arr); } }); http://git-wip-us.apache.org/repos/asf/ambari/blob/d3451fb3/contrib/views/hive20/src/main/resources/ui/app/locales/en/translations.js ---------------------------------------------------------------------- diff --git a/contrib/views/hive20/src/main/resources/ui/app/locales/en/translations.js b/contrib/views/hive20/src/main/resources/ui/app/locales/en/translations.js new file mode 100644 index 0000000..b550dbe --- /dev/null +++ b/contrib/views/hive20/src/main/resources/ui/app/locales/en/translations.js @@ -0,0 +1,111 @@ +/** + * 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. + */ + +export default { + "hive": { + "ui": { + "fileSource": { + 'uploadFromLocal': "Upload from Local", + 'uploadFromHdfs': "Upload from HDFS", + 'selectFileType': "Select File Type", + 'fileType': "File type", + "selectHdfsLocation": "Select HDFS Directory", + "enterHdfsPathLabel": "Enter Hdfs Path", + "selectLocalFileLabel": "Select Local File", + }, + "csvFormatParams": { + 'columnDelimterField': "Field Delimiter", + 'columnDelimiterTooltip': "Delimiter for the column values. Default is comman (,).", + 'escapeCharacterField': "Escape Character", + 'escapeCharacterTooltip': "Escape character. Default is backslash (\).", + 'quoteCharacterTooltip': 'Quote character. Default is double quote (").', + 'quoteCharacterField': "Quote Character", + }, + "uploadTable": { + 'uploadProgress': "Upload Progress", + 'uploading': "Uploading..", + 'selectFromLocal': "Select from local", + 'hdfsPath': "HDFS Path", + 'selectDatabase': "Select a Database", + 'tableName': "Table name", + 'tableNameErrorMessage': "Only alphanumeric and underscore characters are allowed in table name.", + 'tableNameTooltip': "Enter valid (alphanumeric + underscore) table name.", + 'storedAs': "Stored as", + 'isFirstRowHeader': "Is first row header ?", + 'columnNameTooltip': "Enter valid (alphanumeric + underscore) column name.", + 'columnNameErrorMessage': "Only alphanumeric and underscore characters are allowed in column names.", + 'hdfsFieldTooltip': "Enter full HDFS path", + 'hdfsFieldPlaceholder': "Enter full HDFS path", + 'hdfsFieldErrorMessage': "Please enter complete path of hdfs file to upload.", + 'containsEndlines': "Contains endlines?", + 'fieldsTerminatedByField': "Fields Terminated By", + 'escapedByField': "Escape By", + 'escapedByTooltip': "Escaped By character for Hive table.", + 'fieldsTerminatedByTooltip': "Fields Terminated By character for Hive table.", + 'isFirstRowHeaderTooltip': "Check if the first row of CSV is a header.", + 'showPreview': "Preview" + } + }, + words :{ + temporary : "Temporary", + actual : "Actual", + database : "Database" + }, + errors: { + 'no.query': "No query to process.", + 'emptyDatabase': "Please select {{ database }}.", + 'emptyTableName': "Please enter {{ tableNameField }}.", + 'illegalTableName': "Illegal {{ tableNameField }} : '{{ tableName }}'", + 'emptyIsFirstRow': "{{isFirstRowHeaderField}} cannot be null.", + 'emptyHeaders': "Headers (containing column names) cannot be null.", + 'emptyColumnName': "Column name cannot be null.", + 'illegalColumnName': "Illegal column name : '{{columnName}}' in column number {{index}}", + 'emptyHdfsPath': "HdfsPath Name cannot be null or empty.", + 'illegalHdfPath': "Illegal hdfs path : {{hdfsPath}}" + }, + messages: { + 'generatingPreview': "Generating Preview.", + 'startingToCreateActualTable': "Creating Actual table", + 'waitingToCreateActualTable': "Waiting for creation of Actual table", + 'successfullyCreatedActualTable': "Successfully created Actual table.", + 'failedToCreateActualTable': "Failed to create Actual table.", + 'startingToCreateTemporaryTable': "Creating Temporary table.", + 'waitingToCreateTemporaryTable': "Waiting for creation of Temporary table.", + 'successfullyCreatedTemporaryTable': "Successfully created Temporary table.", + 'failedToCreateTemporaryTable': " Failed to create temporary table.", + 'deletingTable': "Deleting {{table}} table.", + 'succesfullyDeletedTable': "Successfully deleted {{ table}} table.", + 'failedToDeleteTable': "Failed to delete {{table}} table.", + 'startingToUploadFile': "Uploading file.", + 'waitingToUploadFile': "Waiting for uploading file.", + 'successfullyUploadedFile': "Successfully uploaded file.", + 'failedToUploadFile': "Failed to upload file.", + 'startingToInsertRows': "Inserting rows from temporary table to actual table.", + 'waitingToInsertRows': "Waiting for insertion of rows from temporary table to actual table.", + 'successfullyInsertedRows': "Successfully inserted rows from temporary table to actual table.", + 'failedToInsertRows': "Failed to insert rows from temporary table to actual table.", + 'startingToDeleteTemporaryTable': "Deleting temporary table.", + 'waitingToDeleteTemporaryTable': "Waiting for deletion of temporary table.", + 'successfullyDeletedTemporaryTable': "Successfully deleted temporary table", + 'manuallyDeleteTable': "You will have to manually delete the table {{databaseName}}.{{tableName}}", + 'uploadingFromHdfs': "Uploading file from HDFS ", + 'successfullyUploadedTableMessage': "Table {{tableName}} created in database {{databaseName}}", + 'successfullyUploadedTableHeader': "Uploaded Successfully" + }, + } +}; http://git-wip-us.apache.org/repos/asf/ambari/blob/d3451fb3/contrib/views/hive20/src/main/resources/ui/app/models/column.js ---------------------------------------------------------------------- diff --git a/contrib/views/hive20/src/main/resources/ui/app/models/column.js b/contrib/views/hive20/src/main/resources/ui/app/models/column.js index b1fa99c..1d9ccce 100644 --- a/contrib/views/hive20/src/main/resources/ui/app/models/column.js +++ b/contrib/views/hive20/src/main/resources/ui/app/models/column.js @@ -19,8 +19,7 @@ import Ember from 'ember'; import datatypes from '../configs/datatypes'; import Helper from '../configs/helpers'; - -export default Ember.Object.extend({ +let Column = Ember.Object.extend(Ember.Copyable,{ name: '', type: datatypes[0], precision: null, @@ -103,5 +102,23 @@ export default Ember.Object.extend({ } return this.get('errors.length') === 0; + }, + + copy: function(){ + return Column.create({ + name: this.get("name"), + type: this.get("type"), + precision: this.get("percision"), + scale: this.get("scale"), + isPartitioned: this.get("isPartitioned"), + isClustered: this.get("isClustered"), + comment: this.get("comment"), + + errors: this.get("errors").copy(), + editing: this.get("editing"), + }); } -}) + +}); + +export default Column; http://git-wip-us.apache.org/repos/asf/ambari/blob/d3451fb3/contrib/views/hive20/src/main/resources/ui/app/router.js ---------------------------------------------------------------------- diff --git a/contrib/views/hive20/src/main/resources/ui/app/router.js b/contrib/views/hive20/src/main/resources/ui/app/router.js index 34f1a66..52361ff 100644 --- a/contrib/views/hive20/src/main/resources/ui/app/router.js +++ b/contrib/views/hive20/src/main/resources/ui/app/router.js @@ -38,6 +38,7 @@ Router.map(function() { this.route('tables', {path: '/tables'}, function() { this.route('new-database'); this.route('new'); + this.route('upload-table'); this.route('table', {path: '/:name'}, function() { this.route('rename'); this.route('columns'); @@ -62,7 +63,6 @@ Router.map(function() { }); }); - }); export default Router; http://git-wip-us.apache.org/repos/asf/ambari/blob/d3451fb3/contrib/views/hive20/src/main/resources/ui/app/routes/databases/database/tables/new.js ---------------------------------------------------------------------- diff --git a/contrib/views/hive20/src/main/resources/ui/app/routes/databases/database/tables/new.js b/contrib/views/hive20/src/main/resources/ui/app/routes/databases/database/tables/new.js index 6dfdf29..c8ad239 100644 --- a/contrib/views/hive20/src/main/resources/ui/app/routes/databases/database/tables/new.js +++ b/contrib/views/hive20/src/main/resources/ui/app/routes/databases/database/tables/new.js @@ -27,42 +27,64 @@ export default Ember.Route.extend({ controller.set('tabs', Ember.copy(tabs)); }, + // function is used in sub-classes + /** + * @param settings + * @param shouldTransition : should transition to other route? + * @returns {Promise.<TResult>|*} + */ + createTable: function(settings, shouldTransition){ + this.controller.set('showCreateTableModal', true); + this.controller.set('createTableMessage', 'Submitting request to create table'); + let databaseModel = this.controllerFor('databases.database').get('model'); + return this.get('tableOperations').submitCreateTable(databaseModel.get('name'), settings) + .then((job) => { + console.log('Created job: ', job.get('id')); + this.controller.set('createTableMessage', 'Waiting for the table to be created'); + return this.get('tableOperations').waitForJobToComplete(job.get('id'), 5 * 1000) + .then((status) => { + this.controller.set('createTableMessage', "Successfully created table"); + Ember.run.later(() => { + this.controller.set('showCreateTableModal', false); + this.controller.set('createTableMessage'); + this._addTableToStoreLocally(databaseModel, settings.name); + this._resetModelInTablesController(databaseModel.get('tables')); + if(shouldTransition){ + this._transitionToCreatedTable(databaseModel.get('name'), settings.name); + } + }, 2 * 1000); + return Ember.RSVP.Promise.resolve(job); + }, (error) => { + // TODO: handle error + Ember.run.later(() => { + this.controller.set('showCreateTableModal', false); + this.controller.set('createTableMessage'); + if(shouldTransition) { + this.transitionTo('databases.database', databaseModel.get('name')); + } + }, 2 * 1000); + + return Ember.RSVP.Promise.reject(error); + }); + }, (error) => { + console.log("Error encountered", error); + this.controller.set('showCreateTableModal', true); + throw error; + }); + }, actions: { cancel() { let databaseController = this.controllerFor('databases.database'); this.transitionTo('databases.database', databaseController.get('model')); }, + toggleCSVFormat: function() { + console.log("inside new route toggleCSVFormat"); + this.toggleProperty('showCSVFormatInput') + }, create(settings) { - this.controller.set('showCreateTableModal', true); - this.controller.set('createTableMessage', 'Submitting request to create table'); - let databaseModel = this.controllerFor('databases.database').get('model'); - this.get('tableOperations').submitCreateTable(databaseModel.get('name'), settings) - .then((job) => { - console.log('Created job: ', job.get('id')); - this.controller.set('createTableMessage', 'Waiting for the table to be created'); - this.get('tableOperations').waitForJobToComplete(job.get('id'), 5 * 1000) - .then((status) => { - this.controller.set('createTableMessage', "Successfully created table"); - Ember.run.later(() => { - this.controller.set('showCreateTableModal', false); - this.controller.set('createTableMessage'); - this._addTableToStoreLocally(databaseModel, settings.name); - this._resetModelInTablesController(databaseModel.get('tables')); - this._transitionToCreatedTable(databaseModel.get('name'), settings.name); - }, 2 * 1000); - }, (error) => { - // TODO: handle error - Ember.run.later(() => { - this.controller.set('showCreateTableModal', false); - this.controller.set('createTableMessage'); - this.transitionTo('databases.database', databaseModel.get('name')); - }, 2 * 1000); - }); - }, (error) => { - console.log("Error encountered", error); - this.controller.set('showCreateTableModal', true); - }); + // keep this a function call call only as the createTable function is used in sub-classes + this.createTable(settings, true); } },
