Ottomata has uploaded a new change for review. (
https://gerrit.wikimedia.org/r/365999 )
Change subject: Auto add indexes for date-time and uuid v1 type columns
......................................................................
Auto add indexes for date-time and uuid v1 type columns
Bug: T170925
Change-Id: I8667916bf6f99da5aa4e9422747b113881955f8b
---
M eventlogging/jrm.py
M tests/test_jrm.py
2 files changed, 53 insertions(+), 3 deletions(-)
git pull ssh://gerrit.wikimedia.org:29418/eventlogging
refs/changes/99/365999/1
diff --git a/eventlogging/jrm.py b/eventlogging/jrm.py
index 1b57b96..3fe3ef5 100644
--- a/eventlogging/jrm.py
+++ b/eventlogging/jrm.py
@@ -11,6 +11,7 @@
import collections
import datetime
+import dateutil.parser
import itertools
import logging
import _mysql
@@ -55,7 +56,6 @@
return '{}_{}'.format(table_name, event.schema_revision())
else:
return table_name
-
# An iterable of properties that should not be stored in the database.
@@ -105,8 +105,28 @@
return datetime.datetime.strptime(value, MEDIAWIKI_TIMESTAMP)
+class DateTimeSerde(sqlalchemy.TypeDecorator):
+ """
+ A :class:`sqlalchemy.TypeDecorator` for datetime columns.
+ This simply uses dateutil.parser.parse on the incoming value
+ to return a Python datetime, which is then given to the
+ sqlalchemy.DateTime column type. Conversion from
+ sqlalchemy.DateTime back to python datetime is handled
+ by sqlalchemy, so process_result_value is not implemented.
+ """
+
+ impl = sqlalchemy.DateTime
+
+ def process_bind_param(self, value, dialect=None):
+ """Converts a time string to a python datetime."""
+ return dateutil.parser.parse(value)
+
+
class JsonSerde(sqlalchemy.TypeDecorator):
- """A :class:`sqlalchemy.TypeDecorator` for converting to and from JSON
strings."""
+ """
+ A :class:`sqlalchemy.TypeDecorator` for converting
+ to and from JSON strings.
+ """
impl = sqlalchemy.Unicode(STRING_MAX_LEN)
@@ -145,6 +165,10 @@
'utc-millisec': {'type_': MediaWikiTimestamp, 'index': True},
'uuid5-hex': {'type_': sqlalchemy.CHAR(32), 'index': True,
'unique': True},
+ # Add indexes to datetime fields: T170925
+ # NOTE: I tried to use timestamp instead of datetime, but could
+ # not get sqlalchemy to create those as DEFAULT NULL.
+ 'date-time': {'type_': DateTimeSerde, 'index': True}
}),
('required', {
# Note that required=true makes the column nullable anyway.
@@ -155,6 +179,14 @@
# required field is present, or discard the event otherwise.
True: {'nullable': True},
False: {'nullable': True}
+ }),
+ ('pattern', {
+ # UUID v1 pattern, make a unique index. T170925
+ '^[a-fA-F0-9]{8}(-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12}$': {
+ 'type_': sqlalchemy.CHAR(38),
+ 'index': True,
+ 'unique': True
+ },
})
))
diff --git a/tests/test_jrm.py b/tests/test_jrm.py
index 7559ccf..a231a00 100644
--- a/tests/test_jrm.py
+++ b/tests/test_jrm.py
@@ -68,13 +68,31 @@
cols |= {'id', 'uuid'} # plus id, uuid
self.assertSetEqual(set(t.columns.keys()), cols)
- def test_index_creation(self):
+ def test_timestamp_column_index_creation(self):
"""The ``timestamp`` column is indexed by default."""
table_name = event_to_table_name(self.event)
t = eventlogging.jrm.declare_table(self.meta, TEST_SCHEMA_SCID,
table_name)
cols = {column.name for index in t.indexes for column in index.columns}
self.assertIn('timestamp', cols)
+ def test_date_time_type_index_creation(self):
+ """A ``date-time`` column is indexed by default."""
+ table_name = event_to_table_name(self.event_with_meta)
+ t = eventlogging.jrm.declare_table(
+ self.meta, TEST_META_SCHEMA_SCID, table_name,
should_encapsulate=False
+ )
+ cols = {column.name for index in t.indexes for column in index.columns}
+ self.assertIn('meta_dt', cols)
+
+ def test_uuid_v1_type_index_creation(self):
+ """A ``uuid v1 pattern`` column is indexed by default."""
+ table_name = event_to_table_name(self.event_with_meta)
+ t = eventlogging.jrm.declare_table(
+ self.meta, TEST_META_SCHEMA_SCID, table_name,
should_encapsulate=False
+ )
+ cols = {column.name for index in t.indexes for column in index.columns}
+ self.assertIn('meta_id', cols)
+
def test_flatten(self):
"""``flatten`` correctly collapses deeply nested maps."""
flat = eventlogging.utils.flatten(self.event)
--
To view, visit https://gerrit.wikimedia.org/r/365999
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I8667916bf6f99da5aa4e9422747b113881955f8b
Gerrit-PatchSet: 1
Gerrit-Project: eventlogging
Gerrit-Branch: master
Gerrit-Owner: Ottomata <[email protected]>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits