001: /*
002: * ConstantColumnValues.java
003: *
004: * This file is part of SQL Workbench/J, http://www.sql-workbench.net
005: *
006: * Copyright 2002-2008, Thomas Kellerer
007: * No part of this code maybe reused without the permission of the author
008: *
009: * To contact the author please send an email to: support@sql-workbench.net
010: *
011: */
012: package workbench.db.importer;
013:
014: import java.sql.PreparedStatement;
015: import java.sql.SQLException;
016: import java.util.ArrayList;
017: import java.util.List;
018: import workbench.db.ColumnIdentifier;
019: import workbench.db.TableIdentifier;
020: import workbench.db.WbConnection;
021: import workbench.log.LogMgr;
022: import workbench.storage.ColumnData;
023: import workbench.util.ConverterException;
024: import workbench.util.SqlUtil;
025: import workbench.util.StringUtil;
026: import workbench.util.ValueConverter;
027:
028: /**
029: * A class to parse column constants for the DataImporter
030: *
031: * @author support@sql-workbench.net
032: */
033: public class ConstantColumnValues {
034: // I'm using two arraylists to ensure that the
035: // order of the columns is always maintained.
036: private List<ColumnData> columnValues;
037:
038: /**
039: * Parses a parameter value for column value definitions.
040: * e.g. description=something,firstname=arthur
041: * The values from the Commandline are converted to the correct
042: * datatype in the targettable.
043: * @throws SQLException if the target table was not found
044: * @throws ConverterException if a value could not be converted to the target data type
045: */
046: public ConstantColumnValues(String parameterValue,
047: WbConnection con, String tablename, ValueConverter converter)
048: throws SQLException, ConverterException {
049: List<ColumnIdentifier> tableColumns = con.getMetadata()
050: .getTableColumns(new TableIdentifier(tablename));
051: if (tableColumns.size() == 0)
052: throw new SQLException("Table '" + tablename
053: + "' not found!");
054: init(parameterValue, tableColumns, converter);
055: }
056:
057: /**
058: * For Unit-Testing without a Database Connection
059: */
060: ConstantColumnValues(String parameterValue,
061: List<ColumnIdentifier> targetColumns) throws SQLException,
062: ConverterException {
063: init(parameterValue, targetColumns, new ValueConverter());
064: }
065:
066: protected void init(String parameterValue,
067: List<ColumnIdentifier> tableColumns,
068: ValueConverter converter) throws SQLException,
069: ConverterException {
070: if (parameterValue == null)
071: return;
072:
073: List<String> entries = StringUtil.stringToList(parameterValue,
074: ",", true, true, false);
075: if (entries.size() == 0)
076: return;
077:
078: this .columnValues = new ArrayList<ColumnData>(entries.size());
079:
080: for (String entry : entries) {
081: String[] parts = entry.split("=");
082:
083: if (parts.length == 2 && parts[0] != null
084: && parts[1] != null) {
085: String colname = parts[0];
086: ColumnIdentifier col = findColumn(tableColumns, colname);
087:
088: if (col != null) {
089: String value = parts[1];
090: Object data = null;
091: if (StringUtil.isEmptyString(value)) {
092: LogMgr.logWarning("ConstanColumnValues.init()",
093: "Empty value for column '" + col
094: + "' assumed as NULL");
095: } else {
096: if (value.startsWith("${")) {
097: // DBMS Function call
098: data = value.trim();
099: } else {
100: if (SqlUtil.isCharacterType(col
101: .getDataType())) {
102: if (value.charAt(0) == '\''
103: && value
104: .charAt(value.length() - 1) == '\'') {
105: value = value.substring(1, value
106: .length() - 1);
107: }
108: }
109: data = converter.convertValue(value, col
110: .getDataType());
111: }
112: }
113: this .columnValues.add(new ColumnData(data, col));
114: } else {
115: throw new SQLException("Column '" + colname
116: + "' not found in target table!");
117: }
118: }
119: }
120: }
121:
122: private ColumnIdentifier findColumn(List<ColumnIdentifier> columns,
123: String name) {
124: for (ColumnIdentifier col : columns) {
125: if (col.getColumnName().equalsIgnoreCase(name))
126: return col;
127: }
128: return null;
129: }
130:
131: public String getFunctionLiteral(int index) {
132: if (!this .isFunctionCall(index))
133: return null;
134: String value = (String) this .getValue(index);
135:
136: // The function call is enclosed in ${...}
137: return value.substring(2, value.length() - 1);
138: }
139:
140: public boolean isFunctionCall(int index) {
141: Object value = this .getValue(index);
142: if (value == null)
143: return false;
144:
145: if (value instanceof String) {
146: String f = (String) value;
147: return f.startsWith("${") && f.endsWith("}");
148: }
149: return false;
150: }
151:
152: public int getColumnCount() {
153: if (this .columnValues == null)
154: return 0;
155: return this .columnValues.size();
156: }
157:
158: public ColumnIdentifier getColumn(int index) {
159: return this .columnValues.get(index).getIdentifier();
160: }
161:
162: public Object getValue(int index) {
163: return this .columnValues.get(index).getValue();
164: }
165:
166: public boolean removeColumn(ColumnIdentifier col) {
167: if (this .columnValues == null)
168: return false;
169: if (col == null)
170: return false;
171:
172: int index = -1;
173: for (int i = 0; i < this .columnValues.size(); i++) {
174: if (columnValues.get(i).getIdentifier().equals(col)) {
175: index = i;
176: break;
177: }
178: }
179:
180: if (index > -1) {
181: this .columnValues.remove(index);
182: }
183: return (index > -1);
184: }
185:
186: public void setParameter(PreparedStatement pstmt,
187: int statementIndex, int columnIndex) throws SQLException {
188: ColumnIdentifier col = getColumn(columnIndex);
189: Object value = getValue(columnIndex);
190: int type = col.getDataType();
191:
192: // If the column value is a function call, this will not
193: // be used in a prepared statement. It is expected that the caller
194: // (that prepared the statement) inserted the literal value of the
195: // function call into the SQL instead of a ? placeholder
196: if (!isFunctionCall(columnIndex)) {
197: pstmt.setObject(statementIndex, value);
198: }
199: }
200: }
|