Java tutorial
/* * Copyright 2014 Lukas Benda <lbenda at lbenda.cz>. * * Licensed 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 cz.lbenda.dataman.db; import cz.lbenda.common.*; import cz.lbenda.dataman.Constants; import cz.lbenda.dataman.db.dialect.SQLDialect; import cz.lbenda.dataman.schema.export.*; import cz.lbenda.dataman.schema.export.ColumnType; import cz.lbenda.rcp.DialogHelper; import cz.lbenda.rcp.ExceptionMessageFrmController; import cz.lbenda.rcp.localization.Message; import freemarker.cache.TemplateLoader; import freemarker.template.*; import org.apache.commons.csv.CSVFormat; import org.apache.commons.csv.CSVPrinter; import org.apache.commons.io.FilenameUtils; import org.apache.commons.io.IOUtils; import org.apache.commons.io.output.WriterOutputStream; import org.apache.poi.hssf.usermodel.HSSFCell; import org.apache.poi.hssf.usermodel.HSSFRow; import org.apache.poi.hssf.usermodel.HSSFSheet; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.apache.poi.xssf.usermodel.XSSFSheet; import org.apache.poi.xssf.usermodel.XSSFRow; import org.apache.poi.xssf.usermodel.XSSFCell; import org.jdom2.Document; import org.jdom2.Element; import org.jdom2.output.XMLOutputter; import org.jopendocument.dom.spreadsheet.SpreadSheet; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.thymeleaf.TemplateEngine; import org.thymeleaf.context.Context; import org.thymeleaf.templateresolver.FileTemplateResolver; import javax.annotation.Nonnull; import javax.swing.table.DefaultTableModel; import javax.swing.table.TableModel; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerConfigurationException; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; import javax.xml.transform.stream.StreamResult; import javax.xml.transform.stream.StreamSource; import java.io.*; import java.util.*; import java.util.stream.Collectors; /** Created by Lukas Benda <lbenda @ lbenda.cz> on 20.9.15. * Class which give ability to export data table */ public class ExportTableData { private static final Logger LOG = LoggerFactory.getLogger(ExportTableData.class); @Message public static final String CHOOSE_FORMAT = "Choose format for export"; public enum SpreadsheetFormat { XLSX("xlsx"), XLS("xls"), ODS("ods"), CSV("csv"), TXT("txt"), XMLv1("xml"), XMLv2("xml"), SQL("sql"),; private static Map<String, List<SpreadsheetFormat>> extensionsMap = new HashMap<>(); static { Arrays.stream(SpreadsheetFormat.values()).forEach(s -> { List<SpreadsheetFormat> list = extensionsMap.get(s.getExtension()); if (list == null) { list = new ArrayList<>(); extensionsMap.put(s.getExtension(), list); } list.add(s); }); } private String extension; public String getExtension() { return extension; } SpreadsheetFormat(String extension) { this.extension = extension; } public static List<SpreadsheetFormat> byExtension(String extension) { return extensionsMap.get(extension); } } public enum TemplateFormat { XLST_XMLv1, XLST_XMLv2, /* VELOCITY, */FREEMARKER, THYMELEAF,; } public static class TemplateExportConfig { /** Format system for template */ private ExportTableData.TemplateFormat templateFormat; public ExportTableData.TemplateFormat getTemplateFormat() { return templateFormat; } /** File which contains template */ private String templateFile; public String getTemplateFile() { return templateFile; } /** File to which will be export write */ private String file; public String getFile() { return file; } public TemplateExportConfig(ExportTableData.TemplateFormat templateFormat, String templateFile, String file) { this.templateFormat = templateFormat; this.templateFile = templateFile; this.file = file; } } public static void writeSqlQueryRows(SpreadsheetFormat format, SQLQueryRows sqlQueryRows, String sheetName, OutputStream outputStream) throws IOException { switch (format) { case XLSX: writeSqlQueryRowsToXLSX(sqlQueryRows, sheetName, outputStream); break; case XLS: writeSqlQueryRowsToXLS(sqlQueryRows, sheetName, outputStream); break; case XMLv1: writeSqlQueryRowsToXMLv1(sqlQueryRows, outputStream); break; case XMLv2: writeSqlQueryRowsToXMLv2(sqlQueryRows, outputStream); break; case CSV: writeSqlQueryRowsToCSV(sqlQueryRows, new OutputStreamWriter(outputStream)); break; case TXT: writeSqlQueryRowsToTXT(sqlQueryRows, new OutputStreamWriter(outputStream)); break; case ODS: writeSqlQueryRowsToODS(sqlQueryRows, sheetName, outputStream); break; case SQL: writeSqlQueryRowsToSQL(sqlQueryRows, new OutputStreamWriter(outputStream)); break; } } public static void writeSqlQueryRows(SpreadsheetFormat format, SQLQueryRows sqlQueryRows, String sheetName, Writer writer) throws IOException { switch (format) { case XLSX: writeSqlQueryRowsToXLSX(sqlQueryRows, sheetName, new WriterOutputStream(writer)); break; case XLS: writeSqlQueryRowsToXLS(sqlQueryRows, sheetName, new WriterOutputStream(writer)); break; case XMLv1: writeSqlQueryRowsToXMLv1(sqlQueryRows, new WriterOutputStream(writer)); break; case XMLv2: writeSqlQueryRowsToXMLv2(sqlQueryRows, new WriterOutputStream(writer)); break; case CSV: writeSqlQueryRowsToCSV(sqlQueryRows, writer); break; case TXT: writeSqlQueryRowsToTXT(sqlQueryRows, writer); break; case ODS: writeSqlQueryRowsToODS(sqlQueryRows, sheetName, new WriterOutputStream(writer)); break; case SQL: writeSqlQueryRowsToSQL(sqlQueryRows, writer); break; } } public static void writeSqlQueryRows(String fileName, SQLQueryRows sqlQueryRows, String sheetName, OutputStream outputStream) throws IOException { String extension = FilenameUtils.getExtension(fileName); List<SpreadsheetFormat> formatList = SpreadsheetFormat.byExtension(extension); final SpreadsheetFormat format; if (formatList == null) { format = DialogHelper.chooseSingOption(CHOOSE_FORMAT, SpreadsheetFormat.values()); } else if (formatList.size() == 1) { format = formatList.get(0); } else { format = DialogHelper.chooseSingOption(CHOOSE_FORMAT, formatList); } if (format == null) { return; } writeSqlQueryRows(format, sqlQueryRows, sheetName, outputStream); } public static void writeSqlQueryRows(@Nonnull TemplateFormat format, @Nonnull SQLQueryRows sqlQueryRows, @Nonnull String templateFile, @Nonnull OutputStream outputStream) throws IOException { try (FileInputStream fis = new FileInputStream(templateFile)) { switch (format) { case FREEMARKER: writeSqlQueryRowsToFreemarker(sqlQueryRows, fis, outputStream); break; case THYMELEAF: writeSqlQueryRowsToThymeleaf(sqlQueryRows, templateFile, outputStream); break; /* case VELOCITY: writeSqlQueryRowsToXMLv1(sqlQueryRows, template, outputStream); break;*/ case XLST_XMLv1: writeSqlQueryRowsToXLSTXMLv1(sqlQueryRows, fis, outputStream); break; case XLST_XMLv2: writeSqlQueryRowsToXLSTXMLv2(sqlQueryRows, fis, outputStream); break; } } } /** Write rows to XLSX file * @param sqlQueryRows rows * @param sheetName name of sheet where is data write * @param outputStream stream where are data write */ public static void writeSqlQueryRowsToXLSX(SQLQueryRows sqlQueryRows, String sheetName, OutputStream outputStream) throws IOException { XSSFWorkbook wb = new XSSFWorkbook(); XSSFSheet sheet = wb.createSheet(sheetName); XSSFRow headerRow = sheet.createRow(0); int c = 0; for (ColumnDesc columnDesc : sqlQueryRows.getMetaData().getColumns()) { XSSFCell cell = headerRow.createCell(c); cell.setCellValue(columnDesc.getName()); c++; } int r = 1; for (RowDesc row : sqlQueryRows.getRows()) { XSSFRow xlsxRow = sheet.createRow(r); c = 0; for (ColumnDesc columnDesc : sqlQueryRows.getMetaData().getColumns()) { XSSFCell cell = xlsxRow.createCell(c); cell.setCellValue(row.getColumnValueStr(columnDesc)); c++; } r++; } wb.write(outputStream); } /** Write rows to XLS file * @param sqlQueryRows rows * @param sheetName name of sheet where is data write * @param outputStream stream where are data write */ public static void writeSqlQueryRowsToXLS(SQLQueryRows sqlQueryRows, String sheetName, OutputStream outputStream) throws IOException { HSSFWorkbook wb = new HSSFWorkbook(); HSSFSheet sheet = wb.createSheet(sheetName); HSSFRow headerRow = sheet.createRow(0); int c = 0; for (ColumnDesc columnDesc : sqlQueryRows.getMetaData().getColumns()) { HSSFCell cell = headerRow.createCell(c); cell.setCellValue(columnDesc.getName()); c++; } int r = 1; for (RowDesc row : sqlQueryRows.getRows()) { HSSFRow xlsxRow = sheet.createRow(r); c = 0; for (ColumnDesc columnDesc : sqlQueryRows.getMetaData().getColumns()) { HSSFCell cell = xlsxRow.createCell(c); cell.setCellValue(row.getColumnValueStr(columnDesc)); c++; } r++; } wb.write(outputStream); } /** Write rows to CSV file * @param sqlQueryRows rows * @param writer where are data */ public static void writeSqlQueryRowsToCSV(SQLQueryRows sqlQueryRows, Writer writer) throws IOException { CSVFormat csvFileFormat = CSVFormat.DEFAULT.withRecordSeparator(Constants.CSV_NEW_LINE_SEPARATOR); CSVPrinter csvFilePrinter = new CSVPrinter(writer, csvFileFormat); csvFilePrinter .printRecord(sqlQueryRows.getMetaData().getColumns().stream().map(ColumnDesc::getName).toArray()); for (RowDesc row : sqlQueryRows.getRows()) { csvFilePrinter.printRecord( sqlQueryRows.getMetaData().getColumns().stream().map(row::getColumnValueStr).toArray()); } } private static StringBuffer SPACES = new StringBuffer(); private static String fixedString(String value, int length) { if (length > Constants.maxTextColumnSize) { length = Constants.maxTextColumnSize; } if (SPACES.length() < length) { for (int i = SPACES.length(); i < length; i++) { SPACES.append(" "); } } if (value == null) { return SPACES.substring(0, length); } if (length < value.length()) { return value.substring(0, length); } return value + SPACES.substring(0, length - value.length()); } /** Write rows to CSV file * @param sqlQueryRows rows * @param writer writer where are data write */ public static void writeSqlQueryRowsToTXT(SQLQueryRows sqlQueryRows, Writer writer) throws IOException { String joined = sqlQueryRows.getMetaData().getColumns().stream() .map(cd -> fixedString(cd.getName(), cd.getSize())).collect(Collectors.joining("")); writer.append(joined).append(Constants.CSV_NEW_LINE_SEPARATOR); for (RowDesc row : sqlQueryRows.getRows()) { joined = sqlQueryRows.getMetaData().getColumns().stream() .map(cd -> fixedString(row.getColumnValueStr(cd), cd.getSize())) .collect(Collectors.joining("")); writer.append(joined).append(Constants.CSV_NEW_LINE_SEPARATOR); writer.flush(); } } /** Write rows to ODS file * @param sqlQueryRows rows * @param sheetName name of sheet where is data write * @param outputStream stream where are data write */ public static void writeSqlQueryRowsToODS(SQLQueryRows sqlQueryRows, @SuppressWarnings("UnusedParameters") String sheetName, OutputStream outputStream) throws IOException { Object[] header = sqlQueryRows.getMetaData().getColumns().stream().map(ColumnDesc::getName).toArray(); Object[][] rows = new Object[sqlQueryRows.getRows().size()][]; int i = 0; for (RowDesc row : sqlQueryRows.getRows()) { rows[i] = sqlQueryRows.getMetaData().getColumns().stream().map(row::getColumnValue).toArray(); i++; } TableModel model = new DefaultTableModel(rows, header); SpreadSheet.createEmpty(model).getPackage().save(outputStream); } private static String columnId(ColumnDesc cd) { return cd.getCatalog() + "." + cd.getSchema() + "." + cd.getTable() + "." + cd.getName(); } /** Write rows from sql query to output stream * @param sqlQueryRows rows * @param outputStream stream to which are data write */ public static void writeSqlQueryRowsToXMLv1(SQLQueryRows sqlQueryRows, OutputStream outputStream) { ObjectFactory of = new ObjectFactory(); ExportType export = of.createExportType(); export.setSql(sqlQueryRows.getSQL()); export.setVersion("1"); ColumnsType columnsType = of.createColumnsType(); export.setColumns(columnsType); Map<ColumnDesc, ColumnType> ctsMap = new HashMap<>(); sqlQueryRows.getMetaData().getColumns().forEach(cd -> { ColumnType ct = of.createColumnType(); ctsMap.put(cd, ct); ct.setId(columnId(cd)); ct.setCatalog(cd.getCatalog()); ct.setSchema(cd.getSchema()); ct.setTable(cd.getTable()); ct.setColumn(cd.getName()); ct.setDataType(DbStructureFactory.columnTypeToDataTypeType(cd.getDataType())); ct.setLength(cd.getSize()); ct.setScale(cd.getScale()); ct.setValue(cd.getLabel()); columnsType.getColumn().add(ct); }); sqlQueryRows.getRows().forEach(row -> { RowType rowType = of.createRowType(); sqlQueryRows.getMetaData().getColumns().forEach(cd -> { FieldType field = of.createFieldType(); field.setColumn(ctsMap.get(cd)); if (row.isColumnNull(cd)) { field.setNull(true); } else { field.setValue(row.getColumnValueStr(cd)); } rowType.getField().add(field); }); export.getRow().add(rowType); }); try { JAXBContext jc = JAXBContext.newInstance(cz.lbenda.dataman.schema.export.ObjectFactory.class); Marshaller m = jc.createMarshaller(); m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.FALSE); m.marshal(of.createExport(export), outputStream); } catch (JAXBException e) { LOG.error("Problem with write exporting data: " + e.toString(), e); throw new RuntimeException("Problem with write exporting data: " + e.toString(), e); } } /** Write rows from sql query to output stream * @param sqlQueryRows rows * @param outputStream stream to which are data write */ public static void writeSqlQueryRowsToXMLv2(SQLQueryRows sqlQueryRows, OutputStream outputStream) throws IOException { Element root = new Element("export"); root.setAttribute("sql", sqlQueryRows.getSQL()); root.setAttribute("version", "2"); List<Element> rows = new ArrayList<>(sqlQueryRows.getRows().size()); sqlQueryRows.getRows().forEach(rowDesc -> { Element row = new Element("row"); List<Element> cols = new ArrayList<>(sqlQueryRows.getMetaData().getColumns().size()); sqlQueryRows.getMetaData().getColumns().forEach(columnDesc -> { Element element = new Element(columnDesc.getName()); if (rowDesc.isColumnNull(columnDesc)) { element.setAttribute("null", "true"); } else { element.setText(rowDesc.getColumnValueStr(columnDesc)); } cols.add(element); }); row.addContent(cols); rows.add(row); }); root.addContent(rows); XMLOutputter xmlOutputter = new XMLOutputter(); xmlOutputter.output(new Document(root), outputStream); } private static void transformXSLT(InputStream templateStream, ByteArrayOutputStream xmlOutputStream, OutputStream outputStream) { StreamSource styleSource = new StreamSource(templateStream); ByteArrayInputStream bais = new ByteArrayInputStream(xmlOutputStream.toByteArray()); StreamSource xmlSource = new StreamSource(bais); StreamResult streamResult = new StreamResult(outputStream); try { Transformer transformer = TransformerFactory.newInstance().newTransformer(styleSource); transformer.transform(xmlSource, streamResult); } catch (TransformerConfigurationException e) { LOG.error("Problem with load style source.", e); ExceptionMessageFrmController.showException("Problem with load style source.", e); } catch (TransformerException e) { LOG.error("Problem with transforming input stream.", e); ExceptionMessageFrmController.showException("Problem with transforming input stream.", e); } } /** Write rows from sql query to output stream * @param sqlQueryRows rows * @param outputStream stream to which are data write */ public static void writeSqlQueryRowsToXLSTXMLv1(SQLQueryRows sqlQueryRows, InputStream template, OutputStream outputStream) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); writeSqlQueryRowsToXMLv1(sqlQueryRows, baos); transformXSLT(template, baos, outputStream); } /** Write rows from sql query to output stream * @param sqlQueryRows rows * @param outputStream stream to which are data write */ public static void writeSqlQueryRowsToXLSTXMLv2(SQLQueryRows sqlQueryRows, InputStream tempalte, OutputStream outputStream) throws IOException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); writeSqlQueryRowsToXMLv2(sqlQueryRows, baos); transformXSLT(tempalte, baos, outputStream); } /** Write rows from sql query to output stream * @param sqlQueryRows rows * @param outputStream stream to which are data write */ public static void writeSqlQueryRowsToThymeleaf(SQLQueryRows sqlQueryRows, String templateFileName, OutputStream outputStream) throws IOException { Context ctx = new Context(Locale.getDefault()); ctx.setVariable("sql", sqlQueryRows.getSQL()); ctx.setVariable("columns", sqlQueryRows.getMetaData().getColumns()); List<List<Object>> rows = new ArrayList<>(); ctx.setVariable("rows", rows); sqlQueryRows.getRows().forEach(rowDesc -> { List<Object> row = new ArrayList<>(); sqlQueryRows.getMetaData().getColumns().forEach(columnDesc -> { if (rowDesc.isColumnNull(columnDesc)) { row.add(null); } else { row.add(rowDesc.getColumnValue(columnDesc)); } }); rows.add(row); }); TemplateEngine templateEngine = new TemplateEngine(); FileTemplateResolver resolver = new FileTemplateResolver(); templateEngine.setTemplateResolver(resolver); IOUtils.write(templateEngine.process(templateFileName, ctx), outputStream); } /** Write rows from sql query to output stream * @param sqlQueryRows rows * @param outputStream stream to which are data write */ public static void writeSqlQueryRowsToFreemarker(SQLQueryRows sqlQueryRows, InputStream template, OutputStream outputStream) throws IOException { Configuration cfg = new Configuration(); cfg.setTemplateLoader(new TemplateLoader() { @Override @SuppressWarnings("RedundantThrowsDeclaration") public Object findTemplateSource(String s) throws IOException { return template; } @Override public long getLastModified(Object o) { return 0; } @Override @SuppressWarnings("RedundantThrowsDeclaration") public Reader getReader(Object o, String s) throws IOException { return new InputStreamReader(template); } @Override @SuppressWarnings("RedundantThrowsDeclaration") public void closeTemplateSource(Object o) throws IOException { } }); cfg.setIncompatibleImprovements(new Version(2, 3, 20)); cfg.setDefaultEncoding("UTF-8"); cfg.setLocale(Locale.US); cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER); Template freemarkerTemplate = cfg.getTemplate("template"); Map<String, Object> input = new HashMap<>(); input.put("sql", sqlQueryRows.getSQL()); input.put("columns", sqlQueryRows.getMetaData().getColumns()); List<List<Object>> rows = new ArrayList<>(); input.put("rows", rows); sqlQueryRows.getRows().forEach(rowDesc -> { List<Object> row = new ArrayList<>(); sqlQueryRows.getMetaData().getColumns().forEach(columnDesc -> { if (rowDesc.isColumnNull(columnDesc)) { row.add(null); } else { row.add(rowDesc.getColumnValue(columnDesc)); } }); rows.add(row); }); input.put("sqlQueryRows", sqlQueryRows); try { freemarkerTemplate.process(input, new OutputStreamWriter(outputStream)); } catch (TemplateException e) { LOG.error("Problem with transforming input stream.", e); ExceptionMessageFrmController.showException("Problem with transforming input stream.", e); } } /** Write SQL query as insert sql * @param sqlQueryRows rows which will be store as INSERT sql * @param writer writer to which is write inserts */ public static void writeSqlQueryRowsToSQL(SQLQueryRows sqlQueryRows, Writer writer) { final Map<String, List<ColumnDesc>> columnsByTables = new HashMap<>(); sqlQueryRows.getMetaData().getColumns().forEach(columnDesc -> { String table = String.format("\"%s\".\"%s\"", columnDesc.getSchema().trim(), columnDesc.getTable().trim()); List<ColumnDesc> columns = columnsByTables.get(table); if (columns == null) { columns = new ArrayList<>(); columnsByTables.put(table, columns); } columns.add(columnDesc); }); final Map<String, String> columnsByTableNames = new HashMap<>(); columnsByTables.entrySet().forEach(entry -> { StringBuilder sb = new StringBuilder(); entry.getValue().forEach(columnDesc -> { if (sb.length() > 0) { sb.append(", "); } sb.append('"').append(columnDesc.getName()).append('"'); }); columnsByTableNames.put(entry.getKey(), sb.toString()); }); sqlQueryRows.getRows().forEach(rowDesc -> columnsByTables.entrySet().forEach(entry -> { StringBuilder row = new StringBuilder(); entry.getValue().forEach(columnDesc -> { if (row.length() > 0) { row.append(", "); } row.append(sqlValue(sqlQueryRows.getDialect(), columnDesc, rowDesc)); }); try { writer.write(String.format("insert into %s (%s) values(%s);\n", entry.getKey(), columnsByTableNames.get(entry.getKey()), row.toString())); writer.flush(); } catch (IOException e) { LOG.error("Problem with write SQL insert", e); throw new RuntimeException("Problem with write SQL insert", e); } })); } /** Create SQL representation of value in column. Format to SQL and add quote etc * @param columnDesc column which is get * @param rowDesc row from which is data get * @return string representation of value in SQL */ public static String sqlValue(SQLDialect dialect, ColumnDesc columnDesc, RowDesc rowDesc) { Object value = rowDesc.getColumnValue(columnDesc); if (value == null) { return "NULL"; } switch (columnDesc.getDataType()) { case STRING: case UUID: return "'" + rowDesc.getColumnValueStr(columnDesc) + "'"; case DATE: return "'" + StringConverters.SQL_SQL_DATE_CONVERTER.toString((java.sql.Date) value) + "'"; case TIME: return "'" + StringConverters.SQL_SQL_TIME_CONVERTER.toString((java.sql.Time) value) + "'"; case TIMESTAMP: return "'" + StringConverters.SQL_SQL_TIMESTAMP_CONVERTER.toString((java.sql.Timestamp) value) + "'"; case BOOLEAN: if (dialect != null && dialect.isBooleanBitRepresent()) { return Boolean.TRUE.equals(value) ? "1" : "0"; } return rowDesc.getColumnValueStr(columnDesc); case CLOB: ClobBinaryData cbd = (ClobBinaryData) value; if (cbd.isNull()) { return "NULL"; } try { return "'" + IOUtils.toString(cbd.getReader()) + "'"; } catch (IOException e) { LOG.error("Error convert clob to string.", e); throw new RuntimeException("Error convert clob to string.", e); } case BLOB: BlobBinaryData bbd = (BlobBinaryData) value; if (bbd.isNull()) { return "NULL"; } try { return "'" + IOUtils.toString(bbd.getReader()) + "'"; } catch (IOException e) { LOG.error("Error convert blob to string.", e); throw new RuntimeException("Error convert blob to string.", e); } case BIT_ARRAY: try { if (((BitArrayBinaryData) value).isNull()) { return "NULL"; } String res = IOUtils.toString(((BitArrayBinaryData) value).getReader()); return "0x'" + res.replaceAll(" ", "") + "'"; } catch (IOException e) { LOG.error("Error convert bit array to string.", e); throw new RuntimeException("Error convert bit array to string.", e); } case BYTE_ARRAY: if (((ByteArrayBinaryData) value).isNull()) { return "NULL"; } return "'" + rowDesc.getColumnValueStr(columnDesc) + "'"; } return rowDesc.getColumnValueStr(columnDesc); } }