Codebase list csvjdbc / upstream/1.0.34
New upstream version 1.0.34 Christopher Hoskin 6 years ago
16 changed file(s) with 446 addition(s) and 31 deletion(s). Raw diff Collapse all Expand all
3535 <!-- =================================================================== -->
3636 <property name="TALK" value="false" />
3737 <property name="name" value="csvjdbc"/>
38 <property name="rel" value="1.0-31"/>
38 <property name="rel" value="1.0-33"/>
3939 <property name="rel.name" value="${name}-${rel}"/>
4040 <property name="build.dir" value="../build"/>
4141 <property name="src.dir" value="../src"/>
22 <modelVersion>4.0.0</modelVersion>
33 <groupId>net.sourceforge.csvjdbc</groupId>
44 <artifactId>csvjdbc</artifactId>
5 <version>1.0.31</version>
5 <version>1.0.34</version>
66 <packaging>jar</packaging>
77 <name>CsvJdbc</name>
88 <description>a Java JDBC driver for reading comma-separated-value files</description>
1717
1818 <scm>
1919 <connection>scm:git:ssh://git.code.sf.net/p/csvjdbc/code</connection>
20 <tag>HEAD</tag>
20 <tag>csvjdbc-1.0.34</tag>
2121 <url>http://sourceforge.net/p/csvjdbc/_list/git</url>
2222 </scm>
2323
131131 <plugin>
132132 <groupId>org.apache.maven.plugins</groupId>
133133 <artifactId>maven-release-plugin</artifactId>
134 <version>2.5.3</version>
134135 <configuration>
135136 <autoVersionSubmodules>true</autoVersionSubmodules>
136137 <useReleaseProfile>false</useReleaseProfile>
137138 <!-- references the profile defined just below -->
138139 <releaseProfiles>release</releaseProfiles>
139140 <goals>deploy</goals>
140 <pushChanges>false</pushChanges>
141 <pushChanges>true</pushChanges>
141142 </configuration>
142143 </plugin>
143144 <plugin>
2424
2525 class ColumnName extends Expression
2626 {
27 String columnName;
27 private String columnName;
28
2829 public ColumnName(String columnName)
2930 {
3031 this.columnName = columnName.toUpperCase();
3132 }
33
34 public String getColumnName()
35 {
36 return columnName;
37 }
38
3239 public Object eval(Map<String, Object> env)
3340 {
3441 return env.get(columnName);
3542 }
43
3644 public String toString()
3745 {
3846 return "["+columnName+"]";
3947 }
48
4049 public List<String> usedColumns(Set<String> availableColumns)
4150 {
4251 List<String> result = new LinkedList<String>();
4141 import java.sql.Statement;
4242 import java.sql.Struct;
4343 import java.util.ArrayList;
44 import java.util.Collections;
4445 import java.util.HashMap;
46 import java.util.HashSet;
4547 import java.util.List;
4648 import java.util.Locale;
4749 import java.util.Map;
4850 import java.util.Properties;
4951 import java.util.Vector;
5052 import java.util.concurrent.Executor;
53 import java.util.regex.Matcher;
54 import java.util.regex.Pattern;
5155
5256 import org.relique.io.CryptoFilter;
5357 import org.relique.io.TableReader;
13881392 return name.endsWith(extension);
13891393 }
13901394 });
1395
1396 Pattern fileNameRE = null;
1397 if (indexedFiles)
1398 {
1399 /*
1400 * Accept any filenames that match the fileTailPattern that was
1401 * configured for this connection.
1402 */
1403 fileNameRE = Pattern.compile("(.+)" + fileNamePattern);
1404 }
1405
1406 HashSet<String> indexedTableNames = new HashSet<String>();
1407
13911408 for (int i = 0; i < matchingFiles.length; i++)
13921409 {
13931410 if (matchingFiles[i].isFile() && matchingFiles[i].canRead())
13951412 String filename = matchingFiles[i].getName();
13961413 String tableName = filename.substring(0,
13971414 filename.length() - extension.length());
1398 tableNames.add(tableName);
1415
1416 if (indexedFiles)
1417 {
1418 Matcher m = fileNameRE.matcher(tableName);
1419 if (m.matches())
1420 {
1421 /*
1422 * We want only the first part of the filename, before
1423 * the fileTailPattern.
1424 *
1425 * We use a java.util.Set so that each indexed table name
1426 * is added only one time, despite comprising of several files.
1427 */
1428 indexedTableNames.add(m.group(1));
1429 }
1430 }
1431 else
1432 {
1433 tableNames.add(tableName);
1434 }
13991435 }
14001436 }
1437 tableNames.addAll(indexedTableNames);
14011438 }
14021439 else
14031440 {
14081445 if (list != null)
14091446 tableNames = list;
14101447 }
1448
1449 /*
1450 * Ensure tables are always reported in the same order.
1451 */
1452 Collections.sort(tableNames);
14111453 return tableNames;
14121454 }
14131455 }
1515 */
1616 package org.relique.jdbc.csv;
1717
18 import java.net.URLDecoder;
19 import java.sql.*;
20 import java.util.Properties;
2118 import java.io.File;
2219 import java.io.IOException;
2320 import java.io.PrintStream;
2421 import java.io.PrintWriter;
2522 import java.io.UnsupportedEncodingException;
23 import java.net.URLDecoder;
24 import java.sql.Connection;
25 import java.sql.Date;
26 import java.sql.Driver;
27 import java.sql.DriverManager;
28 import java.sql.DriverPropertyInfo;
29 import java.sql.ResultSet;
30 import java.sql.ResultSetMetaData;
31 import java.sql.SQLException;
32 import java.sql.SQLFeatureNotSupportedException;
33 import java.sql.Time;
34 import java.sql.Timestamp;
35 import java.sql.Types;
36 import java.util.Locale;
37 import java.util.Properties;
2638 import java.util.logging.Logger;
2739
2840 import org.relique.io.TableReader;
283295 String separator = DEFAULT_SEPARATOR;
284296 Character quoteChar = Character.valueOf(DEFAULT_QUOTECHAR);
285297 String quoteStyle = DEFAULT_QUOTE_STYLE;
298 String dateFormat = DEFAULT_DATE_FORMAT;
299 String timeFormat = DEFAULT_TIME_FORMAT;
300 String timestampFormat = DEFAULT_TIMESTAMP_FORMAT;
301 String timeZoneName = DEFAULT_TIME_ZONE_NAME;
302 Locale locale = null;
286303
287304 if (resultSet instanceof CsvResultSet)
288305 {
294311 separator = csvConnection.getSeparator();
295312 quoteChar = csvConnection.getQuotechar();
296313 quoteStyle = csvConnection.getQuoteStyle();
297 }
314 dateFormat = csvConnection.getDateFormat();
315 timeFormat = csvConnection.getTimeFormat();
316 timestampFormat = csvConnection.getTimestampFormat();
317 timeZoneName = csvConnection.getTimeZoneName();
318 locale = csvConnection.getLocale();
319 }
320
321 StringConverter converter = new StringConverter(dateFormat, timeFormat, timestampFormat, timeZoneName, locale);
298322
299323 ResultSetMetaData meta = null;
300324 int columnCount = 0;
324348 {
325349 if (i > 1)
326350 out.print(separator);
327 String value = resultSet.getString(i);
351 String value = null;
352
353 /*
354 * Use same dateFormat, timeFormat and timestampFormat for output as the input CSV file.
355 */
356 int columnType = meta.getColumnType(i);
357 if (columnType == Types.DATE)
358 {
359 Date d = resultSet.getDate(i);
360 if (d != null)
361 value = converter.formatDate(d);
362 }
363 else if (columnType == Types.TIME)
364 {
365 Time t = resultSet.getTime(i);
366 if (t != null)
367 value = converter.formatTime(t);
368 }
369 else if (columnType == Types.TIMESTAMP)
370 {
371 Timestamp timestamp = resultSet.getTimestamp(i);
372 if (timestamp != null)
373 value = converter.formatTimestamp(timestamp);
374 }
375 else
376 {
377 value = resultSet.getString(i);
378 }
328379 if (value != null)
329380 {
330381 if (quoteChar != null)
9090
9191 CsvDriver.writeLog("CsvPreparedStatement:executeQuery() - sql= " + templateQuery);
9292
93 setTimeoutMillis();
94 cancelled = false;
95
9396 ResultSet resultSet = executeQuery();
9497 lastResultSet = resultSet;
9598
117120 lastResultSet = null;
118121 }
119122
123 setTimeoutMillis();
124 cancelled = false;
125
120126 parser.setPlaceholdersValues(parameters);
121127 return executeParsedQuery(parser);
122128 }
3333 import java.sql.RowId;
3434 import java.sql.SQLException;
3535 import java.sql.SQLFeatureNotSupportedException;
36 import java.sql.SQLTimeoutException;
3637 import java.sql.SQLWarning;
3738 import java.sql.SQLXML;
3839 import java.sql.Statement;
868869 throw new SQLException(CsvResources.getString("closedResultSet"));
869870 }
870871
872 private void checkTimeout() throws SQLTimeoutException
873 {
874 if (statement.getTimeoutMillis() != Long.MAX_VALUE)
875 {
876 if (System.currentTimeMillis() >= statement.getTimeoutMillis())
877 throw new SQLTimeoutException();
878 }
879 }
880
871881 @Override
872882 public boolean next() throws SQLException
873883 {
874884 boolean thereWasAnAnswer;
875885
876886 checkOpen();
887 checkTimeout();
888
889 /*
890 * Has query been cancelled by another thread?
891 */
892 if (statement.isCancelled())
893 throw new SQLException(CsvResources.getString("statementCancelled"));
877894
878895 if ((this.groupByColumns != null ||
879896 this.aggregateFunctions.size() > 0 ||
5656 private int maxRows = 0;
5757 private int fetchSize = 1;
5858 private int queryTimeout = Integer.MAX_VALUE;
59 private long timeoutMillis = Long.MAX_VALUE;
5960 private int fetchDirection = ResultSet.FETCH_FORWARD;
6061 private boolean closed;
62 protected boolean cancelled;
6163
6264 protected int resultSetType = ResultSet.TYPE_SCROLL_INSENSITIVE;
6365
286288 lastResultSet = null;
287289 multipleParsers = null;
288290 }
291
292 setTimeoutMillis();
293 cancelled = false;
289294
290295 SqlParser parser = new SqlParser();
291296 try
511516 }
512517 }
513518
519 public boolean isCancelled() throws SQLException
520 {
521 return cancelled;
522 }
523
514524 @Override
515525 public void cancel() throws SQLException
516526 {
517 throw new SQLException(CsvResources.getString("methodNotSupported") + ": Statement.cancel()");
527 /*
528 * JDBC documentation states that this method may be called
529 * from a different thread to other JDBC calls.
530 * Just set a flag here, so that the next JDBC call will
531 * trigger the statement to close, avoiding any race condition.
532 */
533 cancelled = true;
518534 }
519535
520536 @Override
521537 public void clearWarnings() throws SQLException
522538 {
523539 checkOpen();
540 }
541
542 /**
543 * Set timestamp at which current query will throw an SQLTimeoutException.
544 */
545 protected void setTimeoutMillis()
546 {
547 if (queryTimeout == 0 || queryTimeout == Integer.MAX_VALUE)
548 timeoutMillis = Long.MAX_VALUE;
549 else
550 timeoutMillis = System.currentTimeMillis() + queryTimeout * 1000;
551 }
552
553 /**
554 * Get timestamp at which current query will throw an SQLTimeoutException.
555 * @return timestamp in milliseconds, or MAX_VALUE if no timeout.
556 */
557 public long getTimeoutMillis()
558 {
559 return timeoutMillis;
524560 }
525561
526562 @Override
541577 lastResultSet = null;
542578 multipleParsers = null;
543579 }
580
581 setTimeoutMillis();
582 cancelled = false;
544583
545584 /*
546585 * Execute one or more SQL statements.
6363 sb.append(separator);
6464 separator = ", ";
6565 QueryEnvEntry queryEnvEntry = (QueryEnvEntry)(expr.content);
66 sb.append(queryEnvEntry.expression.toString());
66 sb.append(queryEnvEntry.getExpression().toString());
6767 }
6868 if (tableEntries != null)
6969 {
169169 for (ParsedExpression parsedExpr : queryEntries)
170170 {
171171 QueryEnvEntry queryEnvEntry = (QueryEnvEntry)(parsedExpr.content);
172 List<String> columns = queryEnvEntry.expression.usedColumns(availableColumns);
172 List<String> columns = queryEnvEntry.getExpression().usedColumns(availableColumns);
173173 result.addAll(columns);
174174 }
175175 }
207207 for (ParsedExpression parsedExpr : queryEntries)
208208 {
209209 QueryEnvEntry queryEnvEntry = (QueryEnvEntry)(parsedExpr.content);
210 List<AggregateFunction> functions = queryEnvEntry.expression.aggregateFunctions();
210 List<AggregateFunction> functions = queryEnvEntry.getExpression().aggregateFunctions();
211211 result.addAll(functions);
212212 }
213213 }
2222
2323 class QueryEnvEntry extends Expression
2424 {
25 String key;
26 Expression expression;
25 private String key;
26 private Expression expression;
2727
2828 public QueryEnvEntry(String fieldName, Expression exp)
2929 {
3030 this.key = fieldName.toUpperCase();
3131 this.expression = exp;
3232 }
33
34 public Expression getExpression()
35 {
36 return expression;
37 }
38
39 public String getKey()
40 {
41 return key;
42 }
43
3344 public Object eval(Map<String, Object> env) throws SQLException
3445 {
3546 return expression.eval(env);
3647 }
48
3749 public String toString()
3850 {
3951 return key+": "+expression.toString();
4052 }
53
4154 public void resetAggregateFunctions()
4255 {
4356 expression.resetAggregateFunctions();
159159 /*
160160 * A logical expression such as A > 5 is not allowed as a query expression.
161161 */
162 if ((cc.expression instanceof LogicalExpression) ||
163 (cc.expression.isValid() == false))
162 if ((cc.getExpression() instanceof LogicalExpression) ||
163 (cc.getExpression().isValid() == false))
164164 {
165165 throw new SQLException("invalidQueryExpression");
166166 }
167167
168 String key = cc.key;
168 String key = cc.getKey();
169169 for (int i = 0; i < tableNames.size(); i++)
170170 {
171171 if (tableAliases.get(i) != null && key.startsWith(tableAliases.get(i) + "."))
179179 break;
180180 }
181181 }
182 environment.add(new Object[]{ key, cc.expression });
182 environment.add(new Object[]{ key, cc.getExpression() });
183183 }
184184 }
185185
2727 import java.text.ParseException;
2828 import java.text.SimpleDateFormat;
2929 import java.util.ArrayList;
30 import java.util.Calendar;
3031 import java.util.GregorianCalendar;
3132 import java.util.HashMap;
3233 import java.util.List;
5152 private Pattern timestampPattern;
5253 private SimpleDateFormat timestampFormat;
5354 private SimpleDateFormat simpleDateFormat;
55 private int currentYear;
5456
5557 public StringConverter(String dateformat, String timeformat, String timestampformat,
5658 String timeZoneName)
7577 * SimpleDateFormat parsing required?
7678 */
7779 // TODO prefer to use SimpleDateFormat for everything but existing regex not 100% compatible
78 String upper = dateformat.toUpperCase();
80 String upper = dateformat.toUpperCase(Locale.US);
7981 boolean useSimpleDateFormat = false;
8082 if (upper.contains("MMM"))
8183 {
132134
133135 TimeZone timeZone = TimeZone.getTimeZone(timeZoneName);
134136 calendar = new GregorianCalendar();
137 calendar.setTimeInMillis(System.currentTimeMillis());
138 currentYear = calendar.get(Calendar.YEAR);
135139 calendar.clear();
136140 calendar.setTimeZone(timeZone);
137141 if (timestampformat != null && timestampformat.length() > 0)
333337 private String makeISODate(String date, String format)
334338 {
335339 // first memorize the original order of the groups.
336 format = format.toLowerCase();
340 format = format.toLowerCase(Locale.US);
337341 int dpos = format.indexOf('d');
338342 int mpos = format.indexOf('m');
339343 int ypos = format.indexOf('y');
344 int ylen = 4;
340345
341346 int day = 1, month = 1, year = 1;
342347 if (dpos > mpos)
369374 part = Pattern.compile("y+");
370375 m = part.matcher(format);
371376 if (m.find())
377 {
378 ylen = m.end() - m.start();
372379 format = format.replace(m.group(), "([0-9]{" + (m.end() - m.start()) + ",4})");
380 }
373381
374382 format = format + ".*";
375383
379387 {
380388 // and return the groups in ISO8601 format.
381389 String yearGroup = m.group(year);
390 if (yearGroup.length() == 2 && ylen == 2)
391 {
392 // Parsed year only contains two digits. Determine full year including
393 // century using same logic as java.text.SimpleDateFormat:
394 // select century that is less than 20 years in the future and
395 // less than 80 years in the past.
396 int century = currentYear / 100;
397 int proposedYear = (century * 100) + Integer.parseInt(yearGroup);
398 if (proposedYear - currentYear > 20)
399 proposedYear -= 100;
400 if (currentYear - proposedYear > 80)
401 proposedYear += 100;
402 yearGroup = String.format("%04d", proposedYear);
403 }
382404 String monthGroup = m.group(month);
383405 if (monthGroup.length() < 2)
384406 monthGroup = "0" + monthGroup;
424446 }
425447 }
426448
449 /**
450 * Create date string in format accepted by method {@link #parseDate(String) parseDate}.
451 * @param d date to format.
452 * @return formatted date.
453 */
454 public String formatDate(Date d)
455 {
456 String formatted = null;
457
458 if (d != null)
459 {
460 if (simpleDateFormat != null)
461 {
462 formatted = simpleDateFormat.format(d);
463 }
464 else
465 {
466 formatted = dateFormat.toLowerCase(Locale.US);
467 Calendar gregorianCalendar = new GregorianCalendar();
468 gregorianCalendar.setTime(d);
469
470 // use regular expressions to replace in day, month, year in format string
471 Pattern part;
472 Matcher m;
473
474 part = Pattern.compile("d+");
475 m = part.matcher(formatted);
476 if (m.find())
477 {
478 int patternLength = m.end() - m.start();
479 String dayOfMonth = Integer.toString(gregorianCalendar.get(Calendar.DAY_OF_MONTH));
480 while (dayOfMonth.length() < patternLength)
481 dayOfMonth = "0" + dayOfMonth;
482 formatted = formatted.replace(m.group(), dayOfMonth);
483 }
484 part = Pattern.compile("m+");
485 m = part.matcher(formatted);
486 if (m.find())
487 {
488 int patternLength = m.end() - m.start();
489 String month = Integer.toString(gregorianCalendar.get(Calendar.MONTH) + 1);
490 while (month.length() < patternLength)
491 month = "0" + month;
492 formatted = formatted.replace(m.group(), month);
493 }
494 part = Pattern.compile("y+");
495 m = part.matcher(formatted);
496 if (m.find())
497 {
498 int patternLength = m.end() - m.start();
499 int fullYear = gregorianCalendar.get(Calendar.YEAR);
500 if (patternLength == 2)
501 fullYear = fullYear % 100;
502 String year = Integer.toString(fullYear);
503 while (year.length() < patternLength)
504 year = "0" + year;
505 formatted = formatted.replace(m.group(), year);
506 }
507 }
508 }
509 return formatted;
510 }
511
427512 public Time parseTime(String str)
428513 {
429514 try
450535 {
451536 return null;
452537 }
538 }
539
540 /**
541 * Create time string in format accepted by method {@link #parseTime(String) parseTime}.
542 * @param t time to format.
543 * @return formatted time.
544 */
545 public String formatTime(Time t)
546 {
547 String formatted = null;
548
549 if (t != null)
550 {
551 formatted = simpleTimeFormat.format(t);
552 }
553 return formatted;
453554 }
454555
455556 public Timestamp parseTimestamp(String str)
488589 {
489590 }
490591 return result;
592 }
593
594 /**
595 * Create timestamp string in format accepted by method {@link #parseTimestamp(String) parseTimestamp}.
596 * @param timestamp timestamp to format.
597 * @return formatted timestamp.
598 */
599 public String formatTimestamp(Timestamp timestamp)
600 {
601 String formatted = null;
602
603 if (timestamp != null)
604 {
605 if (timestampFormat != null)
606 {
607 formatted = timestampFormat.format(timestamp);
608 }
609 else
610 {
611 calendar.setTime(timestamp);
612 int year = calendar.get(Calendar.YEAR);
613 int month = calendar.get(Calendar.MONTH) + 1;
614 int dayOfMonth = calendar.get(Calendar.DAY_OF_MONTH);
615 int hourOfDay = calendar.get(Calendar.HOUR_OF_DAY);
616 int minutes = calendar.get(Calendar.MINUTE);
617 int seconds = calendar.get(Calendar.SECOND);
618 formatted = String.format("%04d-%02d-%02d %02d:%02d:%02d", year, month, dayOfMonth, hourOfDay, minutes, seconds);
619 }
620 }
621 return formatted;
491622 }
492623
493624 public InputStream parseAsciiStream(String str)
558689
559690 public Class<?> forSQLName(String sqlTypeName)
560691 {
561 sqlTypeName = sqlTypeName.toLowerCase();
692 sqlTypeName = sqlTypeName.toLowerCase(Locale.US);
562693 return forSQLNameMap.get(sqlTypeName);
563694 }
564695
572703 public static Object getLiteralForTypeName(String sqlTypeName)
573704 {
574705 Object retval = null;
575 sqlTypeName = sqlTypeName.toLowerCase();
706 sqlTypeName = sqlTypeName.toLowerCase(Locale.US);
576707 if (sqlTypeName.equals("string"))
577708 retval = "";
578709 else if (sqlTypeName.equals("boolean"))
699699 (expression = binaryOperation()((<AS>)?alias = columnAlias())?
700700 {
701701 if (alias != null)
702 result = new QueryEnvEntry(((ColumnName)alias).columnName, expression);
702 result = new QueryEnvEntry(((ColumnName)alias).getColumnName(), expression);
703703 else if (expression instanceof ColumnName)
704 result = new QueryEnvEntry(((ColumnName)expression).columnName, expression);
704 result = new QueryEnvEntry(((ColumnName)expression).getColumnName(), expression);
705705 else
706706 result = new QueryEnvEntry(expression.toString(), expression);
707707 return new ParsedExpression(result);
11311131 Number value = null;
11321132 digits = sign+t.image;
11331133 isLong = false;
1134 if (digits.toUpperCase().endsWith("L"))
1134 if (digits.endsWith("L") || digits.endsWith("l"))
11351135 {
11361136 digits = digits.substring(0, digits.length() - 1);
11371137 isLong = true;
6969 notNamedSavepoint=Not a named Savepoint
7070 orderByNotInGroupBy=ORDER BY column not included in GROUP BY
7171 parameterIndex=Parameter index out of range
72 statementCancelled=Statement cancelled
7273 statementClosed=Statement is already closed
7374 streamClosed=Stream is already closed
7475 subqueryOneColumn=Subquery must return one column
578578 }
579579
580580 @Test
581 public void testDatabaseMetadataColumnsWithIndexedFiles() throws SQLException
582 {
583 Properties props = new Properties();
584 props.put("fileExtension", ".txt");
585 props.put("fileTailPattern", "-([0-9]{3})-([0-9]{8})");
586 props.put("fileTailParts", "location,file_date");
587 props.put("indexedFiles", "True");
588 Connection conn = DriverManager.getConnection("jdbc:relique:csv:"
589 + filePath, props);
590 DatabaseMetaData metadata = conn.getMetaData();
591 ResultSet results = metadata.getColumns(null, null, "test", null);
592 assertTrue(results.next());
593 assertEquals("Wrong table name", "test", results.getString("TABLE_NAME"));
594 assertEquals("Wrong column name", "Datum", results.getString("COLUMN_NAME"));
595 assertTrue(results.next());
596 assertEquals("Wrong table name", "test", results.getString("TABLE_NAME"));
597 assertEquals("Wrong column name", "Tijd", results.getString("COLUMN_NAME"));
598 results.close();
599 conn.close();
600 }
601
602 @Test
581603 public void testDatabaseMetadataProcedures() throws SQLException
582604 {
583605 Connection conn = DriverManager.getConnection("jdbc:relique:csv:"
34563478 }
34573479
34583480 @Test
3481 public void testStatementCancelled() throws SQLException
3482 {
3483 Connection conn = DriverManager.getConnection("jdbc:relique:csv:"
3484 + filePath);
3485 Statement stmt = conn.createStatement();
3486
3487 try
3488 {
3489 ResultSet results = stmt.executeQuery("SELECT * FROM sample");
3490 stmt.cancel();
3491 results.next();
3492 fail("expected exception java.sql.SQLException: Statement cancelled");
3493 }
3494 catch (SQLException e)
3495 {
3496 assertEquals("wrong exception and/or exception text!",
3497 "java.sql.SQLException: " + CsvResources.getString("statementCancelled"),
3498 "" + e);
3499 }
3500
3501 conn.close();
3502 }
3503
3504 @Test
34593505 public void testTrimValues() throws SQLException
34603506 {
34613507 Properties props = new Properties();
47204766 }
47214767
47224768 @Test
4769 public void testWriteToCsvWithDates() throws SQLException, UnsupportedEncodingException, IOException
4770 {
4771 Properties props = new Properties();
4772 props.put("columnTypes", "Int,Date,Time,Timestamp");
4773 props.put("dateFormat", "dd-MMM-yy");
4774 props.put("timeFormat", "hh:mm:ss.SSS aa");
4775 props.put("timestampFormat", "yyyy-MM-dd'T'HH:mm:ss.SSS");
4776 if (!Locale.getDefault().equals(Locale.US))
4777 {
4778 /*
4779 * Ensure that test passes when running on non-English language computers.
4780 */
4781 props.put("locale", Locale.US.toString());
4782 }
4783
4784 Connection conn = DriverManager.getConnection("jdbc:relique:csv:"
4785 + filePath, props);
4786 Statement stmt = conn.createStatement();
4787 ResultSet results = stmt.executeQuery("SELECT * FROM sunil_date_time");
4788 ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
4789 PrintStream printStream = new PrintStream(byteStream);
4790
4791 /*
4792 * Check that writing ResultSet to CSV file generates exactly the same CSV file
4793 * that the query was originally read from.
4794 */
4795 boolean writeHeaderLine = true;
4796 CsvDriver.writeToCsv(results, printStream, writeHeaderLine);
4797
4798 BufferedReader reader1 = null;
4799 BufferedReader reader2 = null;
4800 try
4801 {
4802 reader1 = new BufferedReader(new FileReader(filePath + File.separator + "sunil_date_time.csv"));
4803 reader2 = new BufferedReader(new StringReader(byteStream.toString("US-ASCII")));
4804 String line1 = reader1.readLine();
4805 String line2 = reader2.readLine();
4806
4807 while (line1 != null || line2 != null)
4808 {
4809 assertTrue("line1 is null", line1 != null);
4810 assertTrue("line2 is null", line2 != null);
4811 assertTrue("lines do not match", line1.equalsIgnoreCase(line2));
4812 line1 = reader1.readLine();
4813 line2 = reader2.readLine();
4814 }
4815 assertNull("line1 not empty", line1);
4816 assertNull("line2 not empty", line2);
4817 }
4818 finally
4819 {
4820 if (reader1 != null)
4821 reader1.close();
4822 if (reader2 != null)
4823 reader2.close();
4824 }
4825 }
4826
4827 @Test
47234828 public void testBooleanConversion() throws SQLException,
47244829 ParseException
47254830 {
0 ID,D,T
1 100,25-NOV-13,01:29:07.613 PM
2 200,06-DEC-13,11:52:21.342 AM
0 ID,D,T,TS
1 100,25-NOV-13,01:29:07.613 PM,2013-11-25T01:29:07.613
2 200,06-DEC-13,11:52:21.342 AM,2013-12-06T11:52:21.342