[#1438] Add Result<Record> Factory.fetchFromCSV(String)

This commit is contained in:
Lukas Eder 2012-05-22 21:31:24 +02:00
parent e37c5e56e2
commit aefd24c007
5 changed files with 165 additions and 0 deletions

View File

@ -35,6 +35,7 @@
*/
package org.jooq.test._.testcases;
import static java.util.Arrays.asList;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertTrue;
@ -124,6 +125,46 @@ extends BaseTest<A, AP, B, S, B2S, BS, L, X, DATE, BOOL, D, T, U, I, IPK, T658,
}
}
@Test
public void testFetchFromCSV() throws Exception {
Result<Record> result1 = create().fetchFromCSV(
"A,B,\"C\",\"\"\"D\"\n" +
"1,,a,b\n" +
"1,2,a\n" +
"1,2,a,b,c");
// Check meta data
assertEquals(4, result1.getFields().size());
assertEquals(3, result1.size());
assertEquals("A", result1.getField(0).getName());
assertEquals("B", result1.getField(1).getName());
assertEquals("C", result1.getField(2).getName());
assertEquals("\"D", result1.getField(3).getName());
// Check column correctness
assertEquals(asList("1", "1", "1"), result1.getValues(0));
assertEquals(asList(1, 1, 1), result1.getValues(0, Integer.class));
assertEquals(asList("", "2", "2"), result1.getValues(1));
assertEquals(asList(null, 2, 2), result1.getValues(1, Integer.class));
assertEquals(asList("a", "a", "a"), result1.getValues(2));
assertEquals(asList("b", null, "b"), result1.getValues(3));
// Check row correctness
assertEquals(asList("1", "", "a", "b"), asList(result1.get(0).intoArray()));
assertEquals(asList("1", "2", "a", null), asList(result1.get(1).intoArray()));
assertEquals(asList("1", "2", "a", "b"), asList(result1.get(2).intoArray()));
// Factory.fetchFromCSV() should be the inverse of Result.formatCSV()
// ... apart from the loss of type information
String csv = create().selectFrom(TBook()).orderBy(TBook_ID()).fetch().formatCSV();
Result<Record> result2 = create().fetchFromCSV(csv);
assertEquals(4, result2.size());
assertEquals(BOOK_IDS, result2.getValues(TBook_ID(), Integer.class));
assertEquals(BOOK_AUTHOR_IDS, result2.getValues(TBook_AUTHOR_ID(), Integer.class));
assertEquals(BOOK_TITLES, result2.getValues(TBook_TITLE()));
}
@Test
public void testFormatCSV() throws Exception {
List<Field<?>> fields = TBook().getFields();

View File

@ -1150,6 +1150,11 @@ public abstract class jOOQAbstractTest<
new FormatTests(this).testFormatHTML();
}
@Test
public void testFetchFromCSV() throws Exception {
new FormatTests(this).testFetchFromCSV();
}
@Test
public void testFormatCSV() throws Exception {
new FormatTests(this).testFormatCSV();

View File

@ -225,6 +225,62 @@ public interface FactoryOperations extends Configuration {
@Support
Result<Record> fetch(ResultSet rs) throws DataAccessException;
/**
* Fetch all data from a CSV string.
* <p>
* This is the same as calling <code>fetchFromCSV(string, ',')</code> and
* the inverse of calling {@link Result#formatCSV()}. The first row of the
* CSV data is required to hold field name information. Subsequent rows may
* contain data, which is interpreted as {@link String}. Use the various
* conversion methods to retrieve other data types from the
* <code>Result</code>:
* <ul>
* <li> {@link Result#getValues(Field, Class)}</li>
* <li> {@link Result#getValues(int, Class)}</li>
* <li> {@link Result#getValues(String, Class)}</li>
* <li> {@link Result#getValues(Field, Converter)}</li>
* <li> {@link Result#getValues(int, Converter)}</li>
* <li> {@link Result#getValues(String, Converter)}</li>
* </ul>
* <p>
* Missing values result in <code>null</code>. Empty values result in empty
* <code>Strings</code>
*
* @param string The CSV string
* @return The transformed result
* @throws DataAccessException If anything went wrong parsing the CSV file
* @see #fetchFromCSV(String, char)
*/
Result<Record> fetchFromCSV(String string) throws DataAccessException;
/**
* Fetch all data from a CSV string.
* <p>
* This is inverse of calling {@link Result#formatCSV(char)}. The first row
* of the CSV data is required to hold field name information. Subsequent
* rows may contain data, which is interpreted as {@link String}. Use the
* various conversion methods to retrieve other data types from the
* <code>Result</code>:
* <ul>
* <li> {@link Result#getValues(Field, Class)}</li>
* <li> {@link Result#getValues(int, Class)}</li>
* <li> {@link Result#getValues(String, Class)}</li>
* <li> {@link Result#getValues(Field, Converter)}</li>
* <li> {@link Result#getValues(int, Converter)}</li>
* <li> {@link Result#getValues(String, Converter)}</li>
* </ul>
* <p>
* Missing values result in <code>null</code>. Empty values result in empty
* <code>Strings</code>
*
* @param string The CSV string
* @param delimiter The delimiter to expect between records
* @return The transformed result
* @throws DataAccessException If anything went wrong parsing the CSV file
* @see #fetchFromCSV(String)
*/
Result<Record> fetchFromCSV(String string, char delimiter) throws DataAccessException;
// -------------------------------------------------------------------------
// XXX Global Query factory
// -------------------------------------------------------------------------

View File

@ -55,6 +55,7 @@ import static org.jooq.impl.Util.combine;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.StringReader;
import java.io.StringWriter;
import java.math.BigDecimal;
import java.math.BigInteger;
@ -138,6 +139,7 @@ import org.jooq.exception.DataAccessException;
import org.jooq.exception.InvalidResultException;
import org.jooq.exception.SQLDialectNotSupportedException;
import org.jooq.tools.JooqLogger;
import org.jooq.tools.csv.CSVReader;
import org.jooq.types.DayToSecond;
/**
@ -1428,6 +1430,57 @@ public class Factory implements FactoryOperations {
}
}
/**
* {@inheritDoc}
*/
@Override
public final Result<Record> fetchFromCSV(String string) {
return fetchFromCSV(string, ',');
}
/**
* {@inheritDoc}
*/
@Override
public final Result<Record> fetchFromCSV(String string, char delimiter) {
CSVReader reader = new CSVReader(new StringReader(string), delimiter);
List<String[]> all = null;
try {
all = reader.readAll();
}
catch (IOException e) {
throw new DataAccessException("Could not read the CSV string", e);
}
FieldList fields = new FieldList();
if (all.size() == 0) {
return new ResultImpl<Record>(this, fields);
}
else {
for (String name : all.get(0)) {
fields.add(fieldByName(String.class, name));
}
Result<Record> result = new ResultImpl<Record>(this, fields);
if (all.size() > 1) {
for (String[] values : all.subList(1, all.size())) {
Record record = new RecordImpl(fields);
for (int i = 0; i < Math.min(values.length, fields.size()); i++) {
Util.setValue(record, fields.get(i), values[i]);
}
result.add(record);
}
}
return result;
}
}
// -------------------------------------------------------------------------
// XXX Global Condition factory
// -------------------------------------------------------------------------

View File

@ -385,6 +385,16 @@ public final class FactoryProxy implements FactoryOperations {
return getDelegate().fetch(rs);
}
@Override
public final Result<Record> fetchFromCSV(String string) {
return null;
}
@Override
public final Result<Record> fetchFromCSV(String string, char delimiter) {
return null;
}
@Override
public final Result<Record> fetch(String sql) {
return getDelegate().fetch(sql);