Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,14 @@ public static Iterable<Object[]> table_function(int i) {
new Object[] {i * 10, "empty"}
);
}

@QuerySqlTableFunction(alias = "TABLE_FUNC_WITH_ARRAY", columnTypes = {String.class}, columnNames = {"RES_COL"})
public static Iterable<Object[]> table_function_with_arr(List<Object> array) {
return array.stream()
.map(Object::toString)
.map(str -> new Object[]{str})
.collect(Collectors.toList());
}
}
// end::sql-table-function-example[]

Expand Down Expand Up @@ -202,7 +210,11 @@ IgniteCache testSqlTableFunction(Ignite ignite) {

IgniteCache cache = ignite.createCache(cfg);

SqlFieldsQuery query = new SqlFieldsQuery("SELECT STR_COL FROM TABLE_FUNCTION(10) WHERE INT_COL > 50");
SqlFieldsQuery query = new SqlFieldsQuery("SELECT STR_COL FROM TABLE(TABLE_FUNCTION(10)) WHERE INT_COL > 50");

cache.query(query).getAll();

query = new SqlFieldsQuery("SELECT RES_COL FROM TABLE(TABLE_FUNC_WITH_ARRAY(?))").setArgs(List.of("row1", "row2"));

cache.query(query).getAll();
// end::sql-table-function-config-query[]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
import org.apache.calcite.schema.SchemaPlus;
import org.apache.calcite.sql.validate.SqlValidatorException;
import org.apache.ignite.IgniteCache;
Expand Down Expand Up @@ -92,7 +93,6 @@ public void testSameSignatureNotRegistered() throws Exception {
assertEquals(1, schema.getFunctions("SAMESIGN").size());
}


/** */
@Test
public void testSystemFunctionOverriding() throws Exception {
Expand All @@ -105,18 +105,25 @@ public void testSystemFunctionOverriding() throws Exception {

// Make sure that the new functions didn't affect schema 'PUBLIC'.
assertQuery("SELECT UPPER(?)").withParams("abc").returns("ABC").check();
assertQuery("select UNIX_SECONDS(TIMESTAMP '2021-01-01 00:00:00')").returns(1609459200L).check();
assertQuery("select * from table(SYSTEM_RANGE(1, 2))").returns(1L).returns(2L).check();
assertQuery("select TYPEOF(?)").withParams(1L).returns("BIGINT").check();
assertQuery("select ? + ?").withParams(1, 2).returns(3).check();
assertThrows("select PLUS(?, ?)", SqlValidatorException.class, "No match found for function signature", 1, 2);
assertQuery("SELECT UNIX_SECONDS(TIMESTAMP '2021-01-01 00:00:00')").returns(1609459200L).check();
assertQuery("SELECT * FROM TABLE(SYSTEM_RANGE(1, 2))").returns(1L).returns(2L).check();
assertQuery("SELECT TYPEOF(?)").withParams(1L).returns("BIGINT").check();
assertQuery("SELECT ? + ?").withParams(1, 2).returns(3).check();
assertThrows("SELECT PLUS(?, ?)", SqlValidatorException.class, "No match found for function signature", 1, 2);

// Ensure that new functions are successfully created in a custom schema.
assertQuery("SELECT \"OWN_SCHEMA\".UPPER(?)").withParams("abc").returns(3).check();
assertQuery("select \"OWN_SCHEMA\".UNIX_SECONDS(TIMESTAMP '2021-01-01 00:00:00')").returns(1).check();
assertQuery("select * from table(\"OWN_SCHEMA\".SYSTEM_RANGE(1, 2))").returns(100L).check();
assertQuery("select \"OWN_SCHEMA\".TYPEOF('ABC')").returns(1).check();
assertQuery("select \"OWN_SCHEMA\".PLUS(?, ?)").withParams(1, 2).returns(100).check();
assertQuery("SELECT \"OWN_SCHEMA\".UNIX_SECONDS(TIMESTAMP '2021-01-01 00:00:00')").returns(1).check();
assertQuery("SELECT * FROM TABLE(\"OWN_SCHEMA\".SYSTEM_RANGE(1, 2))").returns(100L).check();
assertQuery("SELECT \"OWN_SCHEMA\".TYPEOF('ABC')").returns(1).check();
assertQuery("SELECT \"OWN_SCHEMA\".PLUS(?, ?)").withParams(1, 2).returns(100).check();

assertQuery("SELECT * FROM TABLE(\"OWN_SCHEMA\".STR_ARRAY_CONSUME_TABLE(?)) as t").withParams(List.of("row1", "row2"))
.returns("row1").returns( "row2").check();
assertQuery("SELECT * FROM TABLE(\"OWN_SCHEMA\".OBJ_ARRAY_CONSUME_TABLE(?)) as t").withParams(List.of(new CustomClass(), "row2"))
.returns("CustomClass.toString").returns( "row2").check();
assertThrows("SELECT * FROM TABLE(\"OWN_SCHEMA\".STR_ARRAY_CONSUME_TABLE(?)) as t", IgniteSQLException.class,
"An error occurred while query executing", List.of(new CustomClass(), "row2"));

LogListener logChecker0 = LogListener.matches("Unable to add user-defined SQL function 'upper'")
.andMatches("Unable to add user-defined SQL function 'unix_seconds'")
Expand Down Expand Up @@ -713,6 +720,24 @@ public static int typeof(Object o) {
public static int plus(int x, int y) {
return 100;
}

/** Table function with String array as input. */
@QuerySqlTableFunction(alias = "STR_ARRAY_CONSUME_TABLE", columnTypes = {String.class}, columnNames = {"RESULT"})
public static Iterable<Object[]> strArrConsumeTable(List<String> array) {
return array.stream()
.map(Object::toString)
.map(str -> new Object[]{str})
.collect(Collectors.toList());
}

/** Table function with Object array as input. */
@QuerySqlTableFunction(alias = "OBJ_ARRAY_CONSUME_TABLE", columnTypes = {String.class}, columnNames = {"RESULT"})
public static Iterable<Object[]> objArrConsumeTable(List<Object> array) {
return array.stream()
.map(Object::toString)
.map(str -> new Object[]{str})
.collect(Collectors.toList());
}
}

/** */
Expand All @@ -726,4 +751,12 @@ public static double salary(String ignite, int key) {
.getAll().get(0).get(0);
}
}

/** */
private static class CustomClass {
/** */
@Override public String toString() {
return "CustomClass.toString";
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,9 @@
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.apache.ignite.cache.query.annotations.QuerySqlTableFunction;
import org.apache.ignite.calcite.CalciteQueryEngineConfiguration;
import org.apache.ignite.configuration.CacheConfiguration;
import org.apache.ignite.configuration.IgniteConfiguration;
import org.apache.ignite.configuration.SqlConfiguration;
import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion;
Expand Down Expand Up @@ -69,8 +71,14 @@ public class JdbcQueryTest extends GridCommonAbstractTest {

/** {@inheritDoc} */
@Override protected IgniteConfiguration getConfiguration(String igniteInstanceName) throws Exception {
CacheConfiguration<Object, Object> ccfg = new CacheConfiguration<>("TEST_CACHE_OWN")
.setSqlSchema("OWN_SCHEMA")
.setSqlFunctionClasses(FunctionsLibrary.class);

return super.getConfiguration(igniteInstanceName).setSqlConfiguration(
new SqlConfiguration().setQueryEnginesConfiguration(new CalciteQueryEngineConfiguration()));
new SqlConfiguration()
.setQueryEnginesConfiguration(new CalciteQueryEngineConfiguration()))
.setCacheConfiguration(ccfg);
}

/** {@inheritDoc} */
Expand Down Expand Up @@ -113,6 +121,21 @@ private void connect(String url) throws Exception {
stopAllGrids();
}

/** Test user defined table through jdbc. */
@Test
public void testUdt() throws Exception {
try (PreparedStatement ps = conn.prepareStatement("SELECT * FROM TABLE(\"OWN_SCHEMA\".STR_ARRAY_CONSUME_TABLE(?))")) {
ps.setObject(1, List.of("row1", "row2"));
ResultSet rs = ps.executeQuery();

assertTrue(rs.next());
assertEquals("row1", rs.getString(1));

assertTrue(rs.next());
assertEquals("row2", rs.getString(1));
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

assertFalse(rs.next());? Up to you.

}

/**
* @throws SQLException If failed.
*/
Expand Down Expand Up @@ -490,4 +513,16 @@ public ObjectToStore(int id, String name, double val) {
return Objects.hash(id, name, val);
}
}

/** User defined functions. */
public static class FunctionsLibrary {
/** Function consume String array and output it row by row. */
@QuerySqlTableFunction(alias = "STR_ARRAY_CONSUME_TABLE", columnTypes = {String.class}, columnNames = {"RESULT"})
public static Iterable<Object[]> strArrConsumeTable(List<String> array) {
return array.stream()
.map(Object::toString)
.map(str -> new Object[]{str})
.collect(Collectors.toList());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
* cacheCfg.setSqlFunctionClasses(MyTableFunctions.class);
*
* // And use in queries.
* cache.query(new SqlFieldsQuery("select S_VAL from MY_TABLE(1, 5.0f, "ext") where F_VAL is not null"));
* cache.query(new SqlFieldsQuery("select S_VAL from TABLE(MY_TABLE(1, 5.0f, "ext")) where F_VAL is not null"));
* </pre>
* <p>
* Table function must return an {@code Iterable} as a row set. Each row can be represented by an {@code Object[]} or
Expand Down
Loading