/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF 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 org.apache.ignite.internal.jdbc2;
import java.io.Serializable;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Collection;
import org.apache.ignite.IgniteCache;
import org.apache.ignite.cache.affinity.AffinityKey;
import org.apache.ignite.cache.query.annotations.QuerySqlField;
import org.apache.ignite.configuration.CacheConfiguration;
import org.apache.ignite.configuration.ConnectorConfiguration;
import org.apache.ignite.configuration.IgniteConfiguration;
import org.apache.ignite.internal.util.typedef.F;
import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
import org.apache.ignite.spi.discovery.tcp.ipfinder.TcpDiscoveryIpFinder;
import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder;
import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
import org.jetbrains.annotations.NotNull;
import static java.sql.Types.INTEGER;
import static java.sql.Types.OTHER;
import static java.sql.Types.VARCHAR;
import static org.apache.ignite.IgniteJdbcDriver.CFG_URL_PREFIX;
import static org.apache.ignite.cache.CacheAtomicityMode.TRANSACTIONAL;
import static org.apache.ignite.cache.CacheMode.PARTITIONED;
import static org.apache.ignite.cache.CacheWriteSynchronizationMode.FULL_SYNC;
/**
* Metadata tests.
*/
public class JdbcMetadataSelfTest extends GridCommonAbstractTest {
/** IP finder. */
private static final TcpDiscoveryIpFinder IP_FINDER = new TcpDiscoveryVmIpFinder(true);
/** JDBC URL. */
private static final String BASE_URL = CFG_URL_PREFIX + "cache=pers@modules/clients/src/test/config/jdbc-config.xml";
/** {@inheritDoc} */
@Override protected IgniteConfiguration getConfiguration(String igniteInstanceName) throws Exception {
IgniteConfiguration cfg = super.getConfiguration(igniteInstanceName);
cfg.setCacheConfiguration(
cacheConfiguration("pers", AffinityKey.class, Person.class),
cacheConfiguration("org", String.class, Organization.class));
TcpDiscoverySpi disco = new TcpDiscoverySpi();
disco.setIpFinder(IP_FINDER);
cfg.setDiscoverySpi(disco);
cfg.setConnectorConfiguration(new ConnectorConfiguration());
return cfg;
}
/**
* @param name Name.
* @param clsK Class k.
* @param clsV Class v.
* @return Cache configuration.
*/
protected CacheConfiguration cacheConfiguration(@NotNull String name, Class<?> clsK, Class<?> clsV) {
CacheConfiguration<?,?> cache = defaultCacheConfiguration();
cache.setName(name);
cache.setCacheMode(PARTITIONED);
cache.setBackups(1);
cache.setWriteSynchronizationMode(FULL_SYNC);
cache.setAtomicityMode(TRANSACTIONAL);
cache.setIndexedTypes(clsK, clsV);
return cache;
}
/** {@inheritDoc} */
@Override protected void beforeTestsStarted() throws Exception {
startGridsMultiThreaded(3);
IgniteCache<String, Organization> orgCache = grid(0).cache("org");
orgCache.put("o1", new Organization(1, "A"));
orgCache.put("o2", new Organization(2, "B"));
IgniteCache<AffinityKey<String>, Person> personCache = grid(0).cache("pers");
personCache.put(new AffinityKey<>("p1", "o1"), new Person("John White", 25, 1));
personCache.put(new AffinityKey<>("p2", "o1"), new Person("Joe Black", 35, 1));
personCache.put(new AffinityKey<>("p3", "o2"), new Person("Mike Green", 40, 2));
Class.forName("org.apache.ignite.IgniteJdbcDriver");
}
/** {@inheritDoc} */
@Override protected void afterTestsStopped() throws Exception {
stopAllGrids();
}
/**
* @throws Exception If failed.
*/
public void testResultSetMetaData() throws Exception {
try (Connection conn = DriverManager.getConnection(BASE_URL)) {
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(
"select p.name, o.id as orgId from \"pers\".Person p, \"org\".Organization o where p.orgId = o.id");
assertNotNull(rs);
ResultSetMetaData meta = rs.getMetaData();
assertNotNull(meta);
assertEquals(2, meta.getColumnCount());
assertTrue("Person".equalsIgnoreCase(meta.getTableName(1)));
assertTrue("name".equalsIgnoreCase(meta.getColumnName(1)));
assertTrue("name".equalsIgnoreCase(meta.getColumnLabel(1)));
assertEquals(VARCHAR, meta.getColumnType(1));
assertEquals("VARCHAR", meta.getColumnTypeName(1));
assertEquals("java.lang.String", meta.getColumnClassName(1));
assertTrue("Organization".equalsIgnoreCase(meta.getTableName(2)));
assertTrue("orgId".equalsIgnoreCase(meta.getColumnName(2)));
assertTrue("orgId".equalsIgnoreCase(meta.getColumnLabel(2)));
assertEquals(INTEGER, meta.getColumnType(2));
assertEquals("INTEGER", meta.getColumnTypeName(2));
assertEquals("java.lang.Integer", meta.getColumnClassName(2));
}
}
/**
* @throws Exception If failed.
*/
public void testGetTables() throws Exception {
try (Connection conn = DriverManager.getConnection(BASE_URL)) {
DatabaseMetaData meta = conn.getMetaData();
ResultSet rs = meta.getTables("", "pers", "%", new String[]{"TABLE"});
assertNotNull(rs);
assertTrue(rs.next());
assertEquals("TABLE", rs.getString("TABLE_TYPE"));
assertEquals("PERSON", rs.getString("TABLE_NAME"));
rs = meta.getTables("", "org", "%", new String[]{"TABLE"});
assertNotNull(rs);
assertTrue(rs.next());
assertEquals("TABLE", rs.getString("TABLE_TYPE"));
assertEquals("ORGANIZATION", rs.getString("TABLE_NAME"));
rs = meta.getTables("", "pers", "%", null);
assertNotNull(rs);
assertTrue(rs.next());
assertEquals("TABLE", rs.getString("TABLE_TYPE"));
assertEquals("PERSON", rs.getString("TABLE_NAME"));
rs = meta.getTables("", "org", "%", null);
assertNotNull(rs);
assertTrue(rs.next());
assertEquals("TABLE", rs.getString("TABLE_TYPE"));
assertEquals("ORGANIZATION", rs.getString("TABLE_NAME"));
rs = meta.getTables("", "PUBLIC", "", new String[]{"WRONG"});
assertFalse(rs.next());
}
}
/**
* @throws Exception If failed.
*/
public void testGetColumns() throws Exception {
try (Connection conn = DriverManager.getConnection(BASE_URL)) {
DatabaseMetaData meta = conn.getMetaData();
ResultSet rs = meta.getColumns("", "pers", "Person", "%");
assertNotNull(rs);
Collection<String> names = new ArrayList<>(2);
names.add("NAME");
names.add("AGE");
names.add("ORGID");
int cnt = 0;
while (rs.next()) {
String name = rs.getString("COLUMN_NAME");
assertTrue(names.remove(name));
if ("NAME".equals(name)) {
assertEquals(VARCHAR, rs.getInt("DATA_TYPE"));
assertEquals("VARCHAR", rs.getString("TYPE_NAME"));
assertEquals(1, rs.getInt("NULLABLE"));
} else if ("AGE".equals(name) || "ORGID".equals(name)) {
assertEquals(INTEGER, rs.getInt("DATA_TYPE"));
assertEquals("INTEGER", rs.getString("TYPE_NAME"));
assertEquals(0, rs.getInt("NULLABLE"));
}
cnt++;
}
assertTrue(names.isEmpty());
assertEquals(3, cnt);
rs = meta.getColumns("", "org", "Organization", "%");
assertNotNull(rs);
names.add("ID");
names.add("NAME");
cnt = 0;
while (rs.next()) {
String name = rs.getString("COLUMN_NAME");
assertTrue(names.remove(name));
if ("id".equals(name)) {
assertEquals(INTEGER, rs.getInt("DATA_TYPE"));
assertEquals("INTEGER", rs.getString("TYPE_NAME"));
assertEquals(0, rs.getInt("NULLABLE"));
} else if ("name".equals(name)) {
assertEquals(VARCHAR, rs.getInt("DATA_TYPE"));
assertEquals("VARCHAR", rs.getString("TYPE_NAME"));
assertEquals(1, rs.getInt("NULLABLE"));
}
cnt++;
}
assertTrue(names.isEmpty());
assertEquals(2, cnt);
}
}
/**
* @throws Exception If failed.
*/
public void testMetadataResultSetClose() throws Exception {
try (Connection conn = DriverManager.getConnection(BASE_URL);
ResultSet tbls = conn.getMetaData().getTables(null, null, "%", null)) {
int colCnt = tbls.getMetaData().getColumnCount();
while (tbls.next()) {
for (int i = 0; i < colCnt; i++)
tbls.getObject(i + 1);
}
}
catch (Exception ignored) {
fail();
}
}
/**
* Person.
*/
@SuppressWarnings("UnusedDeclaration")
private static class Person implements Serializable {
/** Name. */
@QuerySqlField(index = false)
private final String name;
/** Age. */
@QuerySqlField
private final int age;
/** Organization ID. */
@QuerySqlField
private final int orgId;
/**
* @param name Name.
* @param age Age.
* @param orgId Organization ID.
*/
private Person(String name, int age, int orgId) {
assert !F.isEmpty(name);
assert age > 0;
assert orgId > 0;
this.name = name;
this.age = age;
this.orgId = orgId;
}
}
/**
* Organization.
*/
@SuppressWarnings("UnusedDeclaration")
private static class Organization implements Serializable {
/** ID. */
@QuerySqlField
private final int id;
/** Name. */
@QuerySqlField(index = false)
private final String name;
/**
* @param id ID.
* @param name Name.
*/
private Organization(int id, String name) {
this.id = id;
this.name = name;
}
}
}