Skip to content
This repository was archived by the owner on Sep 28, 2022. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 46 additions & 47 deletions pilosa/orm.py
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,7 @@ def count(self, row):
"""
return PQLQuery(u"Count(%s)" % row.serialize(), self)

def set_column_attrs(self, column_idkey, attrs):
def set_column_attrs(self, col, attrs):
"""Creates a SetColumnAttrs query.

``SetColumnAttrs`` associates arbitrary key/value pairs with a column in an index.
Expand All @@ -321,16 +321,15 @@ def set_column_attrs(self, column_idkey, attrs):
* bool
* float

:param int column_idkey:
:param int col:
:param dict attrs: column attributes
:return: Pilosa query
:rtype: pilosa.PQLQuery
"""
fmt = id_key_format("Column", column_idkey,
u"SetColumnAttrs(%s, %s)",
u"SetColumnAttrs('%s, %s)")
col_str = idkey_as_str(col)
attrs_str = _create_attributes_str(attrs)
return PQLQuery(fmt % (column_idkey, attrs_str), self)
fmt = u"SetColumnAttrs(%s,%s)"
return PQLQuery(fmt % (col_str, attrs_str), self)

def _row_op(self, name, rows):
return PQLQuery(u"%s(%s)" % (name, u", ".join(b.serialize() for b in rows)), self)
Expand Down Expand Up @@ -406,47 +405,37 @@ def row(self, row_idkey):
u"Row(%s='%s')")
return PQLQuery(fmt % (self.name, row_idkey), self.index)

def set(self, row_idkey, column_idkey, timestamp=None):
def set(self, row, col, timestamp=None):
"""Creates a SetBit query.

``SetBit`` assigns a value of 1 to a bit in the binary matrix, thus associating the given row in the given field with the given column.

:param int row_idkey:
:param int column_idkey:
:param int row:
:param int col:
:param pilosa.TimeStamp timestamp:
:return: Pilosa query
:rtype: pilosa.PQLQuery
"""
if isinstance(row_idkey, int) and isinstance(column_idkey, int):
fmt = u"Set(%s, %s=%s%s)"
elif isinstance(row_idkey, _basestring) and isinstance(column_idkey, _basestring):
fmt = u"Set('%s', %s='%s'%s)"
validate_key(row_idkey)
validate_key(column_idkey)
else:
raise ValidationError("Both Row and Columns must be integers or strings")
row_str = idkey_as_str(row)
col_str = idkey_as_str(col)
ts = ", %s" % timestamp.strftime(_TIME_FORMAT) if timestamp else ''
return PQLQuery(fmt % (column_idkey, self.name, row_idkey, ts), self.index)
fmt = u"Set(%s,%s=%s%s)"
return PQLQuery(fmt % (col_str, self.name, row_str, ts), self.index)

def clear(self, row_idkey, column_idkey):
def clear(self, row, col):
"""Creates a ClearBit query.

``ClearBit`` assigns a value of 0 to a bit in the binary matrix, thus disassociating the given row in the given field from the given column.

:param int row_idkey:
:param int column_idkey:
:param int row:
:param int col:
:return: Pilosa query
:rtype: pilosa.PQLQuery
"""
if isinstance(row_idkey, int) and isinstance(column_idkey, int):
fmt = u"Clear(%s, %s=%s)"
elif isinstance(row_idkey, _basestring) and isinstance(column_idkey, _basestring):
fmt = u"Clear('%s', %s='%s')"
validate_key(row_idkey)
validate_key(column_idkey)
else:
raise ValidationError("Both Row and Columns must be integers or strings")
return PQLQuery(fmt % (column_idkey, self.name, row_idkey), self.index)
row_str = idkey_as_str(row)
col_str = idkey_as_str(col)
fmt = u"Clear(%s,%s=%s)"
return PQLQuery(fmt % (col_str, self.name, row_str), self.index)

def topn(self, n, row=None, field="", *values):
"""Creates a TopN query.
Expand All @@ -468,29 +457,28 @@ def topn(self, n, row=None, field="", *values):
validate_label(field)
values_str = json.dumps(values, separators=(',', ': '))
parts.extend(["field='%s'" % field, "filters=%s" % values_str])
qry = u"TopN(%s)" % ", ".join(parts)
qry = u"TopN(%s)" % ",".join(parts)
return PQLQuery(qry, self.index)

