blob: 6c5bbe2c6bfa1bb138bcc37f5f44840aed4d8476 [file] [log] [blame]
/*
// Licensed to Julian Hyde under one or more contributor license
// agreements. See the NOTICE file distributed with this work for
// additional information regarding copyright ownership.
//
// Julian Hyde licenses this file to you under the Apache License,
// Version 2.0 (the "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at:
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
*/
package net.hydromatic.optiq.test;
import net.hydromatic.linq4j.function.Function1;
import org.junit.Assert;
import org.junit.Ignore;
import org.junit.Test;
import java.io.PrintStream;
import java.sql.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Properties;
/**
* Unit test of the Optiq adapter for CSV.
*/
public class CsvTest {
private void close(Connection connection, Statement statement) {
if (statement != null) {
try {
statement.close();
} catch (SQLException e) {
// ignore
}
}
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
// ignore
}
}
}
public static String toLinux(String s) {
return s.replaceAll("\r\n", "\n");
}
/**
* Tests the vanity driver.
*/
@Ignore
@Test public void testVanityDriver() throws SQLException {
Properties info = new Properties();
Connection connection =
DriverManager.getConnection("jdbc:csv:", info);
connection.close();
}
/**
* Tests the vanity driver with properties in the URL.
*/
@Ignore
@Test public void testVanityDriverArgsInUrl() throws SQLException {
Connection connection =
DriverManager.getConnection(
"jdbc:csv:"
+ "directory='foo'");
connection.close();
}
/** Tests an inline schema with a non-existent directory. */
@Test public void testBadDirectory() throws SQLException {
Properties info = new Properties();
info.put("model",
"inline:"
+ "{\n"
+ " version: '1.0',\n"
+ " schemas: [\n"
+ " {\n"
+ " type: 'custom',\n"
+ " name: 'bad',\n"
+ " factory: 'net.hydromatic.optiq.impl.csv.CsvSchemaFactory',\n"
+ " operand: {\n"
+ " directory: '/does/not/exist'\n"
+ " }\n"
+ " }\n"
+ " ]\n"
+ "}");
Connection connection =
DriverManager.getConnection("jdbc:optiq:", info);
// must print "directory ... not found" to stdout, but not fail
ResultSet tables =
connection.getMetaData().getTables(null, null, null, null);
tables.next();
tables.close();
connection.close();
}
/**
* Reads from a table.
*/
@Test public void testSelect() throws SQLException {
checkSql("model", "select * from EMPS");
}
@Test public void testSelectSingleProject() throws SQLException {
checkSql("smart", "select name from EMPS");
}
@Test public void testCustomTable() throws SQLException {
checkSql("model-with-custom-table", "select * from CUSTOM_TABLE.EMPS");
}
@Test public void testPushDownProjectDumb() throws SQLException {
// rule does not fire, because we're using 'dumb' tables in simple model
checkSql("model", "explain plan for select * from EMPS",
"PLAN=EnumerableTableAccessRel(table=[[SALES, EMPS]])\n");
}
@Test public void testPushDownProject() throws SQLException {
checkSql("smart", "explain plan for select * from EMPS",
"PLAN=CsvTableScan(table=[[SALES, EMPS]], fields=[[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]])\n");
}
@Test public void testPushDownProject2() throws SQLException {
checkSql("smart", "explain plan for select name, empno from EMPS",
"PLAN=CsvTableScan(table=[[SALES, EMPS]], fields=[[1, 0]])\n");
// make sure that it works...
checkSql("smart", "select name, empno from EMPS",
"NAME=Fred; EMPNO=100",
"NAME=Eric; EMPNO=110",
"NAME=John; EMPNO=110",
"NAME=Wilma; EMPNO=120",
"NAME=Alice; EMPNO=130");
}
@Test public void testJson() throws SQLException {
checkSql("model", "select _MAP['id'] as id,\n"
+ " _MAP['title'] as title,\n"
+ " CHAR_LENGTH(CAST(_MAP['title'] AS VARCHAR(30))) as len\n"
+ " from \"archers\"",
"ID=19990101; TITLE=Washday blues.; LEN=14",
"ID=19990103; TITLE=Daniel creates a drama.; LEN=23");
}
private void checkSql(String model, String sql) throws SQLException {
checkSql(sql, model, output());
}
private Function1<ResultSet, Void> output() {
return new Function1<ResultSet, Void>() {
public Void apply(ResultSet resultSet) {
try {
output(resultSet, System.out);
} catch (SQLException e) {
throw new RuntimeException(e);
}
return null;
}
};
}
private void checkSql(String model, String sql, final String... expected)
throws SQLException {
checkSql(sql, model, expect(expected));
}
/** Returns a function that checks the contents of a result set against an
* expected string. */
private static Function1<ResultSet, Void> expect(final String... expected) {
return new Function1<ResultSet, Void>() {
public Void apply(ResultSet resultSet) {
try {
final List<String> lines = new ArrayList<String>();
CsvTest.collect(lines, resultSet);
Assert.assertEquals(Arrays.asList(expected), lines);
} catch (SQLException e) {
throw new RuntimeException(e);
}
return null;
}
};
}
private void checkSql(String sql, String model, Function1<ResultSet, Void> fn)
throws SQLException {
Connection connection = null;
Statement statement = null;
try {
Properties info = new Properties();
info.put("model", "target/test-classes/" + model + ".json");
connection = DriverManager.getConnection("jdbc:optiq:", info);
statement = connection.createStatement();
final ResultSet resultSet =
statement.executeQuery(
sql);
fn.apply(resultSet);
} finally {
close(connection, statement);
}
}
private static void collect(List<String> result, ResultSet resultSet)
throws SQLException {
final StringBuilder buf = new StringBuilder();
while (resultSet.next()) {
buf.setLength(0);
int n = resultSet.getMetaData().getColumnCount();
String sep = "";
for (int i = 1; i <= n; i++) {
buf.append(sep)
.append(resultSet.getMetaData().getColumnLabel(i))
.append("=")
.append(resultSet.getString(i));
sep = "; ";
}
result.add(toLinux(buf.toString()));
}
}
private void output(ResultSet resultSet, PrintStream out)
throws SQLException {
final ResultSetMetaData metaData = resultSet.getMetaData();
final int columnCount = metaData.getColumnCount();
while (resultSet.next()) {
for (int i = 1;; i++) {
out.print(resultSet.getString(i));
if (i < columnCount) {
out.print(", ");
} else {
out.println();
break;
}
}
}
}
@Test public void testJoinOnString() throws SQLException {
checkSql("smart",
"select * from emps join depts on emps.name = depts.name");
}
@Test public void testWackyColumns() throws SQLException {
checkSql("select * from wacky_column_names where false", "bug",
expect());
checkSql(
"select \"joined at\", \"naME\" from wacky_column_names where \"2gender\" = 'F'",
"bug",
expect(
"joined at=2005-09-07; naME=Wilma",
"joined at=2007-01-01; naME=Alice"));
}
@Test public void testBoolean() throws SQLException {
checkSql("smart",
"select empno, slacker from emps where slacker",
"EMPNO=100; SLACKER=true");
}
@Test public void testDateType() throws SQLException {
Properties info = new Properties();
info.put("model", "target/test-classes/bug.json");
Connection connection = DriverManager.getConnection("jdbc:optiq:", info);
try {
ResultSet res = connection.getMetaData().getColumns(null, null,
"DATE", "JOINEDAT");
res.next();
Assert.assertEquals(res.getInt("DATA_TYPE"), java.sql.Types.DATE);
res = connection.getMetaData().getColumns(null, null,
"DATE", "JOINTIME");
res.next();
Assert.assertEquals(res.getInt("DATA_TYPE"), java.sql.Types.TIME);
res = connection.getMetaData().getColumns(null, null,
"DATE", "JOINTIMES");
res.next();
Assert.assertEquals(res.getInt("DATA_TYPE"), java.sql.Types.TIMESTAMP);
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery(
"select \"JOINEDAT\", \"JOINTIME\", \"JOINTIMES\" from \"DATE\" where EMPNO = 100");
resultSet.next();
// date
Assert.assertEquals(java.sql.Date.class, resultSet.getDate(1).getClass());
Assert.assertEquals(java.sql.Date.valueOf("1996-08-03"),
resultSet.getDate(1));
// time
Assert.assertEquals(java.sql.Time.class, resultSet.getTime(2).getClass());
Assert.assertEquals(java.sql.Time.valueOf("00:01:02"),
resultSet.getTime(2));
// timestamp
Assert.assertEquals(java.sql.Timestamp.class,
resultSet.getTimestamp(3).getClass());
Assert.assertEquals(java.sql.Timestamp.valueOf("1996-08-03 00:01:02"),
resultSet.getTimestamp(3));
} finally {
connection.close();
}
}
}
// End CsvTest.java