/**
* Copyright (C) 2009-2013 FoundationDB, LLC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.foundationdb.server.service.externaldata;
import com.foundationdb.ais.model.AkibanInformationSchema;
import com.foundationdb.ais.model.Column;
import com.foundationdb.ais.model.Table;
import com.foundationdb.ais.model.TableName;
import com.foundationdb.server.service.ServiceManager;
import com.foundationdb.server.service.config.ConfigurationService;
import com.foundationdb.server.service.servicemanager.GuicedServiceManager;
import com.foundationdb.server.test.it.ITBase;
import com.foundationdb.server.test.it.qp.TestRow;
import com.foundationdb.qp.operator.QueryContext;
import com.foundationdb.qp.operator.SimpleQueryContext;
import com.foundationdb.qp.operator.StoreAdapter;
import com.foundationdb.qp.row.Row;
import com.foundationdb.qp.rowtype.RowType;
import com.foundationdb.qp.rowtype.Schema;
import com.foundationdb.qp.util.SchemaCache;
import com.foundationdb.server.types.FormatOptions;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.*;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
public class ExternalDataServiceIT extends ITBase
{
public static final String SCHEMA = "test";
public static final boolean WITH_TXN = true;
private static FormatOptions options;
@Override
protected GuicedServiceManager.BindingsConfigurationProvider serviceBindingsProvider() {
return super.serviceBindingsProvider()
.bindAndRequire(ExternalDataService.class, ExternalDataServiceImpl.class);
}
@Override
protected Map<String, String> startupConfigProperties() {
return uniqueStartupConfigProperties(getClass());
}
@Before
public void createData() {
int c = createTable(SCHEMA, "c",
"cid INT PRIMARY KEY NOT NULL",
"name VARCHAR(32)");
int o = createTable(SCHEMA, "o",
"oid INT PRIMARY KEY NOT NULL",
"cid INT NOT NULL",
"GROUPING FOREIGN KEY(cid) REFERENCES c(cid)",
"order_date DATE");
int i = createTable(SCHEMA, "i",
"iid INT PRIMARY KEY NOT NULL",
"oid INT NOT NULL",
"GROUPING FOREIGN KEY(oid) REFERENCES o(oid)",
"sku VARCHAR(10) NOT NULL");
int a = createTable(SCHEMA, "a",
"aid INT PRIMARY KEY NOT NULL",
"cid INT NOT NULL",
"GROUPING FOREIGN KEY(cid) REFERENCES c(cid)",
"state CHAR(2)");
writeRow(c, 1, "Smith");
writeRow(o, 101, 1, "2012-12-12");
writeRow(i, 10101, 101, "ABCD");
writeRow(i, 10102, 101, "1234");
writeRow(o, 102, 1, "2013-01-01");
writeRow(a, 101, 1, "MA");
writeRow(c, 2, "Jones");
writeRow(a, 201, 2, "NY");
writeRow(c, 3, "Adams");
writeRow(o, 301, 3, "2010-04-01");
options = new FormatOptions();
ConfigurationService configService = configService();
options.set(FormatOptions.JsonBinaryFormatOption.fromProperty(configService.getProperty("fdbsql.sql.jsonbinary_output")));
}
static final String C13 = "[\n" +
"{\"cid\":1,\"name\":\"Smith\",\"o\":[{\"oid\":101,\"cid\":1,\"order_date\":\"2012-12-12\",\"i\":[{\"iid\":10101,\"oid\":101,\"sku\":\"ABCD\"},{\"iid\":10102,\"oid\":101,\"sku\":\"1234\"}]},{\"oid\":102,\"cid\":1,\"order_date\":\"2013-01-01\"}],\"a\":[{\"aid\":101,\"cid\":1,\"state\":\"MA\"}]},\n" +
"{\"cid\":3,\"name\":\"Adams\",\"o\":[{\"oid\":301,\"cid\":3,\"order_date\":\"2010-04-01\"}]}\n" +
"]";
@Test
public void dumpJsonC13() throws IOException {
ExternalDataService external =
serviceManager().getServiceByClass(ExternalDataService.class);
StringWriter str = new StringWriter();
PrintWriter pw = new PrintWriter(str);
external.dumpBranchAsJson(session(), pw, SCHEMA, "c",
Arrays.asList(Collections.singletonList((Object)"1"),
Collections.singletonList((Object)"3")),
-1,
WITH_TXN,
options);
assertEquals(C13, str.toString());
}
static final String O101 = "[\n" +
"{\"oid\":101,\"cid\":1,\"order_date\":\"2012-12-12\",\"i\":[{\"iid\":10101,\"oid\":101,\"sku\":\"ABCD\"},{\"iid\":10102,\"oid\":101,\"sku\":\"1234\"}]}\n" +
"]";
@Test
public void dumpJsonO101() throws IOException {
ExternalDataService external =
serviceManager().getServiceByClass(ExternalDataService.class);
StringWriter str = new StringWriter();
PrintWriter pw = new PrintWriter(str);
external.dumpBranchAsJson(session(), pw, SCHEMA, "o",
Collections.singletonList(Collections.singletonList((Object)"101")),
-1,
WITH_TXN,
options);
assertEquals(O101, str.toString());
}
static final String C1d0 = "[\n" +
"{\"cid\":1,\"name\":\"Smith\"}\n" +
"]";
@Test
public void dumpJsonDepth0() throws IOException {
ExternalDataService external =
serviceManager().getServiceByClass(ExternalDataService.class);
StringWriter str = new StringWriter();
PrintWriter pw = new PrintWriter(str);
external.dumpBranchAsJson(session(), pw, SCHEMA, "c",
Collections.singletonList(Collections.singletonList((Object)"1")),
0,
WITH_TXN,
options);
assertEquals(C1d0, str.toString());
}
static final String C1d1 = "[\n" +
"{\"cid\":1,\"name\":\"Smith\",\"o\":[{\"oid\":101,\"cid\":1,\"order_date\":\"2012-12-12\"},{\"oid\":102,\"cid\":1,\"order_date\":\"2013-01-01\"}],\"a\":[{\"aid\":101,\"cid\":1,\"state\":\"MA\"}]}\n" +
"]";
@Test
public void dumpJsonDepth1() throws IOException {
ExternalDataService external =
serviceManager().getServiceByClass(ExternalDataService.class);
StringWriter str = new StringWriter();
PrintWriter pw = new PrintWriter(str);
external.dumpBranchAsJson(session(), pw, SCHEMA, "c",
Collections.singletonList(Collections.singletonList((Object)"1")),
1,
WITH_TXN,
options);
assertEquals(C1d1, str.toString());
}
@Test
public void dumpJsonEmpty() throws IOException {
ExternalDataService external =
serviceManager().getServiceByClass(ExternalDataService.class);
StringWriter str = new StringWriter();
PrintWriter pw = new PrintWriter(str);
external.dumpBranchAsJson(session(), pw, SCHEMA, "c",
Collections.singletonList(Collections.singletonList((Object)"666")),
-1,
WITH_TXN,
options);
assertEquals("[]", str.toString());
}
static final String fooA1BarB1 = "[\n" +
"{\"aid\":1,\"bar.b\":[{\"bid\":10,\"aid\":1}]}\n" +
"]";
@Test
public void dumpJsonCrossSchemaGroup() {
ExternalDataService external =
serviceManager().getServiceByClass(ExternalDataService.class);
int aid = createTable("foo", "a",
"aid INT PRIMARY KEY NOT NULL");
int bid = createTable("bar", "b",
"bid INT PRIMARY KEY NOT NULL",
"aid INT NOT NULL",
"GROUPING FOREIGN KEY(aid) REFERENCES foo.a(aid)");
writeRow(aid, 1L);
writeRow(bid, 10L, 1L);
StringWriter str = new StringWriter();
PrintWriter pw = new PrintWriter(str);
external.dumpBranchAsJson(session(), pw, "foo", "a",
Collections.singletonList(Collections.singletonList((Object)"1")),
-1,
WITH_TXN,
options);
assertEquals(fooA1BarB1, str.toString());
}
static final String CSV = "Fred\nWilma\nBarney\nBetty\n";
@Test
public void loadCsvWithFunctions() throws Exception {
ExternalDataService external =
serviceManager().getServiceByClass(ExternalDataService.class);
int tid = createTable(SCHEMA, "t",
"id INT PRIMARY KEY NOT NULL GENERATED BY DEFAULT AS IDENTITY",
"name VARCHAR(128)",
"source VARCHAR(128) DEFAULT CURRENT SCHEMA");
AkibanInformationSchema ais = ais();
Table table = ais.getTable(tid);
List<Column> columns = Collections.singletonList(table.getColumn("name"));
InputStream istr = new ByteArrayInputStream(CSV.getBytes("UTF-8"));
Schema schema = SchemaCache.globalSchema(ais);
StoreAdapter adapter = newStoreAdapter();
QueryContext queryContext = new SimpleQueryContext(adapter) {
@Override
public ServiceManager getServiceManager() {
return serviceManager();
}
@Override
public String getCurrentSchema() {
return SCHEMA;
}
};
long nrows = external.loadTableFromCsv(session(), istr, new CsvFormat("UTF-8"),
0, table, columns,
-1, 1, queryContext);
assertEquals(4, nrows);
RowType rowType = schema.tableRowType(table);
compareRows(new Row[] {
testRow(rowType, 1L, "Fred", SCHEMA),
testRow(rowType, 2L, "Wilma", SCHEMA),
testRow(rowType, 3L, "Barney", SCHEMA),
testRow(rowType, 4L, "Betty", SCHEMA)
},
adapter.newGroupCursor(table.getGroup()));
}
}