add example of using sqlite3 via pipes
FossilOrigin-Name: c5afff65edeeeff084caba6726c10369770fea6f5d8cd9676fb6f6e82f808573
This commit is contained in:
parent
bfe84ee73a
commit
f3dd6271bf
5 changed files with 117 additions and 10 deletions
17
README.md
17
README.md
|
@ -18,16 +18,7 @@ For most systems (FreeBSD, NetBSD, OpenBSD, macOS, Linux):
|
|||
|
||||
make
|
||||
|
||||
You will need a standard C compiler and `make`. The `retro-ri`
|
||||
binary requires (n)curses, but you can ignore any build/link
|
||||
errors by doing:
|
||||
|
||||
make -kis
|
||||
|
||||
If you are building on an older Linux system and are running
|
||||
into problems, try using the alternative Makefile:
|
||||
|
||||
make -f Makefile.linux
|
||||
You will need a standard C compiler and `make`.
|
||||
|
||||
## Executables
|
||||
|
||||
|
@ -77,6 +68,12 @@ fenced blocks:
|
|||
|
||||
Anything outside the fenced blocks will be ignored.
|
||||
|
||||
## Documentation
|
||||
|
||||
The primary documentation is in RETRO-Book.md (and the formatted
|
||||
RETRO-Book.html.) Additional notes can be found in the `doc`
|
||||
directory.
|
||||
|
||||
## Commercial Versions
|
||||
|
||||
I provide proprietary versions of RETRO for iOS and macOS.
|
||||
|
|
|
@ -20,3 +20,7 @@ This is the changelog for the development builds of Retro.
|
|||
|
||||
- updated Linux build instructions
|
||||
- updated Starting instructions
|
||||
|
||||
## Examples
|
||||
|
||||
- add sqlite3 wrapper
|
||||
|
|
64
example/sqlite3/sql.forth
Normal file
64
example/sqlite3/sql.forth
Normal file
|
@ -0,0 +1,64 @@
|
|||
This is an experimental set of words allowing use of sqlite3
|
||||
within RETRO.
|
||||
|
||||
Do not use this in anything public facing. It doesn't do any
|
||||
error checking, input validation, or make any attempt to be
|
||||
remotely secure. It's also slow due to its design.
|
||||
|
||||
A lot of work is needed for this to actually be useful outside
|
||||
of my tests.
|
||||
|
||||
This works by opening pipes to sqlite3, capturing the output,
|
||||
and then processing it from within RETRO. This is slow, but
|
||||
allows me to not need to deal with adding an FFI, and is
|
||||
adaptable to similar external tools.
|
||||
|
||||
~~~
|
||||
{{
|
||||
'Database var
|
||||
:setup here buffer:set ;
|
||||
:pipe @Database 'sqlite3_%s_'%s' s:format file:R unix:popen ;
|
||||
---reveal---
|
||||
:sql:set-database s:keep !Database ;
|
||||
:sql:query
|
||||
[ setup pipe [ dup file:read dup buffer:add n:-zero? ] while unix:pclose ] buffer:preserve here ASCII:LF s:tokenize dup v:dec ;
|
||||
:sql:split-line (s-a) $| s:tokenize ;
|
||||
}}
|
||||
~~~
|
||||
|
||||
# Construct an SQL Statement
|
||||
|
||||
~~~
|
||||
{{
|
||||
{ 'Action 'Choice 'Table 'Clause } [ var ] a:for-each
|
||||
|
||||
:clear { &Action &Choice &Table &Clause } [ v:off ] a:for-each ;
|
||||
---reveal---
|
||||
:SELECT 'SELECT !Action !Choice ;
|
||||
:DROP 'DROP !Action ;
|
||||
:FROM !Table ;
|
||||
:WHERE !Clause ;
|
||||
:sql:statement (q-s)
|
||||
clear call @Clause n:-zero?
|
||||
[ @Clause @Table @Choice @Action '%s_%s_FROM_%s_WHERE_%s ]
|
||||
[ @Table @Choice @Action '%s_%s_FROM_%s ] choose
|
||||
s:format ;
|
||||
}}
|
||||
~~~
|
||||
|
||||
# Generate Accessor Words
|
||||
|
||||
~~~
|
||||
{{
|
||||
'Table var
|
||||
:set-table (s-s) dup s:keep !Table ;
|
||||
:get-columns (s-a) 'PRAGMA_table\_info("%s") s:format sql:query ;
|
||||
:id (a-n) #0 a:th fetch s:to-number ;
|
||||
:column (a-s) #1 a:th fetch @Table '%s:%s s:format ;
|
||||
:generate (ns-) d:create , [ fetch a:th fetch ] does ;
|
||||
---reveal---
|
||||
:sql:accessors-for (s-)
|
||||
set-table get-columns
|
||||
[ sql:split-line [ id ] [ column ] bi generate ] a:for-each ;
|
||||
}}
|
||||
~~~
|
BIN
example/sqlite3/test.db
Normal file
BIN
example/sqlite3/test.db
Normal file
Binary file not shown.
42
example/sqlite3/test.forth
Normal file
42
example/sqlite3/test.forth
Normal file
|
@ -0,0 +1,42 @@
|
|||
This is a test case, using an sqlite3 database to track time off
|
||||
requests at my employer.
|
||||
|
||||
The database schema is:
|
||||
|
||||
CREATE TABLE pto(id integer primary key,
|
||||
month blob, start blob, end blob, year blob, who blob,
|
||||
reason blob, status blob);
|
||||
|
||||
|
||||
Requests are a range, with a start and ending day. Requests for a single
|
||||
day off have identical start and end days.
|
||||
|
||||
~~~
|
||||
'sql.forth include (include_the_sqlite3_wrapper
|
||||
'test.db sql:set-database (set_the_database_file
|
||||
'pto sql:accessors-for (generate_accessors_for_each_column_in_"pto"
|
||||
~~~
|
||||
|
||||
I can query for approved requests (status=y) in the current month.
|
||||
|
||||
~~~
|
||||
[ 'pto FROM '* SELECT 'status="y"_AND_month=5_ORDER_BY_start WHERE ] sql:statement sql:query
|
||||
~~~
|
||||
|
||||
And then iterate over the results, generating some readable output like:
|
||||
|
||||
Charles Childers
|
||||
From: 2019-4-18 through 2019-4-22
|
||||
|
||||
(This part should be refactored to aid in readability, but this works
|
||||
ok for a quick test.)
|
||||
|
||||
~~~
|
||||
[ sql:split-line
|
||||
dup pto:who s:put nl
|
||||
[ &pto:start &pto:month &pto:year tri
|
||||
'\tFrom:_%s-%s-%s_through_ s:format s:put ] sip
|
||||
[ &pto:end &pto:month &pto:year tri
|
||||
'%s-%s-%s\n s:format s:put ] sip
|
||||
drop ] a:for-each
|
||||
~~~
|
Loading…
Reference in a new issue