Skip to content

Commit 092d227

Browse files
committed
Merge remote-tracking branch 'origin/404'
Conflicts: tests/integration/standard/test_metadata.py
2 parents bd0a864 + 9c200be commit 092d227

3 files changed

Lines changed: 64 additions & 112 deletions

File tree

cassandra/metadata.py

Lines changed: 50 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -1312,64 +1312,51 @@ class IndexMetadata(object):
13121312
"""
13131313
A representation of a secondary index on a column.
13141314
"""
1315+
keyspace_name = None
1316+
""" A string name of the keyspace. """
13151317

1316-
column = None
1317-
"""
1318-
The column (:class:`.ColumnMetadata`) this index is on.
1319-
"""
1318+
table_name = None
1319+
""" A string name of the table this index is on. """
13201320

13211321
name = None
13221322
""" A string name for the index. """
13231323

1324-
index_type = None
1325-
""" A string representing the type of index. """
1324+
kind = None
1325+
""" A string representing the kind of index (COMPOSITE, CUSTOM,...). """
13261326

13271327
index_options = {}
13281328
""" A dict of index options. """
13291329

1330-
def __init__(self, column_metadata, index_name=None, index_type=None, index_options={}):
1331-
self.column = column_metadata
1330+
def __init__(self, keyspace_name, table_name, index_name, kind, index_options):
1331+
self.keyspace_name = keyspace_name
1332+
self.table_name = table_name
13321333
self.name = index_name
1333-
self.index_type = index_type
1334+
self.kind = kind
13341335
self.index_options = index_options
13351336

13361337
def as_cql_query(self):
13371338
"""
13381339
Returns a CQL query that can be used to recreate this index.
13391340
"""
1340-
table = self.column.table
1341-
if self.index_type != "CUSTOM":
1342-
index_target = protect_name(self.column.name)
1343-
if self.index_options is not None:
1344-
option_keys = self.index_options.keys()
1345-
if "index_keys" in option_keys:
1346-
index_target = 'keys(%s)' % (index_target,)
1347-
elif "index_values" in option_keys:
1348-
# don't use any "function" for collection values
1349-
pass
1350-
else:
1351-
# it might be a "full" index on a frozen collection, but
1352-
# we need to check the data type to verify that, because
1353-
# there is no special index option for full-collection
1354-
# indexes.
1355-
data_type = self.column.data_type
1356-
collection_types = ('map', 'set', 'list')
1357-
if data_type.typename == "frozen" and data_type.subtypes[0].typename in collection_types:
1358-
# no index option for full-collection index
1359-
index_target = 'full(%s)' % (index_target,)
1360-
1341+
options = dict(self.index_options)
1342+
index_target = options.pop("target")
1343+
if self.kind != "CUSTOM":
13611344
return "CREATE INDEX %s ON %s.%s (%s)" % (
13621345
self.name, # Cassandra doesn't like quoted index names for some reason
1363-
protect_name(table.keyspace.name),
1364-
protect_name(table.name),
1346+
protect_name(self.keyspace_name),
1347+
protect_name(self.table_name),
13651348
index_target)
13661349
else:
1367-
return "CREATE CUSTOM INDEX %s ON %s.%s (%s) USING '%s'" % (
1350+
class_name = options.pop("class_name")
1351+
ret = "CREATE CUSTOM INDEX %s ON %s.%s (%s) USING '%s'" % (
13681352
self.name, # Cassandra doesn't like quoted index names for some reason
1369-
protect_name(table.keyspace.name),
1370-
protect_name(table.name),
1371-
protect_name(self.column.name),
1372-
self.index_options["class_name"])
1353+
protect_name(self.keyspace_name),
1354+
protect_name(self.table_name),
1355+
index_target,
1356+
class_name)
1357+
if options:
1358+
ret += " WITH OPTIONS = %s" % Encoder().cql_encode_all_types(options)
1359+
return ret
13731360

