/* Copyright (c) 2001-2019, The HSQL Development Group
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 *
 * Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * Neither the name of the HSQL Development Group nor the names of its
 * contributors may be used to endorse or promote products derived from this
 * software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL HSQL DEVELOPMENT GROUP, HSQLDB.ORG,
 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */


package org.hsqldb.persist;

import java.io.UnsupportedEncodingException;

import org.hsqldb.error.Error;
import org.hsqldb.error.ErrorCode;

Parser and container for text table settings.
Author:Bob Preston (sqlbob@users dot sourceforge.net), Fred Toussi (fredt@users dot sourceforge.net)
Version:2.5.0
Since:2.2.6
/** * Parser and container for text table settings. * * @author Bob Preston (sqlbob@users dot sourceforge.net) * @author Fred Toussi (fredt@users dot sourceforge.net) * @version 2.5.0 * @since 2.2.6 */
public class TextFileSettings { //state of Cache public static final String NL = System.getProperty("line.separator"); public String fs; public String vs; public String lvs; public String qc; public char quoteChar; public String stringEncoding; public boolean isQuoted; public boolean isAllQuoted; public boolean ignoreFirst; public String charEncoding; public boolean isUTF8; public boolean isUTF16; public boolean hasUTF16BOM; public boolean isLittleEndian; // private static final byte[] BYTES_NL = NL.getBytes(); private static final byte[] SP = new byte[]{ ' ' }; // String dataFileName; int maxCacheRows; int maxCacheBytes; char singleSeparator = 0; byte[] bytesForLineEnd = BYTES_NL; byte[] bytesForSpace = SP; // static final char DOUBLE_QUOTE_CHAR = '\"'; static final char BACKSLASH_CHAR = '\\'; public static final char LF_CHAR = '\n'; public static final char CR_CHAR = '\r';
The source string for a cached table is evaluated and the parameters are used to open the source file.

Settings are used in this order: (1) settings specified in the source string for the table (2) global database settings (3) program defaults

/** * The source string for a cached table is evaluated and the parameters * are used to open the source file.<p> * * Settings are used in this order: (1) settings specified in the * source string for the table (2) global database settings * (3) program defaults */
TextFileSettings(HsqlDatabaseProperties dbProps, String settingsString) { HsqlProperties tableprops = HsqlProperties.delimitedArgPairsToProps(settingsString, "=", ";", "textdb"); switch (tableprops.errorCodes.length) { case 0 : // no source file name this.dataFileName = null; break; case 1 : // source file name is the only key without a value this.dataFileName = tableprops.errorKeys[0].trim(); break; default : throw Error.error(ErrorCode.X_S0502); } //-- Get separators: from database properties, then from table properties fs = dbProps.getStringProperty(HsqlDatabaseProperties.textdb_fs); fs = tableprops.getProperty(HsqlDatabaseProperties.textdb_fs, fs); vs = dbProps.getStringProperty(HsqlDatabaseProperties.textdb_vs); vs = tableprops.getProperty(HsqlDatabaseProperties.textdb_vs, vs); lvs = dbProps.getStringProperty(HsqlDatabaseProperties.textdb_lvs); lvs = tableprops.getProperty(HsqlDatabaseProperties.textdb_lvs, lvs); qc = dbProps.getStringProperty(HsqlDatabaseProperties.textdb_qc); qc = tableprops.getProperty(HsqlDatabaseProperties.textdb_qc, qc); if (vs == null) { vs = fs; } if (lvs == null) { lvs = fs; } fs = translateSep(fs); vs = translateSep(vs); lvs = translateSep(lvs); qc = translateSep(qc); if (fs.length() == 0 || vs.length() == 0 || lvs.length() == 0) { throw Error.error(ErrorCode.X_S0503); } if (qc.length() != 1) { throw Error.error(ErrorCode.X_S0504); } quoteChar = qc.charAt(0); if (quoteChar > 0x007F) { throw Error.error(ErrorCode.X_S0504); } //-- get booleans ignoreFirst = dbProps.isPropertyTrue(HsqlDatabaseProperties.textdb_ignore_first); ignoreFirst = tableprops.isPropertyTrue( HsqlDatabaseProperties.textdb_ignore_first, ignoreFirst); isQuoted = dbProps.isPropertyTrue(HsqlDatabaseProperties.textdb_quoted); isQuoted = tableprops.isPropertyTrue(HsqlDatabaseProperties.textdb_quoted, isQuoted); isAllQuoted = dbProps.isPropertyTrue(HsqlDatabaseProperties.textdb_all_quoted); isAllQuoted = tableprops.isPropertyTrue(HsqlDatabaseProperties.textdb_all_quoted, isAllQuoted); //-- get string stringEncoding = dbProps.getStringProperty(HsqlDatabaseProperties.textdb_encoding); stringEncoding = tableprops.getProperty(HsqlDatabaseProperties.textdb_encoding, stringEncoding); charEncoding = stringEncoding; // UTF-8 files can begin with BOM 3-byte sequence // UTF-16 files can begin with BOM 2-byte sequence for big-endian // UTF-16BE files (big-endian) have no BOM // UTF-16LE files (little-endian) have no BOM if ("UTF8".equals(stringEncoding)) { isUTF8 = true; } else if ("UTF-8".equals(stringEncoding)) { isUTF8 = true; } else if ("UTF-16".equals(stringEncoding)) { // avoid repeating the BOM in each encoded string charEncoding = "UTF-16BE"; isUTF16 = true; } else if ("UTF-16BE".equals(stringEncoding)) { isUTF16 = true; } else if ("UTF-16LE".equals(stringEncoding)) { isUTF16 = true; isLittleEndian = true; } setSpaceAndLineEnd(); if (fs.length() == 1 || (fs.length() == 2 && fs.endsWith("\n"))) { singleSeparator = fs.charAt(0); } // //-- get size and scale int cacheScale = dbProps.getIntegerProperty( HsqlDatabaseProperties.textdb_cache_scale); cacheScale = tableprops.getIntegerProperty( HsqlDatabaseProperties.textdb_cache_scale, cacheScale); int cacheSizeScale = dbProps.getIntegerProperty( HsqlDatabaseProperties.textdb_cache_size_scale); cacheSizeScale = tableprops.getIntegerProperty( HsqlDatabaseProperties.textdb_cache_size_scale, cacheSizeScale); // maxCacheRows = (1 << cacheScale) * 3; maxCacheRows = dbProps.getIntegerProperty( HsqlDatabaseProperties.textdb_cache_rows, maxCacheRows); maxCacheRows = tableprops.getIntegerProperty( HsqlDatabaseProperties.textdb_cache_rows, maxCacheRows); maxCacheBytes = ((1 << cacheSizeScale) * maxCacheRows) / 1024; if (maxCacheBytes < 4) { maxCacheBytes = 4; } maxCacheBytes = dbProps.getIntegerProperty( HsqlDatabaseProperties.textdb_cache_size, maxCacheBytes); maxCacheBytes = tableprops.getIntegerProperty( HsqlDatabaseProperties.textdb_cache_size, maxCacheBytes); maxCacheBytes *= 1024; } String getFileName() { return dataFileName; } int getMaxCacheRows() { return maxCacheRows; } int getMaxCacheBytes() { return maxCacheBytes; }
for UTF-16 with BOM in file
/** * for UTF-16 with BOM in file */
void setLittleEndianByteOrderMark() { if ("UTF-16".equals(stringEncoding)) { charEncoding = "UTF-16LE"; isLittleEndian = true; hasUTF16BOM = true; // normal - BOM is expected } else { // abnormal - no BOM allowed - must use "UTF-16" as encoding throw Error.error(ErrorCode.X_S0531); } } void setSpaceAndLineEnd() { try { if (isUTF16) { bytesForLineEnd = NL.getBytes(charEncoding); bytesForSpace = " ".getBytes(charEncoding); } } catch (UnsupportedEncodingException e) { throw Error.error(ErrorCode.X_S0531); } } private static String translateSep(String sep) { return translateSep(sep, false); }
Translates the escaped characters in a separator string and returns the non-escaped string.
/** * Translates the escaped characters in a separator string and returns * the non-escaped string. */
private static String translateSep(String sep, boolean isProperty) { if (sep == null) { return null; } int next = sep.indexOf(BACKSLASH_CHAR); if (next != -1) { int start = 0; char[] sepArray = sep.toCharArray(); char ch = 0; int len = sep.length(); StringBuilder sb = new StringBuilder(len); do { sb.append(sepArray, start, next - start); start = ++next; if (next >= len) { sb.append(BACKSLASH_CHAR); break; } if (!isProperty) { ch = sepArray[next]; } if (ch == 'n') { sb.append(LF_CHAR); start++; } else if (ch == 'r') { sb.append(CR_CHAR); start++; } else if (ch == 't') { sb.append('\t'); start++; } else if (ch == BACKSLASH_CHAR) { sb.append(BACKSLASH_CHAR); start++; } else if (ch == 'u') { start++; sb.append( (char) Integer.parseInt( sep.substring(start, start + 4), 16)); start += 4; } else if (sep.startsWith("semi", next)) { sb.append(';'); start += 4; } else if (sep.startsWith("space", next)) { sb.append(' '); start += 5; } else if (sep.startsWith("quote", next)) { sb.append(DOUBLE_QUOTE_CHAR); start += 5; } else if (sep.startsWith("apos", next)) { sb.append('\''); start += 4; } else if (sep.startsWith("colon", next)) { sb.append(':'); start += 5; } else { sb.append(BACKSLASH_CHAR); sb.append(sepArray[next]); start++; } } while ((next = sep.indexOf(BACKSLASH_CHAR, start)) != -1); sb.append(sepArray, start, len - start); sep = sb.toString(); } return sep; } }