Read column types from header of CSV file.
diff --git a/README.md b/README.md
index c37c547..4d85705 100644
--- a/README.md
+++ b/README.md
@@ -9,7 +9,7 @@
 Download and build
 ==================
 
-You need Java (1.7 or higher) and maven (2 or higher).
+You need Java (1.5 or higher; 1.7 preferred) and maven (2 or higher).
 
     $ git clone git://github.com/julianhyde/optiq-csv.git
     $ cd optiq-csv
@@ -19,7 +19,10 @@
 ===========
 
     $ ./sqlline
-    sqlline> connect jdbc:optiq:model=target/test-classes/model.json admin admin
+    sqlline> !connect jdbc:optiq:model=target/test-classes/model.json admin admin
+    sqlline> select * from emp;
+    sqlline> !tables
+    sqlline> !quit
 
 
 Advanced use
diff --git a/src/main/java/net/hydromatic/optiq/impl/csv/CsvSchema.java b/src/main/java/net/hydromatic/optiq/impl/csv/CsvSchema.java
index 37cbf56..8f97ad3 100644
--- a/src/main/java/net/hydromatic/optiq/impl/csv/CsvSchema.java
+++ b/src/main/java/net/hydromatic/optiq/impl/csv/CsvSchema.java
@@ -17,16 +17,19 @@
 */
 package net.hydromatic.optiq.impl.csv;
 
+import au.com.bytecode.opencsv.CSVReader;
 import net.hydromatic.linq4j.*;
 import net.hydromatic.linq4j.expressions.Expression;
 
 import net.hydromatic.optiq.*;
 import net.hydromatic.optiq.impl.TableInSchemaImpl;
 
+import net.hydromatic.optiq.impl.java.JavaTypeFactory;
+import net.hydromatic.optiq.jdbc.OptiqConnection;
 import org.eigenbase.reltype.RelDataType;
+import org.eigenbase.util.Pair;
 
-import java.io.File;
-import java.io.FilenameFilter;
+import java.io.*;
 import java.util.*;
 
 /**
@@ -37,6 +40,8 @@
   private final Schema parentSchema;
   private final File directoryFile;
   private final Expression expression;
+  private final JavaTypeFactory typeFactory;
+  private final RelDataType stringType;
   private Map<String, TableInSchema> map;
 
   public CsvSchema(
@@ -47,6 +52,8 @@
     this.parentSchema = parentSchema;
     this.directoryFile = directoryFile;
     this.expression = expression;
+    this.typeFactory = ((OptiqConnection) getQueryProvider()).getTypeFactory();
+    this.stringType = typeFactory.createJavaType(String.class);
   }
 
   public Expression getExpression() {
@@ -103,9 +110,9 @@
           tableName = tableName.substring(
               0, tableName.length() - ".csv".length());
         }
-        final RelDataType rowType = null;
-        final CsvTable table = new CsvTable(
-            String[].class, rowType, this, tableName);
+        final RelDataType rowType = deduceRowType(file);
+        final CsvTable table =
+            new CsvTable(String[].class, rowType, this, tableName);
         map.put(
             tableName,
             new TableInSchemaImpl(this, tableName, TableType.TABLE, table));
@@ -113,6 +120,54 @@
     }
     return map;
   }
+
+  private RelDataType deduceRowType(File file) {
+    final List<RelDataType> types = new ArrayList<RelDataType>();
+    final List<String> names = new ArrayList<String>();
+    CSVReader reader = null;
+    try {
+      reader = new CSVReader(new FileReader(file));
+      final String[] strings = reader.readNext();
+      for (String string : strings) {
+        RelDataType type;
+        String name;
+        final int colon = string.indexOf(':');
+        if (colon >= 0) {
+          name = string.substring(0, colon);
+          String typeString = string.substring(colon + 1);
+          if (typeString.equals("String")) {
+            type = stringType;
+          } else {
+            try {
+              type = typeFactory.createJavaType(Class.forName(typeString));
+            } catch (ClassNotFoundException e) {
+              type = stringType;
+            }
+          }
+        } else {
+          name = string;
+          type = stringType;
+        }
+        names.add(name);
+        types.add(type);
+      }
+    } catch (IOException e) {
+      // ignore
+    } finally {
+      if (reader != null) {
+        try {
+          reader.close();
+        } catch (IOException e) {
+          // ignore
+        }
+      }
+    }
+    if (names.isEmpty()) {
+      names.add("line");
+      types.add(stringType);
+    }
+    return typeFactory.createStructType(Pair.zip(names, types));
+  }
 }
 
 // End CsvSchema.java
diff --git a/src/main/java/net/hydromatic/optiq/impl/csv/CsvTableScan.java b/src/main/java/net/hydromatic/optiq/impl/csv/CsvTableScan.java
index 861f293..d029be7 100644
--- a/src/main/java/net/hydromatic/optiq/impl/csv/CsvTableScan.java
+++ b/src/main/java/net/hydromatic/optiq/impl/csv/CsvTableScan.java
@@ -21,6 +21,7 @@
 import net.hydromatic.optiq.impl.java.JavaTypeFactory;
 import net.hydromatic.optiq.rules.java.*;
 
+import org.eigenbase.rel.RelNode;
 import org.eigenbase.rel.TableAccessRelBase;
 import org.eigenbase.relopt.*;
 import org.eigenbase.reltype.RelDataType;
@@ -49,7 +50,7 @@
       List<String> fieldList)
   {
     super(
-        cluster, cluster.traitSetOf(Convention.NONE), table);
+        cluster, cluster.traitSetOf(EnumerableConvention.ARRAY), table);
     this.csvTable = csvTable;
     this.fieldList = fieldList;
     this.physType =
@@ -66,6 +67,12 @@
   }
 
   @Override
+  public RelNode copy(RelTraitSet traitSet, List<RelNode> inputs) {
+    assert inputs.isEmpty();
+    return new CsvTableScan(getCluster(), table, csvTable, fieldList);
+  }
+
+  @Override
   public void explain(RelOptPlanWriter pw) {
     pw.explain(
         this,