13741361
def export_as_string(self):
13751362
"""
@@ -1944,13 +1931,32 @@ def _build_column_metadata(table_metadata, row):
19441931
@staticmethod
19451932
def _build_index_metadata(column_metadata, row):
19461933
index_name = row.get("index_name")
1947-
index_type = row.get("index_type")
1948-
if index_name or index_type:
1934+
kind = row.get("index_type")
1935+
if index_name or kind:
19491936
options = row.get("index_options")
1950-
index_options = json.loads(options) if options else None
1951-
return IndexMetadata(column_metadata, index_name, index_type, index_options)
1952-
else:
1953-
return None
1937+
options = json.loads(options) if options else {}
1938+
options = options or {} # if the json parsed to None, init empty dict
1939+
1940+
# generate a CQL index identity string
1941+
target = protect_name(column_metadata.name)
1942+
if kind != "CUSTOM":
1943+
if "index_keys" in options:
1944+
target = 'keys(%s)' % (target,)
1945+
elif "index_values" in options:
1946+
# don't use any "function" for collection values
1947+
pass
1948+
else:
1949+
# it might be a "full" index on a frozen collection, but
1950+
# we need to check the data type to verify that, because
1951+
# there is no special index option for full-collection
1952+
# indexes.
1953+
data_type = column_metadata.data_type
1954+
collection_types = ('map', 'set', 'list')
1955+
if data_type.typename == "frozen" and data_type.subtypes[0].typename in collection_types:
1956+
# no index option for full-collection index
1957+
target = 'full(%s)' % (target,)
1958+
options['target'] = target
1959+
return IndexMetadata(column_metadata.table.keyspace_name, column_metadata.table.name, index_name, kind, options)
19541960

19551961
@staticmethod
19561962
def _build_trigger_metadata(table_metadata, row):
@@ -2232,7 +2238,7 @@ def _build_index_metadata(table_metadata, row):
22322238
kind = row.get("kind")
22332239
if index_name or kind:
22342240
index_options = row.get("options")
2235-
return IndexMetadataV3(table_metadata.keyspace_name, table_metadata.name, index_name, kind, index_options)
2241+
return IndexMetadata(table_metadata.keyspace_name, table_metadata.name, index_name, kind, index_options)
22362242
else:
22372243
return None
22382244

@@ -2322,63 +2328,6 @@ def _make_option_strings(cls, options_map):
23222328
return list(sorted(ret))
23232329

23242330

2325-
class IndexMetadataV3(object):
2326-
"""
2327-
A representation of a secondary index on a column.
2328-
"""
2329-
keyspace_name = None
2330-
""" A string name of the keyspace. """
2331-
2332-
table_name = None
2333-
""" A string name of the table this index is on. """
2334-
2335-
name = None
2336-
""" A string name for the index. """
2337-
2338-
kind = None
2339-
""" A string representing the kind of index (COMPOSITE, CUSTOM,...). """
2340-
2341-
index_options = {}
2342-
""" A dict of index options. """
2343-
2344-
def __init__(self, keyspace_name, table_name, index_name, kind, index_options):
2345-
self.keyspace_name = keyspace_name
2346-
self.table_name = table_name
2347-
self.name = index_name
2348-
self.kind = kind
2349-
self.index_options = index_options
2350-
2351-
def as_cql_query(self):
2352-
"""
2353-
Returns a CQL query that can be used to recreate this index.
2354-
"""
2355-
options = dict(self.index_options)
2356-
index_target = options.pop("target")
2357-
if self.kind != "CUSTOM":
2358-
return "CREATE INDEX %s ON %s.%s (%s)" % (
2359-
self.name, # Cassandra doesn't like quoted index names for some reason
2360-
protect_name(self.keyspace_name),
2361-
protect_name(self.table_name),
2362-
index_target)
2363-
else:
2364-
class_name = options.pop("class_name")
2365-
ret = "CREATE CUSTOM INDEX %s ON %s.%s (%s) USING '%s'" % (
2366-
self.name, # Cassandra doesn't like quoted index names for some reason
2367-
protect_name(self.keyspace_name),
2368-
protect_name(self.table_name),
2369-
index_target,
2370-
class_name)
2371-
if options:
2372-
ret += " WITH OPTIONS = %s" % Encoder().cql_encode_all_types(options)
2373-
return ret
2374-
2375-
def export_as_string(self):
2376-
"""
2377-
Returns a CQL query string that can be used to recreate this index.
2378-
"""
2379-
return self.as_cql_query() + ';'
2380-
2381-
23822331
class MaterializedViewMetadata(object):
23832332
"""
23842333
A representation of a materialized view on a table

docs/api/cassandra/metadata.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ Schemas
4040
.. autoclass:: IndexMetadata ()
4141
:members:
4242

43+
.. autoclass:: MaterializedViewMetadata ()
44+
:members:
45+
4346
Tokens and Ring Topology
4447
------------------------
4548

