diff --git a/include/cassandra.h b/include/cassandra.h index d58654ff6..106e094eb 100644 --- a/include/cassandra.h +++ b/include/cassandra.h @@ -2501,6 +2501,22 @@ CASS_EXPORT const CassColumnMeta* cass_materialized_view_meta_clustering_key(const CassMaterializedViewMeta* view_meta, size_t index); +/** + * Gets the clustering order column metadata for the provided index. + * + * @public @memberof CassMaterializedViewMeta + * + * @param[in] view_meta + * @param[in] index + * @return The clustering order for a column. + * CASS_CLUSTERING_ORDER_NONE returned if the index is out of range. + * + * @see cass_materialized_view_meta_clustering_key_count() + */ +CASS_EXPORT CassClusteringOrder +cass_materialized_view_meta_clustering_key_order(const CassMaterializedViewMeta* view_meta, + size_t index); + /** * Gets a metadata field for the provided name. Metadata fields allow direct * access to the column data found in the underlying "views" metadata view. diff --git a/src/metadata.cpp b/src/metadata.cpp index 542645ff6..62ac76c31 100644 --- a/src/metadata.cpp +++ b/src/metadata.cpp @@ -358,6 +358,14 @@ const CassColumnMeta* cass_materialized_view_meta_clustering_key(const CassMater return CassColumnMeta::to(view_meta->clustering_key()[index].get()); } +CassClusteringOrder cass_materialized_view_meta_clustering_key_order(const CassMaterializedViewMeta* view_meta, + size_t index) { + if (index >= view_meta->clustering_key_order().size()) { + return CASS_CLUSTERING_ORDER_NONE; + } + return view_meta->clustering_key_order()[index]; +} + void cass_column_meta_name(const CassColumnMeta* column_meta, const char** name, size_t* name_length) { *name = column_meta->name().data(); @@ -1324,6 +1332,7 @@ void TableMetadataBase::build_keys_and_sort(const MetadataConfig& config) { if (config.cassandra_version.major_version() >= 2) { partition_key_.resize(get_column_count(columns_, CASS_COLUMN_TYPE_PARTITION_KEY)); clustering_key_.resize(get_column_count(columns_, CASS_COLUMN_TYPE_CLUSTERING_KEY)); + clustering_key_order_.resize(clustering_key_.size(), CASS_CLUSTERING_ORDER_NONE); for (ColumnMetadata::Vec::const_iterator i = columns_.begin(), end = columns_.end(); i != end; ++i) { ColumnMetadata::Ptr column(*i); @@ -1335,8 +1344,8 @@ void TableMetadataBase::build_keys_and_sort(const MetadataConfig& config) { column->position() >= 0 && static_cast(column->position()) < clustering_key_.size()) { clustering_key_[column->position()] = column; - clustering_key_order_.push_back(column->is_reversed() ? CASS_CLUSTERING_ORDER_DESC - : CASS_CLUSTERING_ORDER_ASC); + clustering_key_order_[column->position()] = column->is_reversed() ? CASS_CLUSTERING_ORDER_DESC + : CASS_CLUSTERING_ORDER_ASC; } } diff --git a/test/integration_tests/src/test_schema_metadata.cpp b/test/integration_tests/src/test_schema_metadata.cpp index feb43bcd6..b3b8f1896 100644 --- a/test/integration_tests/src/test_schema_metadata.cpp +++ b/test/integration_tests/src/test_schema_metadata.cpp @@ -141,6 +141,13 @@ struct TestSchemaMetadata : public test_utils::SingleSessionTest { return table_meta; } + const CassMaterializedViewMeta* schema_get_view(const std::string& ks_name, + const std::string& view_name) { + const CassMaterializedViewMeta* view_meta = cass_keyspace_meta_materialized_view_by_name(schema_get_keyspace(ks_name), view_name.c_str()); + BOOST_REQUIRE(view_meta); + return view_meta; + } + const CassColumnMeta* schema_get_column(const std::string& ks_name, const std::string& table_name, const std::string& col_name) { @@ -1211,6 +1218,21 @@ BOOST_AUTO_TEST_CASE(clustering_order) { BOOST_CHECK_EQUAL(cass_table_meta_clustering_key_order(table_meta, 1), CASS_CLUSTERING_ORDER_ASC); BOOST_CHECK_EQUAL(cass_table_meta_clustering_key_order(table_meta, 2), CASS_CLUSTERING_ORDER_DESC); } + + { + test_utils::execute_query(session, "CREATE TABLE clustering_order.mixed_order_composite_clustering_key (" + "key1 text, key2 text, key3 text, key4 text, value text, " + "PRIMARY KEY(key1, key4, key3, key2))" + "WITH CLUSTERING ORDER BY (key4 DESC, key3 ASC, key2 ASC)"); + refresh_schema_meta(); + + const CassTableMeta* table_meta = schema_get_table("clustering_order", "mixed_order_composite_clustering_key"); + + BOOST_REQUIRE_EQUAL(cass_table_meta_clustering_key_count(table_meta), 3); + BOOST_CHECK_EQUAL(cass_table_meta_clustering_key_order(table_meta, 0), CASS_CLUSTERING_ORDER_DESC); + BOOST_CHECK_EQUAL(cass_table_meta_clustering_key_order(table_meta, 1), CASS_CLUSTERING_ORDER_ASC); + BOOST_CHECK_EQUAL(cass_table_meta_clustering_key_order(table_meta, 2), CASS_CLUSTERING_ORDER_ASC); + } } /** @@ -1608,4 +1630,94 @@ BOOST_AUTO_TEST_CASE(materialized_views) { // DROP MATERIALIZE VIEW event. } +/** + * Test materialized view clustering order. + * + * Verify that column clustering order is properly updated and returned. + * + * @since 2.3.0 + * @jira_ticket CPP-332 + * @test_category schema + * @cassandra_version 3.0.x + */ +BOOST_AUTO_TEST_CASE(materialized_view_clustering_order) { + if (version < "3.0.0") return; + + { + test_utils::execute_query(session, "CREATE KEYSPACE materialized_view_clustering_order WITH replication = " + "{ 'class' : 'SimpleStrategy', 'replication_factor' : 3 }"); + + test_utils::execute_query(session, "CREATE TABLE materialized_view_clustering_order.table1 (key1 text, value1 text, PRIMARY KEY(key1))"); + test_utils::execute_query(session, "CREATE TABLE materialized_view_clustering_order.table2 (key1 text, key2 text, value1 text, PRIMARY KEY(key1, key2))"); + + refresh_schema_meta(); + } + + { + test_utils::execute_query(session, "CREATE MATERIALIZED VIEW materialized_view_clustering_order.composite_key AS " + "SELECT key1 FROM materialized_view_clustering_order.table1 WHERE value1 IS NOT NULL " + "PRIMARY KEY(value1, key1)"); + refresh_schema_meta(); + + const CassMaterializedViewMeta* view_meta = schema_get_view("materialized_view_clustering_order", "composite_key"); + + BOOST_REQUIRE_EQUAL(cass_materialized_view_meta_clustering_key_count(view_meta), 1); + BOOST_CHECK_EQUAL(cass_materialized_view_meta_clustering_key_order(view_meta, 0), CASS_CLUSTERING_ORDER_ASC); + } + + { + test_utils::execute_query(session, "CREATE MATERIALIZED VIEW materialized_view_clustering_order.reversed_composite_key AS " + "SELECT key1 FROM materialized_view_clustering_order.table1 WHERE value1 IS NOT NULL " + "PRIMARY KEY(value1, key1)" + "WITH CLUSTERING ORDER BY (key1 DESC)"); + refresh_schema_meta(); + + const CassMaterializedViewMeta* view_meta = schema_get_view("materialized_view_clustering_order", "reversed_composite_key"); + + BOOST_REQUIRE_EQUAL(cass_materialized_view_meta_clustering_key_count(view_meta), 1); + BOOST_CHECK_EQUAL(cass_materialized_view_meta_clustering_key_order(view_meta, 0), CASS_CLUSTERING_ORDER_DESC); + } + + { + test_utils::execute_query(session, "CREATE MATERIALIZED VIEW materialized_view_clustering_order.composite_clustering_key AS " + "SELECT key1 FROM materialized_view_clustering_order.table2 WHERE key2 IS NOT NULL AND value1 IS NOT NULL " + "PRIMARY KEY(value1, key2, key1)"); + refresh_schema_meta(); + + const CassMaterializedViewMeta* view_meta = schema_get_view("materialized_view_clustering_order", "composite_clustering_key"); + + BOOST_REQUIRE_EQUAL(cass_materialized_view_meta_clustering_key_count(view_meta), 2); + BOOST_CHECK_EQUAL(cass_materialized_view_meta_clustering_key_order(view_meta, 0), CASS_CLUSTERING_ORDER_ASC); + BOOST_CHECK_EQUAL(cass_materialized_view_meta_clustering_key_order(view_meta, 1), CASS_CLUSTERING_ORDER_ASC); + } + + { + test_utils::execute_query(session, "CREATE MATERIALIZED VIEW materialized_view_clustering_order.reversed_composite_clustering_key AS " + "SELECT key1 FROM materialized_view_clustering_order.table2 WHERE key2 IS NOT NULL AND value1 IS NOT NULL " + "PRIMARY KEY(value1, key2, key1) " + "WITH CLUSTERING ORDER BY (key2 DESC, key1 DESC)"); + refresh_schema_meta(); + + const CassMaterializedViewMeta* view_meta = schema_get_view("materialized_view_clustering_order", "reversed_composite_clustering_key"); + + BOOST_REQUIRE_EQUAL(cass_materialized_view_meta_clustering_key_count(view_meta), 2); + BOOST_CHECK_EQUAL(cass_materialized_view_meta_clustering_key_order(view_meta, 0), CASS_CLUSTERING_ORDER_DESC); + BOOST_CHECK_EQUAL(cass_materialized_view_meta_clustering_key_order(view_meta, 1), CASS_CLUSTERING_ORDER_DESC); + } + + { + test_utils::execute_query(session, "CREATE MATERIALIZED VIEW materialized_view_clustering_order.mixed_composite_clustering_key AS " + "SELECT key1 FROM materialized_view_clustering_order.table2 WHERE key2 IS NOT NULL AND value1 IS NOT NULL " + "PRIMARY KEY(value1, key2, key1) " + "WITH CLUSTERING ORDER BY (key2 DESC, key1 ASC)"); + refresh_schema_meta(); + + const CassMaterializedViewMeta* view_meta = schema_get_view("materialized_view_clustering_order", "mixed_composite_clustering_key"); + + BOOST_REQUIRE_EQUAL(cass_materialized_view_meta_clustering_key_count(view_meta), 2); + BOOST_CHECK_EQUAL(cass_materialized_view_meta_clustering_key_order(view_meta, 0), CASS_CLUSTERING_ORDER_DESC); + BOOST_CHECK_EQUAL(cass_materialized_view_meta_clustering_key_order(view_meta, 1), CASS_CLUSTERING_ORDER_ASC); + } +} + BOOST_AUTO_TEST_SUITE_END()