From 9262f0eae6a05bfe65e5ef9d861b37af6646f0b4 Mon Sep 17 00:00:00 2001 From: Itai Shirav Date: Thu, 23 Jun 2016 19:05:44 +0300 Subject: [PATCH] add database.select and field range checks --- src/infi/clickhouse_orm/database.py | 8 +- src/infi/clickhouse_orm/fields.py | 42 +++++- src/infi/clickhouse_orm/models.py | 1 + src/infi/clickhouse_orm/utils.py | 2 +- tests/test_database.py | 200 +++++++++++++++------------- 5 files changed, 150 insertions(+), 103 deletions(-) diff --git a/src/infi/clickhouse_orm/database.py b/src/infi/clickhouse_orm/database.py index b7ae30a..0151c50 100644 --- a/src/infi/clickhouse_orm/database.py +++ b/src/infi/clickhouse_orm/database.py @@ -46,9 +46,15 @@ class Database(object): r = self._send(query) return int(r.text) if r.text else 0 + def select(self, query, model_class=None, settings=None): + query += ' FORMAT TabSeparated' + r = self._send(query, settings) + for line in r.iter_lines(): + yield model_class.from_tsv(line) + def _send(self, data, settings=None): params = self._build_params(settings) - r = requests.post(self.db_url, params=params, data=data) + r = requests.post(self.db_url, params=params, data=data, stream=True) if r.status_code != 200: raise DatabaseException(r.text) return r diff --git a/src/infi/clickhouse_orm/fields.py b/src/infi/clickhouse_orm/fields.py index 91b0e50..c90363e 100644 --- a/src/infi/clickhouse_orm/fields.py +++ b/src/infi/clickhouse_orm/fields.py @@ -21,6 +21,13 @@ class Field(object): """ return value + def validate(self, value): + pass + + def _range_check(self, value, min_value, max_value): + if value < min_value or value > max_value: + raise ValueError('%s out of range - %s is not between %s and %s' % (self.__class__.__name__, value, min_value, max_value)) + def get_db_prep_value(self, value): """ Returns the field's value prepared for interacting with the database. @@ -48,7 +55,9 @@ class StringField(Field): class DateField(Field): - class_default = datetime.date(1970, 1, 1) + min_value = datetime.date(1970, 1, 1) + max_value = datetime.date(2038, 1, 19) + class_default = min_value db_type = 'Date' def to_python(self, value): @@ -57,8 +66,12 @@ class DateField(Field): if isinstance(value, int): return DateField.class_default + datetime.timedelta(days=value) if isinstance(value, basestring): + # TODO parse '0000-00-00' return datetime.datetime.strptime(value, '%Y-%m-%d').date() - raise ValueError('Invalid value for %s: %r' % (self.__class__.__name__, value)) + raise ValueError('Invalid value for %s - %r' % (self.__class__.__name__, value)) + + def validate(self, value): + self._range_check(value, DateField.min_value, DateField.max_value) def get_db_prep_value(self, value): return value.isoformat() @@ -78,7 +91,7 @@ class DateTimeField(Field): return datetime.datetime.fromtimestamp(value, pytz.utc) if isinstance(value, basestring): return datetime.datetime.strptime(value, '%Y-%m-%d %H-%M-%S') - raise ValueError('Invalid value for %s: %r' % (self.__class__.__name__, value)) + raise ValueError('Invalid value for %s - %r' % (self.__class__.__name__, value)) def get_db_prep_value(self, value): return int(time.mktime(value.timetuple())) @@ -91,46 +104,65 @@ class BaseIntField(Field): return value if isinstance(value, basestring): return int(value) - raise ValueError('Invalid value for %s: %r' % (self.__class__.__name__, value)) + raise ValueError('Invalid value for %s - %r' % (self.__class__.__name__, value)) + + def validate(self, value): + self._range_check(value, self.min_value, self.max_value) class UInt8Field(BaseIntField): + min_value = 0 + max_value = 2**8 - 1 db_type = 'UInt8' class UInt16Field(BaseIntField): + min_value = 0 + max_value = 2**16 - 1 db_type = 'UInt16' class UInt32Field(BaseIntField): + min_value = 0 + max_value = 2**32 - 1 db_type = 'UInt32' class UInt64Field(BaseIntField): + min_value = 0 + max_value = 2**64 - 1 db_type = 'UInt64' class Int8Field(BaseIntField): + min_value = -2**7 + max_value = 2**7 - 1 db_type = 'Int8' class Int16Field(BaseIntField): + min_value = -2**16 + max_value = 2**16 - 1 db_type = 'Int16' class Int32Field(BaseIntField): + min_value = -2**32 + max_value = 2**32 - 1 db_type = 'Int32' class Int64Field(BaseIntField): + min_value = -2**64 + max_value = 2**64 - 1 db_type = 'Int64' @@ -141,7 +173,7 @@ class BaseFloatField(Field): return value if isinstance(value, basestring) or isinstance(value, int): return float(value) - raise ValueError('Invalid value for %s: %r' % (self.__class__.__name__, value)) + raise ValueError('Invalid value for %s - %r' % (self.__class__.__name__, value)) class Float32Field(BaseFloatField): diff --git a/src/infi/clickhouse_orm/models.py b/src/infi/clickhouse_orm/models.py index e5d41fd..8f58818 100644 --- a/src/infi/clickhouse_orm/models.py +++ b/src/infi/clickhouse_orm/models.py @@ -49,6 +49,7 @@ class Model(object): field = self.get_field(name) if field: value = field.to_python(value) + field.validate(value) super(Model, self).__setattr__(name, value) def get_field(self, name): diff --git a/src/infi/clickhouse_orm/utils.py b/src/infi/clickhouse_orm/utils.py index 5f49778..62c61e2 100644 --- a/src/infi/clickhouse_orm/utils.py +++ b/src/infi/clickhouse_orm/utils.py @@ -25,4 +25,4 @@ def unescape(value): def parse_tsv(line): if line[-1] == '\n': line = line[:-1] - return [_unescape(value) for value in line.split('\t')] + return [unescape(value) for value in line.split('\t')] diff --git a/tests/test_database.py b/tests/test_database.py index c368e7a..1d89e9a 100644 --- a/tests/test_database.py +++ b/tests/test_database.py @@ -39,6 +39,14 @@ class DatabaseTestCase(unittest.TestCase): self.assertEquals(self.database.count(Person, "birthday > '2000-01-01'"), 22) self.assertEquals(self.database.count(Person, "birthday < '1900-01-01'"), 0) + def test_select(self): + self._insert_and_check(self._sample_data(), len(data)) + query = "SELECT * FROM test_db.person WHERE first_name = 'Whitney' ORDER BY last_name" + results = list(self.database.select(query, Person)) + self.assertEquals(len(results), 2) + self.assertEquals(results[0].last_name, 'Durham') + self.assertEquals(results[1].last_name, 'Scott') + def _sample_data(self): for entry in data: yield Person(**entry) @@ -55,104 +63,104 @@ class Person(Model): data = [ - {"first_name": "Courtney", "last_name": "Cannon", "birthday": "1967-10-26", "height": "1.76"}, - {"first_name": "Kieran", "last_name": "Solomon", "birthday": "1963-10-30", "height": "1.69"}, - {"first_name": "Wynter", "last_name": "Garcia", "birthday": "1945-01-10", "height": "1.69"}, - {"first_name": "Buffy", "last_name": "Webb", "birthday": "1960-03-06", "height": "1.68"}, - {"first_name": "Jarrod", "last_name": "Gibbs", "birthday": "1957-06-13", "height": "1.62"}, - {"first_name": "Cara", "last_name": "Fox", "birthday": "2004-05-15", "height": "1.71"}, - {"first_name": "Shoshana", "last_name": "Solis", "birthday": "1968-07-18", "height": "1.65"}, - {"first_name": "Adam", "last_name": "Goodman", "birthday": "1956-01-07", "height": "1.74"}, - {"first_name": "Ciaran", "last_name": "Hurley", "birthday": "1965-10-25", "height": "1.65"}, - {"first_name": "Emma", "last_name": "Clements", "birthday": "1996-08-07", "height": "1.75"}, - {"first_name": "Warren", "last_name": "Dudley", "birthday": "1965-10-23", "height": "1.59"}, - {"first_name": "Courtney", "last_name": "Hoffman", "birthday": "1994-11-07", "height": "1.65"}, - {"first_name": "Karleigh", "last_name": "Bartlett", "birthday": "1991-10-24", "height": "1.69"}, - {"first_name": "Aline", "last_name": "Crane", "birthday": "1958-05-01", "height": "1.62"}, - {"first_name": "Sawyer", "last_name": "Fischer", "birthday": "1995-04-01", "height": "1.78"}, - {"first_name": "Ella", "last_name": "Castillo", "birthday": "1943-03-28", "height": "1.73"}, - {"first_name": "Jesse", "last_name": "Gomez", "birthday": "2011-01-28", "height": "1.71"}, - {"first_name": "Mary", "last_name": "Kirkland", "birthday": "1987-10-09", "height": "1.73"}, - {"first_name": "Quon", "last_name": "Wiggins", "birthday": "1962-05-06", "height": "1.74"}, - {"first_name": "Dominique", "last_name": "Sandoval", "birthday": "1942-02-01", "height": "1.72"}, - {"first_name": "Elton", "last_name": "Smith", "birthday": "1952-06-20", "height": "1.66"}, - {"first_name": "Whitney", "last_name": "Scott", "birthday": "1941-07-04", "height": "1.70"}, - {"first_name": "Sydney", "last_name": "Stevens", "birthday": "1959-07-11", "height": "1.70"}, - {"first_name": "Lesley", "last_name": "Stephenson", "birthday": "2010-04-10", "height": "1.64"}, - {"first_name": "Georgia", "last_name": "Kennedy", "birthday": "1944-12-29", "height": "1.66"}, - {"first_name": "Norman", "last_name": "Santos", "birthday": "1959-01-10", "height": "1.68"}, - {"first_name": "Vaughan", "last_name": "Schmidt", "birthday": "1955-06-19", "height": "1.61"}, - {"first_name": "Edan", "last_name": "Dennis", "birthday": "1959-09-18", "height": "1.73"}, - {"first_name": "Yolanda", "last_name": "Duke", "birthday": "1967-02-25", "height": "1.74"}, - {"first_name": "Seth", "last_name": "Serrano", "birthday": "2017-06-02", "height": "1.71"}, - {"first_name": "Callie", "last_name": "Wiley", "birthday": "1957-11-24", "height": "1.69"}, - {"first_name": "Shana", "last_name": "Jarvis", "birthday": "1967-05-21", "height": "1.72"}, - {"first_name": "Madeline", "last_name": "Kidd", "birthday": "1954-12-09", "height": "1.69"}, - {"first_name": "Macaulay", "last_name": "Rowe", "birthday": "1952-03-02", "height": "1.68"}, - {"first_name": "Rafael", "last_name": "Parker", "birthday": "2016-01-24", "height": "1.76"}, - {"first_name": "Ava", "last_name": "Sanders", "birthday": "1967-08-10", "height": "1.60"}, - {"first_name": "Ciaran", "last_name": "Carver", "birthday": "2016-12-25", "height": "1.76"}, - {"first_name": "Hyacinth", "last_name": "Kent", "birthday": "1971-07-18", "height": "1.72"}, - {"first_name": "Velma", "last_name": "English", "birthday": "1999-01-18", "height": "1.65"}, - {"first_name": "Adena", "last_name": "Norman", "birthday": "1949-05-14", "height": "1.66"}, - {"first_name": "Hedy", "last_name": "Strong", "birthday": "2001-10-04", "height": "1.60"}, - {"first_name": "Griffith", "last_name": "Henry", "birthday": "1955-04-02", "height": "1.66"}, - {"first_name": "Barrett", "last_name": "Clemons", "birthday": "1985-07-03", "height": "1.71"}, - {"first_name": "Roary", "last_name": "Simmons", "birthday": "1956-07-23", "height": "1.63"}, - {"first_name": "Connor", "last_name": "Jenkins", "birthday": "1969-07-23", "height": "1.67"}, - {"first_name": "Cassady", "last_name": "Knapp", "birthday": "1947-12-15", "height": "1.72"}, {"first_name": "Abdul", "last_name": "Hester", "birthday": "1970-12-02", "height": "1.63"}, - {"first_name": "Evangeline", "last_name": "Weber", "birthday": "1984-06-03", "height": "1.70"}, - {"first_name": "Clementine", "last_name": "Moon", "birthday": "1964-03-29", "height": "1.73"}, - {"first_name": "Montana", "last_name": "Bruce", "birthday": "1952-06-28", "height": "1.66"}, - {"first_name": "Whitney", "last_name": "Durham", "birthday": "1947-09-15", "height": "1.72"}, - {"first_name": "Naomi", "last_name": "Hays", "birthday": "2004-11-27", "height": "1.70"}, - {"first_name": "Macey", "last_name": "Griffin", "birthday": "1971-09-18", "height": "1.63"}, - {"first_name": "Dora", "last_name": "Cabrera", "birthday": "2016-04-26", "height": "1.68"}, - {"first_name": "Chelsea", "last_name": "Castro", "birthday": "2001-08-10", "height": "1.71"}, - {"first_name": "Reese", "last_name": "Noel", "birthday": "1966-11-04", "height": "1.77"}, + {"first_name": "Adam", "last_name": "Goodman", "birthday": "1986-01-07", "height": "1.74"}, + {"first_name": "Adena", "last_name": "Norman", "birthday": "1979-05-14", "height": "1.66"}, + {"first_name": "Aline", "last_name": "Crane", "birthday": "1988-05-01", "height": "1.62"}, {"first_name": "Althea", "last_name": "Barrett", "birthday": "2004-07-28", "height": "1.71"}, - {"first_name": "Odette", "last_name": "Mcneil", "birthday": "1948-05-21", "height": "1.76"}, - {"first_name": "Oliver", "last_name": "Ashley", "birthday": "2004-08-13", "height": "1.68"}, - {"first_name": "Ashton", "last_name": "Fuller", "birthday": "1995-11-17", "height": "1.75"}, - {"first_name": "Denton", "last_name": "Sanchez", "birthday": "1971-10-16", "height": "1.72"}, - {"first_name": "Molly", "last_name": "Salas", "birthday": "1994-04-23", "height": "1.70"}, - {"first_name": "Josiah", "last_name": "Hodges", "birthday": "2011-09-04", "height": "1.68"}, - {"first_name": "Victoria", "last_name": "Slater", "birthday": "2009-07-19", "height": "1.72"}, - {"first_name": "Catherine", "last_name": "Hicks", "birthday": "1959-05-23", "height": "1.80"}, - {"first_name": "Sharon", "last_name": "Shelton", "birthday": "1970-05-02", "height": "1.65"}, - {"first_name": "Rigel", "last_name": "Oneal", "birthday": "1993-11-05", "height": "1.63"}, - {"first_name": "Victor", "last_name": "Woods", "birthday": "1959-06-23", "height": "1.67"}, - {"first_name": "Cathleen", "last_name": "Frank", "birthday": "1947-09-04", "height": "1.61"}, - {"first_name": "Russell", "last_name": "Pruitt", "birthday": "1979-05-04", "height": "1.63"}, - {"first_name": "Warren", "last_name": "Bowen", "birthday": "2000-07-20", "height": "1.76"}, - {"first_name": "Hu", "last_name": "May", "birthday": "1976-10-01", "height": "1.76"}, - {"first_name": "Amanda", "last_name": "Vang", "birthday": "1943-02-23", "height": "1.68"}, - {"first_name": "Fritz", "last_name": "Atkinson", "birthday": "2011-06-15", "height": "1.73"}, - {"first_name": "Scarlett", "last_name": "Durham", "birthday": "2005-09-29", "height": "1.65"}, - {"first_name": "Leroy", "last_name": "Pacheco", "birthday": "1968-12-30", "height": "1.70"}, - {"first_name": "Eagan", "last_name": "Dodson", "birthday": "2015-10-22", "height": "1.67"}, - {"first_name": "Whilemina", "last_name": "Blankenship", "birthday": "1970-07-14", "height": "1.66"}, - {"first_name": "Anne", "last_name": "Rasmussen", "birthday": "1995-04-03", "height": "1.77"}, - {"first_name": "Caryn", "last_name": "Sears", "birthday": "1999-02-17", "height": "1.71"}, - {"first_name": "Elton", "last_name": "Ayers", "birthday": "1994-06-20", "height": "1.68"}, - {"first_name": "Venus", "last_name": "Hurst", "birthday": "1963-10-22", "height": "1.72"}, - {"first_name": "Octavius", "last_name": "Floyd", "birthday": "1955-02-22", "height": "1.68"}, - {"first_name": "Keelie", "last_name": "Mathis", "birthday": "1963-10-26", "height": "1.69"}, - {"first_name": "Wang", "last_name": "Goodwin", "birthday": "1983-05-15", "height": "1.66"}, - {"first_name": "Rhona", "last_name": "Camacho", "birthday": "1946-12-17", "height": "1.59"}, - {"first_name": "Ulla", "last_name": "Arnold", "birthday": "1990-06-04", "height": "1.63"}, - {"first_name": "Idola", "last_name": "Fulton", "birthday": "1974-11-27", "height": "1.66"}, - {"first_name": "Galvin", "last_name": "Phillips", "birthday": "2004-01-17", "height": "1.74"}, - {"first_name": "Faith", "last_name": "Emerson", "birthday": "1959-12-30", "height": "1.62"}, - {"first_name": "Shad", "last_name": "Bradshaw", "birthday": "1968-08-25", "height": "1.72"}, - {"first_name": "Stephen", "last_name": "Baxter", "birthday": "2004-09-24", "height": "1.74"}, - {"first_name": "Tasha", "last_name": "Campos", "birthday": "1984-02-11", "height": "1.72"}, - {"first_name": "Celeste", "last_name": "James", "birthday": "1990-03-08", "height": "1.67"}, - {"first_name": "Ariana", "last_name": "Cole", "birthday": "1947-12-20", "height": "1.72"}, - {"first_name": "Beatrice", "last_name": "Gregory", "birthday": "1992-01-19", "height": "1.80"}, - {"first_name": "Laith", "last_name": "Howell", "birthday": "1961-07-07", "height": "1.70"}, + {"first_name": "Amanda", "last_name": "Vang", "birthday": "1973-02-23", "height": "1.68"}, {"first_name": "Angela", "last_name": "Sanders", "birthday": "2016-01-08", "height": "1.66"}, + {"first_name": "Anne", "last_name": "Rasmussen", "birthday": "1995-04-03", "height": "1.77"}, + {"first_name": "Ariana", "last_name": "Cole", "birthday": "1977-12-20", "height": "1.72"}, + {"first_name": "Ashton", "last_name": "Fuller", "birthday": "1995-11-17", "height": "1.75"}, + {"first_name": "Ava", "last_name": "Sanders", "birthday": "1997-08-10", "height": "1.60"}, + {"first_name": "Barrett", "last_name": "Clemons", "birthday": "1985-07-03", "height": "1.71"}, + {"first_name": "Beatrice", "last_name": "Gregory", "birthday": "1992-01-19", "height": "1.80"}, + {"first_name": "Buffy", "last_name": "Webb", "birthday": "1990-03-06", "height": "1.68"}, + {"first_name": "Callie", "last_name": "Wiley", "birthday": "1987-11-24", "height": "1.69"}, + {"first_name": "Cara", "last_name": "Fox", "birthday": "2004-05-15", "height": "1.71"}, + {"first_name": "Caryn", "last_name": "Sears", "birthday": "1999-02-17", "height": "1.71"}, + {"first_name": "Cassady", "last_name": "Knapp", "birthday": "1977-12-15", "height": "1.72"}, {"first_name": "Cassady", "last_name": "Rogers", "birthday": "2013-11-04", "height": "1.71"}, - {"first_name": "Maia", "last_name": "Hyde", "birthday": "1972-06-09", "height": "1.74"} + {"first_name": "Catherine", "last_name": "Hicks", "birthday": "1989-05-23", "height": "1.80"}, + {"first_name": "Cathleen", "last_name": "Frank", "birthday": "1977-09-04", "height": "1.61"}, + {"first_name": "Celeste", "last_name": "James", "birthday": "1990-03-08", "height": "1.67"}, + {"first_name": "Chelsea", "last_name": "Castro", "birthday": "2001-08-10", "height": "1.71"}, + {"first_name": "Ciaran", "last_name": "Carver", "birthday": "2016-12-25", "height": "1.76"}, + {"first_name": "Ciaran", "last_name": "Hurley", "birthday": "1995-10-25", "height": "1.65"}, + {"first_name": "Clementine", "last_name": "Moon", "birthday": "1994-03-29", "height": "1.73"}, + {"first_name": "Connor", "last_name": "Jenkins", "birthday": "1999-07-23", "height": "1.67"}, + {"first_name": "Courtney", "last_name": "Cannon", "birthday": "1997-10-26", "height": "1.76"}, + {"first_name": "Courtney", "last_name": "Hoffman", "birthday": "1994-11-07", "height": "1.65"}, + {"first_name": "Denton", "last_name": "Sanchez", "birthday": "1971-10-16", "height": "1.72"}, + {"first_name": "Dominique", "last_name": "Sandoval", "birthday": "1972-02-01", "height": "1.72"}, + {"first_name": "Dora", "last_name": "Cabrera", "birthday": "2016-04-26", "height": "1.68"}, + {"first_name": "Eagan", "last_name": "Dodson", "birthday": "2015-10-22", "height": "1.67"}, + {"first_name": "Edan", "last_name": "Dennis", "birthday": "1989-09-18", "height": "1.73"}, + {"first_name": "Ella", "last_name": "Castillo", "birthday": "1973-03-28", "height": "1.73"}, + {"first_name": "Elton", "last_name": "Ayers", "birthday": "1994-06-20", "height": "1.68"}, + {"first_name": "Elton", "last_name": "Smith", "birthday": "1982-06-20", "height": "1.66"}, + {"first_name": "Emma", "last_name": "Clements", "birthday": "1996-08-07", "height": "1.75"}, + {"first_name": "Evangeline", "last_name": "Weber", "birthday": "1984-06-03", "height": "1.70"}, + {"first_name": "Faith", "last_name": "Emerson", "birthday": "1989-12-30", "height": "1.62"}, + {"first_name": "Fritz", "last_name": "Atkinson", "birthday": "2011-06-15", "height": "1.73"}, + {"first_name": "Galvin", "last_name": "Phillips", "birthday": "2004-01-17", "height": "1.74"}, + {"first_name": "Georgia", "last_name": "Kennedy", "birthday": "1974-12-29", "height": "1.66"}, + {"first_name": "Griffith", "last_name": "Henry", "birthday": "1985-04-02", "height": "1.66"}, + {"first_name": "Hedy", "last_name": "Strong", "birthday": "2001-10-04", "height": "1.60"}, + {"first_name": "Hu", "last_name": "May", "birthday": "1976-10-01", "height": "1.76"}, + {"first_name": "Hyacinth", "last_name": "Kent", "birthday": "1971-07-18", "height": "1.72"}, + {"first_name": "Idola", "last_name": "Fulton", "birthday": "1974-11-27", "height": "1.66"}, + {"first_name": "Jarrod", "last_name": "Gibbs", "birthday": "1987-06-13", "height": "1.62"}, + {"first_name": "Jesse", "last_name": "Gomez", "birthday": "2011-01-28", "height": "1.71"}, + {"first_name": "Josiah", "last_name": "Hodges", "birthday": "2011-09-04", "height": "1.68"}, + {"first_name": "Karleigh", "last_name": "Bartlett", "birthday": "1991-10-24", "height": "1.69"}, + {"first_name": "Keelie", "last_name": "Mathis", "birthday": "1993-10-26", "height": "1.69"}, + {"first_name": "Kieran", "last_name": "Solomon", "birthday": "1993-10-30", "height": "1.69"}, + {"first_name": "Laith", "last_name": "Howell", "birthday": "1991-07-07", "height": "1.70"}, + {"first_name": "Leroy", "last_name": "Pacheco", "birthday": "1998-12-30", "height": "1.70"}, + {"first_name": "Lesley", "last_name": "Stephenson", "birthday": "2010-04-10", "height": "1.64"}, + {"first_name": "Macaulay", "last_name": "Rowe", "birthday": "1982-03-02", "height": "1.68"}, + {"first_name": "Macey", "last_name": "Griffin", "birthday": "1971-09-18", "height": "1.63"}, + {"first_name": "Madeline", "last_name": "Kidd", "birthday": "1984-12-09", "height": "1.69"}, + {"first_name": "Maia", "last_name": "Hyde", "birthday": "1972-06-09", "height": "1.74"}, + {"first_name": "Mary", "last_name": "Kirkland", "birthday": "1987-10-09", "height": "1.73"}, + {"first_name": "Molly", "last_name": "Salas", "birthday": "1994-04-23", "height": "1.70"}, + {"first_name": "Montana", "last_name": "Bruce", "birthday": "1982-06-28", "height": "1.66"}, + {"first_name": "Naomi", "last_name": "Hays", "birthday": "2004-11-27", "height": "1.70"}, + {"first_name": "Norman", "last_name": "Santos", "birthday": "1989-01-10", "height": "1.68"}, + {"first_name": "Octavius", "last_name": "Floyd", "birthday": "1985-02-22", "height": "1.68"}, + {"first_name": "Odette", "last_name": "Mcneil", "birthday": "1978-05-21", "height": "1.76"}, + {"first_name": "Oliver", "last_name": "Ashley", "birthday": "2004-08-13", "height": "1.68"}, + {"first_name": "Quon", "last_name": "Wiggins", "birthday": "1992-05-06", "height": "1.74"}, + {"first_name": "Rafael", "last_name": "Parker", "birthday": "2016-01-24", "height": "1.76"}, + {"first_name": "Reese", "last_name": "Noel", "birthday": "1996-11-04", "height": "1.77"}, + {"first_name": "Rhona", "last_name": "Camacho", "birthday": "1976-12-17", "height": "1.59"}, + {"first_name": "Rigel", "last_name": "Oneal", "birthday": "1993-11-05", "height": "1.63"}, + {"first_name": "Roary", "last_name": "Simmons", "birthday": "1986-07-23", "height": "1.63"}, + {"first_name": "Russell", "last_name": "Pruitt", "birthday": "1979-05-04", "height": "1.63"}, + {"first_name": "Sawyer", "last_name": "Fischer", "birthday": "1995-04-01", "height": "1.78"}, + {"first_name": "Scarlett", "last_name": "Durham", "birthday": "2005-09-29", "height": "1.65"}, + {"first_name": "Seth", "last_name": "Serrano", "birthday": "2017-06-02", "height": "1.71"}, + {"first_name": "Shad", "last_name": "Bradshaw", "birthday": "1998-08-25", "height": "1.72"}, + {"first_name": "Shana", "last_name": "Jarvis", "birthday": "1997-05-21", "height": "1.72"}, + {"first_name": "Sharon", "last_name": "Shelton", "birthday": "1970-05-02", "height": "1.65"}, + {"first_name": "Shoshana", "last_name": "Solis", "birthday": "1998-07-18", "height": "1.65"}, + {"first_name": "Stephen", "last_name": "Baxter", "birthday": "2004-09-24", "height": "1.74"}, + {"first_name": "Sydney", "last_name": "Stevens", "birthday": "1989-07-11", "height": "1.70"}, + {"first_name": "Tasha", "last_name": "Campos", "birthday": "1984-02-11", "height": "1.72"}, + {"first_name": "Ulla", "last_name": "Arnold", "birthday": "1990-06-04", "height": "1.63"}, + {"first_name": "Vaughan", "last_name": "Schmidt", "birthday": "1985-06-19", "height": "1.61"}, + {"first_name": "Velma", "last_name": "English", "birthday": "1999-01-18", "height": "1.65"}, + {"first_name": "Venus", "last_name": "Hurst", "birthday": "1993-10-22", "height": "1.72"}, + {"first_name": "Victor", "last_name": "Woods", "birthday": "1989-06-23", "height": "1.67"}, + {"first_name": "Victoria", "last_name": "Slater", "birthday": "2009-07-19", "height": "1.72"}, + {"first_name": "Wang", "last_name": "Goodwin", "birthday": "1983-05-15", "height": "1.66"}, + {"first_name": "Warren", "last_name": "Bowen", "birthday": "2000-07-20", "height": "1.76"}, + {"first_name": "Warren", "last_name": "Dudley", "birthday": "1995-10-23", "height": "1.59"}, + {"first_name": "Whilemina", "last_name": "Blankenship", "birthday": "1970-07-14", "height": "1.66"}, + {"first_name": "Whitney", "last_name": "Durham", "birthday": "1977-09-15", "height": "1.72"}, + {"first_name": "Whitney", "last_name": "Scott", "birthday": "1971-07-04", "height": "1.70"}, + {"first_name": "Wynter", "last_name": "Garcia", "birthday": "1975-01-10", "height": "1.69"}, + {"first_name": "Yolanda", "last_name": "Duke", "birthday": "1997-02-25", "height": "1.74"} ];