tests/integration/standard/test_metadata.py

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
from cassandra.cluster import Cluster
2929
from cassandra.cqltypes import DoubleType, Int32Type, ListType, UTF8Type, MapType, LongType
3030
from cassandra.encoder import Encoder
31-
from cassandra.metadata import (Metadata, KeyspaceMetadata, IndexMetadata, IndexMetadataV3,
31+
from cassandra.metadata import (Metadata, KeyspaceMetadata, IndexMetadata,
3232
Token, MD5Token, TokenMap, murmur3, Function, Aggregate, protect_name, protect_names,
3333
get_schema_parser)
3434
from cassandra.policies import SimpleConvictionPolicy
@@ -1304,10 +1304,10 @@ def test_index_updates(self):
13041304

13051305
ks_meta = self.cluster.metadata.keyspaces[self.keyspace_name]
13061306
table_meta = ks_meta.tables[self.table_name]
1307-
self.assertIsInstance(ks_meta.indexes['a_idx'], (IndexMetadata, IndexMetadataV3))
1308-
self.assertIsInstance(ks_meta.indexes['b_idx'], (IndexMetadata, IndexMetadataV3))
1309-
self.assertIsInstance(table_meta.indexes['a_idx'], (IndexMetadata, IndexMetadataV3))
1310-
self.assertIsInstance(table_meta.indexes['b_idx'], (IndexMetadata, IndexMetadataV3))
1307+
self.assertIsInstance(ks_meta.indexes['a_idx'], IndexMetadata)
1308+
self.assertIsInstance(ks_meta.indexes['b_idx'], IndexMetadata)
1309+
self.assertIsInstance(table_meta.indexes['a_idx'], IndexMetadata)
1310+
self.assertIsInstance(table_meta.indexes['b_idx'], IndexMetadata)
13111311

13121312
# both indexes updated when index dropped
13131313
self.session.execute("DROP INDEX a_idx")
@@ -1318,9 +1318,9 @@ def test_index_updates(self):
13181318
ks_meta = self.cluster.metadata.keyspaces[self.keyspace_name]
13191319
table_meta = ks_meta.tables[self.table_name]
13201320
self.assertNotIn('a_idx', ks_meta.indexes)
1321-
self.assertIsInstance(ks_meta.indexes['b_idx'], (IndexMetadata, IndexMetadataV3))
1321+
self.assertIsInstance(ks_meta.indexes['b_idx'], IndexMetadata)
13221322
self.assertNotIn('a_idx', table_meta.indexes)
1323-
self.assertIsInstance(table_meta.indexes['b_idx'], (IndexMetadata, IndexMetadataV3))
1323+
self.assertIsInstance(table_meta.indexes['b_idx'], IndexMetadata)
13241324

13251325
# keyspace index updated when table dropped
13261326
self.drop_basic_table()
@@ -1336,15 +1336,15 @@ def test_index_follows_alter(self):
13361336
self.session.execute("CREATE INDEX %s ON %s (a)" % (idx, self.table_name))
13371337
ks_meta = self.cluster.metadata.keyspaces[self.keyspace_name]
13381338
table_meta = ks_meta.tables[self.table_name]
1339-
self.assertIsInstance(ks_meta.indexes[idx], (IndexMetadata, IndexMetadataV3))
1340-
self.assertIsInstance(table_meta.indexes[idx], (IndexMetadata, IndexMetadataV3))
1339+
self.assertIsInstance(ks_meta.indexes[idx], IndexMetadata)
1340+
self.assertIsInstance(table_meta.indexes[idx], IndexMetadata)
13411341
self.session.execute('ALTER KEYSPACE %s WITH durable_writes = false' % self.keyspace_name)
13421342
old_meta = ks_meta
13431343
ks_meta = self.cluster.metadata.keyspaces[self.keyspace_name]
13441344
self.assertIsNot(ks_meta, old_meta)
13451345
table_meta = ks_meta.tables[self.table_name]
1346-
self.assertIsInstance(ks_meta.indexes[idx], (IndexMetadata, IndexMetadataV3))
1347-
self.assertIsInstance(table_meta.indexes[idx], (IndexMetadata, IndexMetadataV3))
1346+
self.assertIsInstance(ks_meta.indexes[idx], IndexMetadata)
1347+
self.assertIsInstance(table_meta.indexes[idx], IndexMetadata)
13481348
self.drop_basic_table()
13491349

13501350

0 commit comments

Comments
 (0)