8
8
#include <common/json_param.h>
9
9
#include <common/json_stream.h>
10
10
#include <common/memleak.h>
11
+ #include <common/setup.h>
11
12
#include <common/type_to_string.h>
12
13
#include <errno.h>
13
14
#include <fcntl.h>
14
15
#include <gossipd/gossip_store_wiregen.h>
15
16
#include <plugins/libplugin.h>
16
17
#include <sqlite3.h>
18
+ #include <stdio.h>
17
19
#include <sys/stat.h>
18
20
#include <sys/types.h>
19
21
#include <unistd.h>
@@ -25,8 +27,6 @@ static const char schemas[] =
25
27
26
28
/* TODO:
27
29
* 2. Refresh time in API.
28
- * 3. Colnames API to return dict.
29
- * 4. sql-schemas command.
30
30
* 5. documentation.
31
31
* 6. test on mainnet.
32
32
* 7. Some cool query for documentation.
@@ -94,9 +94,10 @@ struct db_query {
94
94
};
95
95
96
96
struct table_desc {
97
- /* e.g. listpeers */
97
+ /* e.g. listpeers. For sub-tables, the raw name without
98
+ * parent prepended */
98
99
const char * cmdname ;
99
- /* e.g. peers for listpeers */
100
+ /* e.g. peers for listpeers, peers_channels for listpeers.channels. */
100
101
const char * name ;
101
102
/* e.g. "payments" for listsendpays */
102
103
const char * arrname ;
@@ -969,7 +970,7 @@ static bool ignore_column(const struct table_desc *td, const jsmntok_t *t)
969
970
return false;
970
971
}
971
972
972
- /* Creates sql statements, initializes table, adds to tablemap */
973
+ /* Creates sql statements, initializes table */
973
974
static void finish_td (struct plugin * plugin , struct table_desc * td )
974
975
{
975
976
char * create_stmt ;
@@ -1027,8 +1028,6 @@ static void finish_td(struct plugin *plugin, struct table_desc *td)
1027
1028
if (err != SQLITE_OK )
1028
1029
plugin_err (plugin , "Could not create %s: %s" , td -> name , errmsg );
1029
1030
1030
- strmap_add (& tablemap , td -> name , td );
1031
-
1032
1031
/* Now do any children */
1033
1032
for (size_t i = 0 ; i < tal_count (td -> columns ); i ++ ) {
1034
1033
const struct column * col = & td -> columns [i ];
@@ -1101,6 +1100,11 @@ static struct table_desc *new_table_desc(struct table_desc *parent,
1101
1100
td -> refresh = nodes_refresh ;
1102
1101
else
1103
1102
td -> refresh = default_refresh ;
1103
+
1104
+ /* sub-objects are a JSON thing, not a real table! */
1105
+ if (!td -> is_subobject )
1106
+ strmap_add (& tablemap , td -> name , td );
1107
+
1104
1108
return td ;
1105
1109
}
1106
1110
@@ -1238,6 +1242,7 @@ static void add_table_object(struct table_desc *td, const jsmntok_t *tok)
1238
1242
add_table_object (td , cond );
1239
1243
}
1240
1244
1245
+ /* plugin is NULL if we're just doing --print-docs */
1241
1246
static void init_tablemap (struct plugin * plugin )
1242
1247
{
1243
1248
const jsmntok_t * toks , * t ;
@@ -1259,10 +1264,14 @@ static void init_tablemap(struct plugin *plugin)
1259
1264
assert (json_tok_streq (schemas , type , "object" ));
1260
1265
1261
1266
td = new_table_desc (NULL , t , cmd , false);
1262
- tal_steal (plugin , td );
1267
+ if (plugin )
1268
+ tal_steal (plugin , td );
1269
+ else
1270
+ tal_steal (tmpctx , td );
1263
1271
add_table_object (td , items );
1264
1272
1265
- finish_td (plugin , td );
1273
+ if (plugin )
1274
+ finish_td (plugin , td );
1266
1275
}
1267
1276
}
1268
1277
@@ -1315,9 +1324,102 @@ static const struct plugin_command commands[] = { {
1315
1324
},
1316
1325
};
1317
1326
1327
+ static const char * fmt_indexes (const tal_t * ctx , const char * table )
1328
+ {
1329
+ char * ret = NULL ;
1330
+
1331
+ for (size_t i = 0 ; i < ARRAY_SIZE (indices ); i ++ ) {
1332
+ if (!streq (indices [i ].tablename , table ))
1333
+ continue ;
1334
+ /* FIXME: Handle multiple indices! */
1335
+ assert (!ret );
1336
+ BUILD_ASSERT (ARRAY_SIZE (indices [i ].fields ) == 2 );
1337
+ if (indices [i ].fields [1 ])
1338
+ ret = tal_fmt (tmpctx , "%s and %s" ,
1339
+ indices [i ].fields [0 ],
1340
+ indices [i ].fields [1 ]);
1341
+ else
1342
+ ret = tal_fmt (tmpctx , "%s" ,
1343
+ indices [i ].fields [0 ]);
1344
+ }
1345
+ if (!ret )
1346
+ return "" ;
1347
+ return tal_fmt (ctx , " indexed by `%s`" , ret );
1348
+ }
1349
+
1350
+ static void print_columns (const struct table_desc * td , const char * indent ,
1351
+ const char * objsrc )
1352
+ {
1353
+ for (size_t i = 0 ; i < tal_count (td -> columns ); i ++ ) {
1354
+ const char * origin ;
1355
+ if (td -> columns [i ].sub ) {
1356
+ const struct table_desc * subtd = td -> columns [i ].sub ;
1357
+
1358
+ if (!subtd -> is_subobject ) {
1359
+ const char * subindent ;
1360
+
1361
+ subindent = tal_fmt (tmpctx , "%s " , indent );
1362
+ printf ("%s- related table `%s`%s\n" ,
1363
+ indent , subtd -> name , objsrc );
1364
+ printf ("%s- `row` (reference to `%s.rowid`, sqltype `INTEGER`)\n"
1365
+ "%s- `arrindex` (index within array, sqltype `INTEGER`)\n" ,
1366
+ subindent , td -> name , subindent );
1367
+ print_columns (subtd , subindent , "" );
1368
+ } else {
1369
+ const char * subobjsrc ;
1370
+
1371
+ subobjsrc = tal_fmt (tmpctx ,
1372
+ ", from JSON object `%s`" ,
1373
+ td -> columns [i ].jsonname );
1374
+ print_columns (subtd , indent , subobjsrc );
1375
+ }
1376
+ continue ;
1377
+ }
1378
+
1379
+ if (streq (objsrc , "" )
1380
+ && td -> columns [i ].jsonname
1381
+ && !streq (td -> columns [i ].dbname , td -> columns [i ].jsonname )) {
1382
+ origin = tal_fmt (tmpctx , ", from JSON field `%s`" ,
1383
+ td -> columns [i ].jsonname );
1384
+ } else
1385
+ origin = "" ;
1386
+ printf ("%s- `%s` (type `%s`, sqltype `%s`%s%s)\n" ,
1387
+ indent , td -> columns [i ].dbname ,
1388
+ fieldtypemap [td -> columns [i ].ftype ].name ,
1389
+ fieldtypemap [td -> columns [i ].ftype ].sqltype ,
1390
+ origin , objsrc );
1391
+ }
1392
+ }
1393
+
1394
+ static bool print_one_table (const char * member ,
1395
+ struct table_desc * td ,
1396
+ void * unused )
1397
+ {
1398
+ if (td -> parent )
1399
+ return true;
1400
+
1401
+ printf ("- `%s`%s (see lightning-%s(7))\n" ,
1402
+ member , fmt_indexes (tmpctx , member ), td -> cmdname );
1403
+
1404
+ print_columns (td , " " , "" );
1405
+ printf ("\n" );
1406
+ return true;
1407
+ }
1408
+
1318
1409
int main (int argc , char * argv [])
1319
1410
{
1320
1411
setup_locale ();
1412
+
1413
+ if (argc == 2 && streq (argv [1 ], "--print-docs" )) {
1414
+ common_setup (argv [0 ]);
1415
+ /* plugin is NULL, so just sets up tables */
1416
+ init_tablemap (NULL );
1417
+
1418
+ printf ("The following tables are currently supported:\n" );
1419
+ strmap_iterate (& tablemap , print_one_table , NULL );
1420
+ common_shutdown ();
1421
+ return 0 ;
1422
+ }
1321
1423
plugin_main (argv , init , PLUGIN_RESTARTABLE , true, NULL , commands , ARRAY_SIZE (commands ),
1322
1424
NULL , 0 , NULL , 0 , NULL , 0 ,
1323
1425
plugin_option ("sqlfilename" ,
0 commit comments