def range(self, row_idkey, start, end):
def range(self, row, start, end):
"""Creates a Range query.

Similar to ``Row``, but only returns columns which were set with timestamps between the given start and end timestamps.

* see: `Range Query <https://www.pilosa.com/docs/query-language/#range>`_

:param int row_idkey:
:param int row:
:param datetime.datetime start: start timestamp
:param datetime.datetime end: end timestamp
"""
fmt = id_key_format("Row", row_idkey,
u"Range(%s=%s, %s, %s)",
u"Range(%s='%s', %s, %s)")
row_str = idkey_as_str(row)
start_str = start.strftime(_TIME_FORMAT)
end_str = end.strftime(_TIME_FORMAT)
return PQLQuery(fmt % (self.name, row_idkey, start_str, end_str),
fmt = u"Range(%s=%s,%s,%s)"
return PQLQuery(fmt % (self.name, row_str, start_str, end_str),
self.index)

def set_row_attrs(self, row_idkey, attrs):
def set_row_attrs(self, row, attrs):
"""Creates a SetRowAttrs query.

``SetRowAttrs`` associates arbitrary key/value pairs with a row in a field.
Expand All @@ -502,16 +490,15 @@ def set_row_attrs(self, row_idkey, attrs):
* bool
* float

:param int row_idkey:
:param int row:
:param dict attrs: row attributes
:return: Pilosa query
:rtype: pilosa.PQLQuery
"""
fmt = id_key_format("Row", row_idkey,
u"SetRowAttrs(%s, %s, %s)",
u"SetRowAttrs('%s', '%s', %s)")
row_str = idkey_as_str(row)
attrs_str = _create_attributes_str(attrs)
return PQLQuery(fmt % (self.name, row_idkey, attrs_str), self.index)
fmt = u"SetRowAttrs(%s,%s,%s)"
return PQLQuery(fmt % (self.name, row_str, attrs_str), self.index)

def lt(self, n):
"""Creates a Range query with less than (<) condition.
Expand Down Expand Up @@ -614,15 +601,16 @@ def max(self, row=None):
"""
return self._value_query("Max", row)

def setvalue(self, column_id, value):
def setvalue(self, col, value):
"""Creates a SetValue query.

:param column_id: column ID
:param col: column ID or key
:param value: the value to assign to the field
:return: a PQL query
:rtype: PQLQuery
"""
q = u"Set(%d, %s=%d)" % (column_id, self.name, value)
col_str = idkey_as_str(col)
q = u"Set(%s,%s=%d)" % (col_str, self.name, value)
return PQLQuery(q, self.index)

def _binary_operation(self, op, n):
Expand Down Expand Up @@ -671,7 +659,7 @@ def _create_attributes_str(attrs):
# TODO: make key use its own validator
validate_label(k)
kvs.append("%s=%s" % (k, json.dumps(v)))
return ", ".join(sorted(kvs))
return ",".join(sorted(kvs))
except TypeError:
raise PilosaError("Error while converting values")

Expand All @@ -697,3 +685,14 @@ def id_key_format(name, id_key, id_fmt, key_fmt):
return key_fmt
else:
raise ValidationError("%s must be an integer or string" % name)


def idkey_as_str(idkey):
if isinstance(idkey, int):
row_idkey_str = str(idkey)
elif isinstance(idkey, _basestring):
validate_key(idkey)
row_idkey_str = "'%s'" % idkey
else:
raise ValidationError("Rows/Columns must be integers or strings")
return row_idkey_str
79 changes: 53 additions & 26 deletions tests/test_orm.py
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,12 @@ def test_set_column_attributes(self):
}
q = projectIndex.set_column_attrs(5, attrs_map)
self.assertEquals(
u"SetColumnAttrs(5, happy=true, quote=\"\\\"Don't worry, be happy\\\"\")",
u"SetColumnAttrs(5,happy=true,quote=\"\\\"Don't worry, be happy\\\"\")",
q.serialize())

q = projectIndex.set_column_attrs("some_id", attrs_map)
self.assertEquals(
u"SetColumnAttrs('some_id',happy=true,quote=\"\\\"Don't worry, be happy\\\"\")",
q.serialize())

def test_set_column_attributes_invalid_values(self):
Expand All @@ -214,6 +219,10 @@ def test_set_column_attributes_invalid_values(self):
}
self.assertRaises(PilosaError, projectIndex.set_column_attrs, 5, attrs_map)

def test_get_options_string(self):
index = Index("my-index", keys=True)
self.assertEqual('{"options":{"keys":true}}', index._get_options_string())


class FieldTestCase(unittest.TestCase):

Expand Down Expand Up @@ -246,64 +255,77 @@ def test_row_with_invalid_id_type(self):
self.assertRaises(ValidationError, sampleField.row, {})

def test_set(self):
qry1 = collabField.set(5, 10)
qry = collabField.set(5, 10)
self.assertEquals(
u"Set(10, collaboration=5)",
qry1.serialize())
u"Set(10,collaboration=5)",
qry.serialize())

qry2 = collabField.set("b7feb014-8ea7-49a8-9cd8-19709161ab63", "some_id")
qry = collabField.set(5, "some_id")
self.assertEquals(
u"Set('some_id', collaboration='b7feb014-8ea7-49a8-9cd8-19709161ab63')",
qry2.serialize())
u"Set('some_id',collaboration=5)",
qry.serialize())

qry = collabField.set("b7feb014-8ea7-49a8-9cd8-19709161ab63", 10)
self.assertEquals(
u"Set(10,collaboration='b7feb014-8ea7-49a8-9cd8-19709161ab63')",
qry.serialize())

