/* * Copyright (c) 2013-2017 Cinchapi Inc. * * Licensed 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 com.cinchapi.concourse; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.Statement; import java.util.Set; import org.junit.Assert; import org.junit.Test; import com.cinchapi.concourse.Timestamp; import com.cinchapi.concourse.importer.CsvImporter; import com.cinchapi.concourse.importer.Importer; import com.cinchapi.concourse.lang.Criteria; import com.cinchapi.concourse.test.ConcourseIntegrationTest; import com.cinchapi.concourse.test.Variables; import com.cinchapi.concourse.thrift.Operator; import com.cinchapi.concourse.util.Resources; import com.google.common.base.Throwables; import com.google.common.collect.Sets; /** * Unit tests to make sure that the find operation works with complex * {@link Criteria}. * * @author Jeff Nelson */ public class FindCriteriaTest extends ConcourseIntegrationTest { private Statement sql; @Override protected void beforeEachTest() { // Import data into Concourse System.out.println("Importing college data into Concourse"); Importer importer = new CsvImporter(client); importer.importFile(Resources.get("/college.csv").getFile()); // Load up the SQL db which also contains a copy of the data System.out.println("Loading SQL database with college data"); try { // NOTE: The JDBC API is atrocious :o= Class.forName("org.sqlite.JDBC"); Connection conn = DriverManager.getConnection("jdbc:sqlite:" + Resources.get("/college.db").getFile()); sql = conn.createStatement(); } catch (Exception e) { throw Throwables.propagate(e); } super.beforeEachTest(); } @Test public void testSimpleWithTime() { Set<Long> results = client.find(Criteria.where().key("graduation_rate") .operator(Operator.GREATER_THAN).value(90)); Timestamp t1 = Timestamp.now(); System.out.println("Importing college data into Concourse"); Importer importer = new CsvImporter(client); importer.importFile(Resources.get("/college.csv").getFile()); Assert.assertEquals( results, client.find(Criteria.where().key("graduation_rate") .operator(Operator.GREATER_THAN).value(90).at(t1))); } @Test public void testBuildableStateParamSucceeds() { Assert.assertEquals( client.find(Criteria.where().key("graduation_rate") .operator(Operator.GREATER_THAN).value(90)), client.find(Criteria.where().key("graduation_rate") .operator(Operator.GREATER_THAN).value(90).build())); } @Test(expected = IllegalArgumentException.class) public void testNonBuildableStateParamDoesNotSucceed() { client.find(new Object()); } @Test public void testSimple() { Assert.assertTrue(hasSameResults(Criteria.where() .key("graduation_rate").operator(Operator.GREATER_THAN) .value(90).build())); } @Test public void testSimpleAnd() { Assert.assertTrue(hasSameResults(Criteria.where() .key("graduation_rate").operator(Operator.GREATER_THAN) .value(90).and().key("percent_undergrad_black") .operator(Operator.GREATER_THAN_OR_EQUALS).value(5).build())); } @Test public void testSimpleOr() { Assert.assertTrue(hasSameResults(Criteria.where() .key("graduation_rate").operator(Operator.GREATER_THAN) .value(90).or().key("percent_undergrad_black") .operator(Operator.GREATER_THAN_OR_EQUALS).value(5).build())); } @Test public void testSimpleAndOr() { Assert.assertTrue(hasSameResults(Criteria.where() .key("graduation_rate").operator(Operator.GREATER_THAN) .value(90).and().key("percent_undergrad_black") .operator(Operator.GREATER_THAN_OR_EQUALS).value(5).or() .key("total_cost_out_state").operator(Operator.GREATER_THAN) .value(50000).build())); } @Test public void testSimpleOrAnd() { Assert.assertTrue(hasSameResults(Criteria.where() .key("graduation_rate").operator(Operator.GREATER_THAN) .value(90).or().key("percent_undergrad_black") .operator(Operator.GREATER_THAN_OR_EQUALS).value(5).and() .key("total_cost_out_state").operator(Operator.GREATER_THAN) .value(50000).build())); } @Test public void testAndGroupOr() { Assert.assertTrue(hasSameResults(Criteria .where() .key("graduation_rate") .operator(Operator.GREATER_THAN) .value(90) .and() .group(Criteria.where().key("percent_undergrad_black") .operator(Operator.GREATER_THAN_OR_EQUALS).value(5) .or().key("total_cost_out_state") .operator(Operator.GREATER_THAN).value(50000).build()) .build())); } @Test public void testOrGroupAnd() { Assert.assertTrue(hasSameResults(Criteria .where() .key("graduation_rate") .operator(Operator.GREATER_THAN) .value(90) .or() .group(Criteria.where().key("percent_undergrad_black") .operator(Operator.GREATER_THAN_OR_EQUALS).value(5) .and().key("total_cost_out_state") .operator(Operator.GREATER_THAN).value(50000).build()) .build())); } @Test public void testGroupAndOrGroupAnd() { Assert.assertTrue(hasSameResults(Criteria .where() .group(Criteria.where().key("graduation_rate") .operator(Operator.GREATER_THAN).value(90).and() .key("yield_men").operator(Operator.EQUALS).value(20) .build()) .or() .group(Criteria.where().key("percent_undergrad_black") .operator(Operator.GREATER_THAN_OR_EQUALS).value(5) .and().key("total_cost_out_state") .operator(Operator.GREATER_THAN).value(50000).build()) .build())); } @Test public void testGroupOrAndGroupOr() { Assert.assertTrue(hasSameResults(Criteria .where() .group(Criteria.where().key("graduation_rate") .operator(Operator.GREATER_THAN).value(90).or() .key("yield_men").operator(Operator.EQUALS).value(20) .build()) .and() .group(Criteria.where().key("percent_undergrad_black") .operator(Operator.GREATER_THAN_OR_EQUALS).value(5) .or().key("total_cost_out_state") .operator(Operator.GREATER_THAN).value(50000).build()) .build())); } /** * Validate that the {@code criteria} returns the same result in Concourse * as it does in a relational database. * * @param criteria * @return {@code true} if the Concourse and SQL result sets are the same */ private boolean hasSameResults(Criteria criteria) { try { Set<Object> a = Sets.newHashSet(client.get("ipeds_id", client.find(criteria)).values()); String query = "SELECT ipeds_id FROM data WHERE " + criteria.toString(); ResultSet rs = sql.executeQuery(query); rs.next(); // skip column header Set<Object> b = Sets.newHashSet(); while (rs.next()) { b.add(rs.getInt(1)); } Variables.register("query", query); Variables.register("con", a); Variables.register("sql", b); Variables.register("diff", Sets.symmetricDifference(a, b)); return a.equals(b); } catch (Exception e) { throw Throwables.propagate(e); } } }