import sqlite3
import decimal
class DecimalSum:
def __init__(self):
self.sum = None
def step(self, value):
if value is None:
return
v = decimal.Decimal(value)
if self.sum is None:
self.sum = v
else:
self.sum += v
def finalize(self):
return None if self.sum is None else str(self.sum)
def adapt_decimal(d):
return str(d)
def convert_decimal(s):
return decimal.Decimal(s.decode('ascii')) # required for Python 3
# Register the adapter
sqlite3.register_adapter(decimal.Decimal, adapt_decimal)
# Register the converter
sqlite3.register_converter("DECTEXT", convert_decimal)
# We need also sqlite3.PARSE_COLNAMES for returning correct type for
# aggregate function decimal_sum:
con = sqlite3.connect(":memory:", detect_types=sqlite3.PARSE_DECLTYPES|sqlite3.PARSE_COLNAMES)
con.create_aggregate("decimal_sum", 1, DecimalSum)
cur = con.cursor()
cur.execute("""CREATE TABLE a_test(
a_decimal DECTEXT NOT NULL -- will be stored as TEXT
)""")
con.execute("INSERT INTO a_test VALUES(?)", (decimal.Decimal("102.20"),))
# Convert sum to decimal explicitly:
cur.execute("SELECT decimal_sum(a_decimal) AS `s [DECTEXT]` from a_test")
data = cur.fetchone()[0]
print(data)
print(type(data))
cur.close()
con.close()
aW1wb3J0IHNxbGl0ZTMKaW1wb3J0IGRlY2ltYWwKCmNsYXNzIERlY2ltYWxTdW06CiAgICBkZWYgX19pbml0X18oc2VsZik6CiAgICAgICAgc2VsZi5zdW0gPSBOb25lCgogICAgZGVmIHN0ZXAoc2VsZiwgdmFsdWUpOgogICAgICAgIGlmIHZhbHVlIGlzIE5vbmU6CiAgICAgICAgICAgIHJldHVybgogICAgICAgIHYgPSBkZWNpbWFsLkRlY2ltYWwodmFsdWUpCiAgICAgICAgaWYgc2VsZi5zdW0gaXMgTm9uZToKICAgICAgICAgICAgc2VsZi5zdW0gPSB2CiAgICAgICAgZWxzZToKICAgICAgICAgICAgc2VsZi5zdW0gKz0gdgoKICAgIGRlZiBmaW5hbGl6ZShzZWxmKToKICAgICAgICByZXR1cm4gTm9uZSBpZiBzZWxmLnN1bSBpcyBOb25lIGVsc2Ugc3RyKHNlbGYuc3VtKQoKZGVmIGFkYXB0X2RlY2ltYWwoZCk6CiAgICByZXR1cm4gc3RyKGQpCgpkZWYgY29udmVydF9kZWNpbWFsKHMpOgogICAgcmV0dXJuIGRlY2ltYWwuRGVjaW1hbChzLmRlY29kZSgnYXNjaWknKSkgIyByZXF1aXJlZCBmb3IgUHl0aG9uIDMKCiMgUmVnaXN0ZXIgdGhlIGFkYXB0ZXIKc3FsaXRlMy5yZWdpc3Rlcl9hZGFwdGVyKGRlY2ltYWwuRGVjaW1hbCwgYWRhcHRfZGVjaW1hbCkKIyBSZWdpc3RlciB0aGUgY29udmVydGVyCnNxbGl0ZTMucmVnaXN0ZXJfY29udmVydGVyKCJERUNURVhUIiwgY29udmVydF9kZWNpbWFsKQoKIyBXZSBuZWVkIGFsc28gc3FsaXRlMy5QQVJTRV9DT0xOQU1FUyBmb3IgcmV0dXJuaW5nIGNvcnJlY3QgdHlwZSBmb3IKIyBhZ2dyZWdhdGUgZnVuY3Rpb24gZGVjaW1hbF9zdW06CmNvbiA9IHNxbGl0ZTMuY29ubmVjdCgiOm1lbW9yeToiLCBkZXRlY3RfdHlwZXM9c3FsaXRlMy5QQVJTRV9ERUNMVFlQRVN8c3FsaXRlMy5QQVJTRV9DT0xOQU1FUykKY29uLmNyZWF0ZV9hZ2dyZWdhdGUoImRlY2ltYWxfc3VtIiwgMSwgRGVjaW1hbFN1bSkKY3VyID0gY29uLmN1cnNvcigpCmN1ci5leGVjdXRlKCIiIkNSRUFURSBUQUJMRSBhX3Rlc3QoCiAgYV9kZWNpbWFsIERFQ1RFWFQgTk9UIE5VTEwgIC0tIHdpbGwgYmUgc3RvcmVkIGFzIFRFWFQKKSIiIikKCmNvbi5leGVjdXRlKCJJTlNFUlQgSU5UTyBhX3Rlc3QgVkFMVUVTKD8pIiwgKGRlY2ltYWwuRGVjaW1hbCgiMTAyLjIwIiksKSkKIyBDb252ZXJ0IHN1bSB0byBkZWNpbWFsIGV4cGxpY2l0bHk6CmN1ci5leGVjdXRlKCJTRUxFQ1QgZGVjaW1hbF9zdW0oYV9kZWNpbWFsKSBBUyBgcyBbREVDVEVYVF1gIGZyb20gYV90ZXN0IikKZGF0YSA9IGN1ci5mZXRjaG9uZSgpWzBdCnByaW50KGRhdGEpCnByaW50KHR5cGUoZGF0YSkpCgpjdXIuY2xvc2UoKQpjb24uY2xvc2UoKQ==