qry = collabField.set("b7feb014-8ea7-49a8-9cd8-19709161ab63", "some_id")
self.assertEquals(
u"Set('some_id',collaboration='b7feb014-8ea7-49a8-9cd8-19709161ab63')",
qry.serialize())

def test_set_with_invalid_id_type(self):
self.assertRaises(ValidationError, sampleField.set, {}, 1)
self.assertRaises(ValidationError, sampleField.set, 1, {})
self.assertRaises(ValidationError, sampleField.set, 1, "zero")

def test_set_with_timestamp(self):
timestamp = datetime(2017, 4, 24, 12, 14)
qry = collabField.set(10, 20, timestamp)
self.assertEquals(
u"Set(20, collaboration=10, 2017-04-24T12:14)",
u"Set(20,collaboration=10, 2017-04-24T12:14)",
qry.serialize()
)

def test_clear(self):
qry1 = collabField.clear(5, 10)
qry = collabField.clear(5, 10)
self.assertEquals(
"Clear(10, collaboration=5)",
qry1.serialize())
"Clear(10,collaboration=5)",
qry.serialize())

qry2 = collabField.clear(10, 20)
qry = collabField.clear(5, 'some_id')
self.assertEquals(
"Clear(20, collaboration=10)",
qry2.serialize())
"Clear('some_id',collaboration=5)",
qry.serialize())

qry3 = collabField.clear("b7feb014-8ea7-49a8-9cd8-19709161ab63", "some_id")
qry = collabField.clear("b7feb014-8ea7-49a8-9cd8-19709161ab63", 10)
self.assertEquals(
"Clear('some_id', collaboration='b7feb014-8ea7-49a8-9cd8-19709161ab63')",
qry3.serialize())
"Clear(10,collaboration='b7feb014-8ea7-49a8-9cd8-19709161ab63')",
qry.serialize())

qry = collabField.clear("b7feb014-8ea7-49a8-9cd8-19709161ab63", "some_id")
self.assertEquals(
"Clear('some_id',collaboration='b7feb014-8ea7-49a8-9cd8-19709161ab63')",
qry.serialize())

def test_clear_with_invalid_id_type(self):
self.assertRaises(ValidationError, sampleField.clear, {}, 1)
self.assertRaises(ValidationError, sampleField.clear, 1, {})
self.assertRaises(ValidationError, sampleField.clear, 1, "zero")

def test_topn(self):
q1 = collabField.topn(27)
self.assertEquals(
u"TopN(collaboration, n=27)",
u"TopN(collaboration,n=27)",
q1.serialize())

q2 = collabField.topn(10, collabField.row(3))
self.assertEquals(
u"TopN(collaboration, Row(collaboration=3), n=10)",
u"TopN(collaboration,Row(collaboration=3),n=10)",
q2.serialize())

q3 = sampleField.topn(12, collabField.row(7), "category", 80, 81)
self.assertEquals(
u"TopN(sample-field, Row(collaboration=7), n=12, field='category', filters=[80,81])",
u"TopN(sample-field,Row(collaboration=7),n=12,field='category',filters=[80,81])",
q3.serialize())

def test_range(self):
Expand All @@ -312,12 +334,12 @@ def test_range(self):

q1 = collabField.range(10, start, end)
self.assertEquals(
u"Range(collaboration=10, 1970-01-01T00:00, 2000-02-02T03:04)",
u"Range(collaboration=10,1970-01-01T00:00,2000-02-02T03:04)",
q1.serialize())

q3 = collabField.range("b7feb014-8ea7-49a8-9cd8-19709161ab63", start, end)
self.assertEquals(
u"Range(collaboration='b7feb014-8ea7-49a8-9cd8-19709161ab63', 1970-01-01T00:00, 2000-02-02T03:04)",
u"Range(collaboration='b7feb014-8ea7-49a8-9cd8-19709161ab63',1970-01-01T00:00,2000-02-02T03:04)",
q3.serialize())

def test_set_row_attributes(self):
Expand All @@ -327,7 +349,7 @@ def test_set_row_attributes(self):
}
q = collabField.set_row_attrs(5, attrs_map)
self.assertEquals(
u'SetRowAttrs(collaboration, 5, active=true, quote="\\"Don\'t worry, be happy\\"")',
u'SetRowAttrs(collaboration,5,active=true,quote="\\"Don\'t worry, be happy\\"")',
q.serialize())

def test_field_lt(self):
Expand Down Expand Up @@ -391,7 +413,12 @@ def test_field_sum(self):
def test_field_set_value(self):
q = collabField.setvalue(10, 20)
self.assertEquals(
"Set(10, collaboration=20)",
"Set(10,collaboration=20)",
q.serialize())

q = collabField.setvalue("some_id", 20)
self.assertEquals(
"Set('some_id',collaboration=20)",
q.serialize())

def test_get_options_string(self):
Expand Down