switching most columns from blob to text

This commit is contained in:
Lex Berezhny 2018-07-14 17:47:51 -04:00
parent f46550262f
commit 9370b1d2fa

View file

@ -108,32 +108,32 @@ class SQLiteMixin(object):
class BaseDatabase(SQLiteMixin): class BaseDatabase(SQLiteMixin):
CREATE_PUBKEY_ADDRESS_TABLE = """
create table if not exists pubkey_address (
address text primary key,
account text not null,
chain integer not null,
position integer not null,
pubkey text not null,
history text,
used_times integer not null default 0
);
"""
CREATE_TX_TABLE = """ CREATE_TX_TABLE = """
create table if not exists tx ( create table if not exists tx (
txhash blob primary key, txid text primary key,
raw blob not null, raw blob not null,
height integer not null, height integer not null,
is_verified boolean not null default 0 is_verified boolean not null default 0
); );
""" """
CREATE_PUBKEY_ADDRESS_TABLE = """
create table if not exists pubkey_address (
address blob primary key,
account blob not null,
chain integer not null,
position integer not null,
pubkey blob not null,
history text,
used_times integer not null default 0
);
"""
CREATE_TXO_TABLE = """ CREATE_TXO_TABLE = """
create table if not exists txo ( create table if not exists txo (
txoid integer primary key, txoid text primary key,
txhash blob references tx, txid text references tx,
address blob references pubkey_address, address text references pubkey_address,
position integer not null, position integer not null,
amount integer not null, amount integer not null,
script blob not null, script blob not null,
@ -143,9 +143,9 @@ class BaseDatabase(SQLiteMixin):
CREATE_TXI_TABLE = """ CREATE_TXI_TABLE = """
create table if not exists txi ( create table if not exists txi (
txhash blob references tx, txid text references tx,
address blob references pubkey_address, txoid text references txo,
txoid integer references txo address text references pubkey_address
); );
""" """
@ -158,9 +158,9 @@ class BaseDatabase(SQLiteMixin):
def txo_to_row(self, tx, address, txo): def txo_to_row(self, tx, address, txo):
return { return {
'txhash': sqlite3.Binary(tx.hash), 'txid': sqlite3.Binary(tx.hash),
'address': sqlite3.Binary(address), 'address': sqlite3.Binary(address),
'position': txo.index, 'position': txo.position,
'amount': txo.amount, 'amount': txo.amount,
'script': sqlite3.Binary(txo.script.source) 'script': sqlite3.Binary(txo.script.source)
} }
@ -245,16 +245,25 @@ class BaseDatabase(SQLiteMixin):
def get_balance_for_account(self, account, **constraints): def get_balance_for_account(self, account, **constraints):
extra_sql = "" extra_sql = ""
if constraints: if constraints:
extra_sql = ' AND ' + ' AND '.join( extras = []
'{} = :{}'.format(c, c) for c in constraints.keys() for key in constraints.keys():
) col, op = key, '='
if key.endswith('__not'):
col, op = key[:-len('__not')], '!='
elif key.endswith('__lte'):
col, op = key[:-len('__lte')], '<='
extras.append('{} {} :{}'.format(col, op, key))
extra_sql = ' AND ' + ' AND '.join(extras)
values = {'account': sqlite3.Binary(account.public_key.address)} values = {'account': sqlite3.Binary(account.public_key.address)}
values.update(constraints) values.update(constraints)
result = yield self.db.runQuery( result = yield self.db.runQuery(
""" """
SELECT SUM(amount) FROM txo SELECT SUM(amount)
FROM txo
JOIN tx ON tx.txhash=txo.txhash
JOIN pubkey_address ON pubkey_address.address=txo.address JOIN pubkey_address ON pubkey_address.address=txo.address
WHERE account=:account AND WHERE
pubkey_address.account=:account AND
txoid NOT IN (SELECT txoid FROM txi) txoid NOT IN (SELECT txoid FROM txi)
"""+extra_sql, values """+extra_sql, values
) )
@ -305,38 +314,6 @@ class BaseDatabase(SQLiteMixin):
values.append(sqlite3.Binary(pubkey.pubkey_bytes)) values.append(sqlite3.Binary(pubkey.pubkey_bytes))
return self.db.runOperation(sql, values) return self.db.runOperation(sql, values)
def get_addresses(self, account, chain, limit=None, details=False):
sql = ["SELECT {} FROM pubkey_address WHERE account = :account"]
params = {'account': sqlite3.Binary(account.public_key.address)}
if chain is not None:
sql.append("AND chain = :chain")
params['chain'] = chain
sql.append("ORDER BY position DESC")
if limit is not None:
sql.append("LIMIT {}".format(limit))
if details:
return self.query_dict_value_list(' '.join(sql), ('address', 'position', 'used_times'), params)
else:
return self.query_one_value_list(' '.join(sql).format('address'), params)
def _used_address_sql(self, account, chain, comparison_op, used_times, limit=None):
sql = [
"SELECT address FROM pubkey_address",
"WHERE account = :account AND"
]
params = {
'account': sqlite3.Binary(account.public_key.address),
'used_times': used_times
}
if chain is not None:
sql.append("chain = :chain AND")
params['chain'] = chain
sql.append("used_times {} :used_times".format(comparison_op))
sql.append("ORDER BY used_times ASC")
if limit is not None:
sql.append('LIMIT {}'.format(limit))
return ' '.join(sql), params
@staticmethod @staticmethod
def _set_address_history(t, address, history): def _set_address_history(t, address, history):
t.execute( t.execute(
@ -347,20 +324,39 @@ class BaseDatabase(SQLiteMixin):
def set_address_history(self, address, history): def set_address_history(self, address, history):
return self.db.runInteraction(lambda t: self._set_address_history(t, address, history)) return self.db.runInteraction(lambda t: self._set_address_history(t, address, history))
def get_unused_addresses(self, account, chain): def get_addresses(self, account, chain, limit=None, max_used_times=None, order_by=None):
# type: (torba.baseaccount.BaseAccount, Union[int,None]) -> defer.Deferred[List[str]] columns = ['account', 'chain', 'position', 'address', 'used_times']
return self.query_one_value_list(*self._used_address_sql( sql = ["SELECT {} FROM pubkey_address"]
account, chain, '=', 0
))
def get_usable_addresses(self, account, chain, max_used_times, limit): where = []
return self.query_one_value_list(*self._used_address_sql( params = {}
account, chain, '<=', max_used_times, limit if account is not None:
)) params["account"] = account.public_key.address
where.append("account = :account")
columns.remove("account")
if chain is not None:
params["chain"] = chain
where.append("chain = :chain")
columns.remove("chain")
if max_used_times is not None:
params["used_times"] = max_used_times
where.append("used_times <= :used_times")
if where:
sql.append("WHERE")
sql.append(" AND ".join(where))
if order_by:
sql.append("ORDER BY {}".format(order_by))
if limit is not None:
sql.append("LIMIT {}".format(limit))
return self.query_dict_value_list(" ".join(sql), columns, params)
def get_address(self, address): def get_address(self, address):
return self.query_dict_value( return self.query_dict_value(
"SELECT {} FROM pubkey_address WHERE address = :address", "SELECT {} FROM pubkey_address WHERE address = :address",
('address', 'account', 'chain', 'position', 'pubkey', 'history', 'used_times'), ('address', 'account', 'chain', 'position', 'pubkey', 'history', 'used_times'),
{'address': sqlite3.Binary(address)} {'address': address}
) )