Skip to content

Commit 212c859

Browse files
committed
plugins/sql: allow some simple functions.
And document them! Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
1 parent 224383b commit 212c859

File tree

3 files changed

+84
-3
lines changed

3 files changed

+84
-3
lines changed

doc/lightning-sql.7.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,28 @@ represented as an integer in the database, so a query will return 0 or
5353
* JSON: string
5454
* sqlite3: TEXT
5555

56+
PERMITTED SQLITE3 FUNCTIONS
57+
---------------------------
58+
Writing to the database is not permitted, and limits are placed
59+
on various other query parameters.
60+
61+
Additionally, only the following functions are allowed:
62+
63+
* abs
64+
* avg
65+
* coalesce
66+
* count
67+
* hex
68+
* quote
69+
* length
70+
* like
71+
* lower
72+
* upper
73+
* min
74+
* max
75+
* sum
76+
* total
77+
5678
TABLES
5779
------
5880
[comment]: # (GENERATE-DOC-START)

plugins/sql.c

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,38 @@ static int sqlite_authorize(void *dbq_, int code,
264264
return SQLITE_OK;
265265
}
266266

267+
/* Some functions are fairly necessary: */
268+
if (code == SQLITE_FUNCTION) {
269+
if (streq(b, "abs"))
270+
return SQLITE_OK;
271+
if (streq(b, "avg"))
272+
return SQLITE_OK;
273+
if (streq(b, "coalesce"))
274+
return SQLITE_OK;
275+
if (streq(b, "count"))
276+
return SQLITE_OK;
277+
if (streq(b, "hex"))
278+
return SQLITE_OK;
279+
if (streq(b, "quote"))
280+
return SQLITE_OK;
281+
if (streq(b, "length"))
282+
return SQLITE_OK;
283+
if (streq(b, "like"))
284+
return SQLITE_OK;
285+
if (streq(b, "lower"))
286+
return SQLITE_OK;
287+
if (streq(b, "upper"))
288+
return SQLITE_OK;
289+
if (streq(b, "min"))
290+
return SQLITE_OK;
291+
if (streq(b, "max"))
292+
return SQLITE_OK;
293+
if (streq(b, "sum"))
294+
return SQLITE_OK;
295+
if (streq(b, "total"))
296+
return SQLITE_OK;
297+
}
298+
267299
/* See https://www.sqlite.org/c3ref/c_alter_table.html to decode these! */
268300
dbq->authfail = tal_fmt(dbq, "Unauthorized: %u arg1=%s arg2=%s dbname=%s caller=%s",
269301
code,

tests/test_plugin.py

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3280,10 +3280,16 @@ def test_block_added_notifications(node_factory, bitcoind):
32803280
@pytest.mark.openchannel('v2')
32813281
@pytest.mark.developer("wants dev-announce-localhost so we see listnodes.addresses")
32823282
def test_sql(node_factory, bitcoind):
3283+
opts = {'experimental-offers': None,
3284+
'dev-allow-localhost': None}
3285+
l2opts = {'lease-fee-basis': 50,
3286+
'lease-fee-base-sat': '2000msat',
3287+
'channel-fee-max-base-msat': '500sat',
3288+
'channel-fee-max-proportional-thousandths': 200,
3289+
'sqlfilename': 'sql.sqlite3'}
3290+
l2opts.update(opts)
32833291
l1, l2, l3 = node_factory.line_graph(3, wait_for_announce=True,
3284-
opts={'experimental-offers': None,
3285-
'sqlfilename': 'sql.sqlite3',
3286-
'dev-allow-localhost': None})
3292+
opts=[opts, l2opts, opts])
32873293

32883294
ret = l2.rpc.sql("SELECT * FROM forwards;")
32893295
assert ret == {'rows': []}
@@ -3794,6 +3800,27 @@ def test_sql(node_factory, bitcoind):
37943800
with pytest.raises(RpcError, match='query failed with no such table: peers_channels'):
37953801
l2.rpc.sql("SELECT * FROM peers_channels;")
37963802

3803+
# Test subobject case (option_will_fund)
3804+
ret = l2.rpc.sql("SELECT option_will_fund_lease_fee_base_msat,"
3805+
" option_will_fund_lease_fee_basis,"
3806+
" option_will_fund_funding_weight,"
3807+
" option_will_fund_channel_fee_max_base_msat,"
3808+
" option_will_fund_channel_fee_max_proportional_thousandths,"
3809+
" option_will_fund_compact_lease"
3810+
" FROM nodes WHERE HEX(nodeid) = '{}';".format(l2.info['id'].upper()))
3811+
optret = only_one(l2.rpc.listnodes(l2.info['id'])['nodes'])['option_will_fund']
3812+
row = only_one(ret['rows'])
3813+
assert row == [v for v in optret.values()]
3814+
3815+
# Correctly handles missing object.
3816+
assert l2.rpc.sql("SELECT option_will_fund_lease_fee_base_msat,"
3817+
" option_will_fund_lease_fee_basis,"
3818+
" option_will_fund_funding_weight,"
3819+
" option_will_fund_channel_fee_max_base_msat,"
3820+
" option_will_fund_channel_fee_max_proportional_thousandths,"
3821+
" option_will_fund_compact_lease"
3822+
" FROM nodes WHERE HEX(nodeid) = '{}';".format(l1.info['id'].upper())) == {'rows': [[None] * 6]}
3823+
37973824

37983825
def test_sql_deprecated(node_factory, bitcoind):
37993826
# deprecated-apis breaks schemas...

0 commit comments

Comments
 (0)