@@ -302,6 +302,140 @@ CASSANDRA_INTEGRATION_TEST_F(DbaasTests, QueryEachNode) {
302302 EXPECT_EQ (3u , server_names.size ()); // Ensure all three nodes were queried
303303}
304304
305+ /* *
306+ * Create function and aggregate definitions and ensure the schema metadata is reflected when
307+ * execute against the DBaaS SNI single endpoint docker image.
308+ *
309+ * This test will perform a connection and execute create function/aggregate queries to ensure
310+ * schema metadata using a DBaaS SNI single endpoint is handled properly.
311+ *
312+ * @jira_ticket CPP-815
313+ * @test_category dbaas
314+ * @test_category queries:schema_metadata:udf
315+ * @since 2.14.0
316+ * @expected_result Function/Aggregate definitions schema metadata are validated.
317+ */
318+ CASSANDRA_INTEGRATION_TEST_F (DbaasTests, SchemaMetadata) {
319+ CHECK_FAILURE;
320+
321+ Cluster cluster = default_cluster (false );
322+ cass_cluster_set_cloud_secure_connection_bundle_no_ssl_lib_init (cluster.get (),
323+ creds_v1 ().c_str ());
324+ connect (cluster);
325+
326+ // clang-format off
327+ session_.execute (" CREATE OR REPLACE FUNCTION avg_state(state tuple<int, bigint>, val int) "
328+ " CALLED ON NULL INPUT RETURNS tuple<int, bigint> "
329+ " LANGUAGE java AS "
330+ " 'if (val != null) {"
331+ " state.setInt(0, state.getInt(0) + 1);"
332+ " state.setLong(1, state.getLong(1) + val.intValue());"
333+ " };"
334+ " return state;'"
335+ " ;" );
336+ session_.execute (" CREATE OR REPLACE FUNCTION avg_final (state tuple<int, bigint>) "
337+ " CALLED ON NULL INPUT RETURNS double "
338+ " LANGUAGE java AS "
339+ " 'double r = 0;"
340+ " if (state.getInt(0) == 0) return null;"
341+ " r = state.getLong(1);"
342+ " r /= state.getInt(0);"
343+ " return Double.valueOf(r);'"
344+ " ;" );
345+ session_.execute (" CREATE OR REPLACE AGGREGATE average(int) "
346+ " SFUNC avg_state STYPE tuple<int, bigint> FINALFUNC avg_final "
347+ " INITCOND(0, 0);" );
348+ // clang-format on
349+
350+ const CassSchemaMeta* schema_meta = cass_session_get_schema_meta (session_.get ());
351+ ASSERT_TRUE (schema_meta != NULL );
352+ const CassKeyspaceMeta* keyspace_meta =
353+ cass_schema_meta_keyspace_by_name (schema_meta, default_keyspace ().c_str ());
354+ ASSERT_TRUE (keyspace_meta != NULL );
355+
356+ { // Function `avg_state`
357+ const char * data = NULL ;
358+ size_t length = 0 ;
359+ const CassDataType* datatype = NULL ;
360+
361+ const CassFunctionMeta* function_meta =
362+ cass_keyspace_meta_function_by_name (keyspace_meta, " avg_state" , " tuple<int,bigint>,int" );
363+ ASSERT_TRUE (function_meta != NULL );
364+ cass_function_meta_name (function_meta, &data, &length);
365+ EXPECT_EQ (" avg_state" , std::string (data, length));
366+ cass_function_meta_full_name (function_meta, &data, &length);
367+ EXPECT_EQ (" avg_state(tuple<int,bigint>,int)" , std::string (data, length));
368+ cass_function_meta_body (function_meta, &data, &length);
369+ EXPECT_EQ (" if (val != null) {state.setInt(0, state.getInt(0) + 1);state.setLong(1, "
370+ " state.getLong(1) + val.intValue());};return state;" ,
371+ std::string (data, length));
372+ cass_function_meta_language (function_meta, &data, &length);
373+ EXPECT_EQ (" java" , std::string (data, length));
374+ EXPECT_TRUE (cass_function_meta_called_on_null_input (function_meta));
375+ ASSERT_EQ (2u , cass_function_meta_argument_count (function_meta));
376+ cass_function_meta_argument (function_meta, 0 , &data, &length, &datatype);
377+ EXPECT_EQ (" state" , std::string (data, length));
378+ EXPECT_EQ (CASS_VALUE_TYPE_TUPLE, cass_data_type_type (datatype));
379+ ASSERT_EQ (2u , cass_data_type_sub_type_count (datatype));
380+ EXPECT_EQ (CASS_VALUE_TYPE_INT, cass_data_type_type (cass_data_type_sub_data_type (datatype, 0 )));
381+ EXPECT_EQ (CASS_VALUE_TYPE_BIGINT,
382+ cass_data_type_type (cass_data_type_sub_data_type (datatype, 1 )));
383+ cass_function_meta_argument (function_meta, 1 , &data, &length, &datatype);
384+ EXPECT_EQ (" val" , std::string (data, length));
385+ EXPECT_EQ (CASS_VALUE_TYPE_INT, cass_data_type_type (datatype));
386+ datatype = cass_function_meta_argument_type_by_name (function_meta, " state" );
387+ EXPECT_EQ (CASS_VALUE_TYPE_TUPLE, cass_data_type_type (datatype));
388+ ASSERT_EQ (2u , cass_data_type_sub_type_count (datatype));
389+ EXPECT_EQ (CASS_VALUE_TYPE_INT, cass_data_type_type (cass_data_type_sub_data_type (datatype, 0 )));
390+ EXPECT_EQ (CASS_VALUE_TYPE_BIGINT,
391+ cass_data_type_type (cass_data_type_sub_data_type (datatype, 1 )));
392+ datatype = cass_function_meta_argument_type_by_name (function_meta, " val" );
393+ EXPECT_EQ (CASS_VALUE_TYPE_INT, cass_data_type_type (datatype));
394+ datatype = cass_function_meta_return_type (function_meta);
395+ EXPECT_EQ (CASS_VALUE_TYPE_TUPLE, cass_data_type_type (datatype));
396+ ASSERT_EQ (2u , cass_data_type_sub_type_count (datatype));
397+ EXPECT_EQ (CASS_VALUE_TYPE_INT, cass_data_type_type (cass_data_type_sub_data_type (datatype, 0 )));
398+ EXPECT_EQ (CASS_VALUE_TYPE_BIGINT,
399+ cass_data_type_type (cass_data_type_sub_data_type (datatype, 1 )));
400+ }
401+
402+ { // Aggregate `average`
403+ const char * data = NULL ;
404+ size_t length = 0 ;
405+ const CassDataType* datatype = NULL ;
406+
407+ const CassAggregateMeta* aggregate_meta =
408+ cass_keyspace_meta_aggregate_by_name (keyspace_meta, " average" , " int" );
409+ ASSERT_TRUE (aggregate_meta != NULL );
410+ cass_aggregate_meta_name (aggregate_meta, &data, &length);
411+ EXPECT_EQ (" average" , std::string (data, length));
412+ cass_aggregate_meta_full_name (aggregate_meta, &data, &length);
413+ EXPECT_EQ (" average(int)" , std::string (data, length));
414+ size_t count = cass_aggregate_meta_argument_count (aggregate_meta);
415+ ASSERT_EQ (1u , cass_aggregate_meta_argument_count (aggregate_meta));
416+ datatype = cass_aggregate_meta_argument_type (aggregate_meta, 0 );
417+ EXPECT_EQ (CASS_VALUE_TYPE_INT, cass_data_type_type (datatype));
418+ datatype = cass_aggregate_meta_return_type (aggregate_meta);
419+ EXPECT_EQ (CASS_VALUE_TYPE_DOUBLE, cass_data_type_type (datatype));
420+ datatype = cass_aggregate_meta_state_type (aggregate_meta);
421+ EXPECT_EQ (CASS_VALUE_TYPE_TUPLE, cass_data_type_type (datatype));
422+ ASSERT_EQ (2u , cass_data_type_sub_type_count (datatype));
423+ EXPECT_EQ (CASS_VALUE_TYPE_INT, cass_data_type_type (cass_data_type_sub_data_type (datatype, 0 )));
424+ EXPECT_EQ (CASS_VALUE_TYPE_BIGINT,
425+ cass_data_type_type (cass_data_type_sub_data_type (datatype, 1 )));
426+ const CassFunctionMeta* function_meta = cass_aggregate_meta_state_func (aggregate_meta);
427+ cass_function_meta_name (function_meta, &data, &length);
428+ EXPECT_EQ (" avg_state" , std::string (data, length));
429+ function_meta = cass_aggregate_meta_final_func (aggregate_meta);
430+ cass_function_meta_name (function_meta, &data, &length);
431+ EXPECT_EQ (" avg_final" , std::string (data, length));
432+ const CassValue* initcond = cass_aggregate_meta_init_cond (aggregate_meta);
433+ EXPECT_EQ (CASS_VALUE_TYPE_VARCHAR, cass_value_type (initcond));
434+ EXPECT_EQ (Text (" (0, 0)" ), Text (initcond));
435+ ASSERT_TRUE (true );
436+ }
437+ }
438+
305439/* *
306440 * Ensure guardrails are enabled when performing a query against the DBaaS SNI single endpoint
307441 * docker image.
0 commit comments