Refactorings of the cont-responder and sqlite code. The browser
responder now accepts 'word' and 'vocab' as query parameters. The cont-responder takes the continuation id as a query parameter instead of part of the url.cvs
parent
a1d6e58851
commit
f88bfcf2a8
|
@ -45,6 +45,7 @@ USE: errors
|
||||||
USE: unparser
|
USE: unparser
|
||||||
USE: logging
|
USE: logging
|
||||||
USE: listener
|
USE: listener
|
||||||
|
USE: url-encoding
|
||||||
|
|
||||||
: <browser> ( allow-edit? vocab word -- )
|
: <browser> ( allow-edit? vocab word -- )
|
||||||
#! An object for storing the current browser
|
#! An object for storing the current browser
|
||||||
|
@ -187,6 +188,15 @@ USE: listener
|
||||||
] when*
|
] when*
|
||||||
] catch ;
|
] catch ;
|
||||||
|
|
||||||
|
: browser-url ( vocab word -- url )
|
||||||
|
#! Given a vocabulary and word as strings, return a browser
|
||||||
|
#! URL which, when requested, will display the source to that
|
||||||
|
#! word.
|
||||||
|
[
|
||||||
|
".?word=" , url-encode ,
|
||||||
|
"&vocab=" , url-encode ,
|
||||||
|
] make-string ;
|
||||||
|
|
||||||
: browse ( <browser> -- )
|
: browse ( <browser> -- )
|
||||||
#! Display a Smalltalk like browser for exploring/modifying words.
|
#! Display a Smalltalk like browser for exploring/modifying words.
|
||||||
[
|
[
|
||||||
|
@ -216,12 +226,19 @@ USE: listener
|
||||||
"vocabs" get
|
"vocabs" get
|
||||||
"words" get
|
"words" get
|
||||||
"eval" get dup [ "vocabs" get swap eval-string ] [ drop ] ifte
|
"eval" get dup [ "vocabs" get swap eval-string ] [ drop ] ifte
|
||||||
|
[
|
||||||
|
"vocabs" get "words" get browser-url forward-to-url
|
||||||
|
] show
|
||||||
] bind <browser>
|
] bind <browser>
|
||||||
] forever ;
|
] forever ;
|
||||||
|
|
||||||
: browser-responder ( allow-edit? -- )
|
: browser-responder ( allow-edit? -- )
|
||||||
#! Start the Smalltalk-like browser.
|
#! Start the Smalltalk-like browser.
|
||||||
"browser" f <browser> browse ;
|
"query" get dup [
|
||||||
|
dup >r "vocab" swap assoc r> "word" swap assoc
|
||||||
|
] [
|
||||||
|
drop "browser" f
|
||||||
|
] ifte <browser> browse ;
|
||||||
|
|
||||||
"browser" [ f browser-responder ] install-cont-responder
|
"browser" [ f browser-responder ] install-cont-responder
|
||||||
! "browser-edit" [ t browser-responder ] install-cont-responder
|
! "browser-edit" [ t browser-responder ] install-cont-responder
|
||||||
|
|
|
@ -39,7 +39,7 @@ USE: logging
|
||||||
USE: url-encoding
|
USE: url-encoding
|
||||||
USE: unparser
|
USE: unparser
|
||||||
USE: hashtables
|
USE: hashtables
|
||||||
|
USE: parser
|
||||||
USE: prettyprint
|
USE: prettyprint
|
||||||
USE: inspector
|
USE: inspector
|
||||||
|
|
||||||
|
@ -58,7 +58,7 @@ USE: inspector
|
||||||
|
|
||||||
: get-random-id ( -- id )
|
: get-random-id ( -- id )
|
||||||
#! Generate a random id to use for continuation URL's
|
#! Generate a random id to use for continuation URL's
|
||||||
[ 16 [ random-digit unparse , ] times ] make-string ;
|
[ 32 [ random-digit unparse , ] times ] make-string str>number 36 >base ;
|
||||||
|
|
||||||
: continuation-table ( -- <namespace> )
|
: continuation-table ( -- <namespace> )
|
||||||
#! Return the global table of continuations
|
#! Return the global table of continuations
|
||||||
|
@ -127,6 +127,11 @@ USE: inspector
|
||||||
#! Get the continuation item associated with the id.
|
#! Get the continuation item associated with the id.
|
||||||
continuation-table [ get ] bind ;
|
continuation-table [ get ] bind ;
|
||||||
|
|
||||||
|
: id>url ( id -- string )
|
||||||
|
#! Convert the continuation id to an URL suitable for
|
||||||
|
#! embedding in an HREF or other HTML.
|
||||||
|
url-encode "?id=" swap cat2 ;
|
||||||
|
|
||||||
DEFER: show
|
DEFER: show
|
||||||
|
|
||||||
: expired-page-handler ( alist -- )
|
: expired-page-handler ( alist -- )
|
||||||
|
@ -195,6 +200,15 @@ DEFER: show
|
||||||
#! stream. Return the string on exit.
|
#! stream. Return the string on exit.
|
||||||
1024 <string-output> dup >r swap with-stream r> stream>str ;
|
1024 <string-output> dup >r swap with-stream r> stream>str ;
|
||||||
|
|
||||||
|
: forward-to-url ( url -- )
|
||||||
|
#! When executed inside a 'show' call, this will force a
|
||||||
|
#! HTTP 302 to occur to instruct the browser to forward to
|
||||||
|
#! the request URL.
|
||||||
|
[
|
||||||
|
"HTTP/1.1 302 Document Moved\nLocation: " , ,
|
||||||
|
"\nContent-Length: 0\nContent-Type: text/plan\n\n" ,
|
||||||
|
] make-string call-exit-continuation ;
|
||||||
|
|
||||||
: redirect-to-here ( -- )
|
: redirect-to-here ( -- )
|
||||||
#! Force a redirect to the client browser so that the browser
|
#! Force a redirect to the client browser so that the browser
|
||||||
#! goes to the current point in the code. This forces an URL
|
#! goes to the current point in the code. This forces an URL
|
||||||
|
@ -208,7 +222,7 @@ DEFER: show
|
||||||
] [
|
] [
|
||||||
[
|
[
|
||||||
t swap register-continuation
|
t swap register-continuation
|
||||||
[ "HTTP/1.1 302 Document Moved\nLocation: " , , "\n" ,
|
[ "HTTP/1.1 302 Document Moved\nLocation: " , id>url , "\n" ,
|
||||||
"Content-Length: 0\nContent-Type: text/plain\n\n" , ] make-string
|
"Content-Length: 0\nContent-Type: text/plain\n\n" , ] make-string
|
||||||
call-exit-continuation
|
call-exit-continuation
|
||||||
] callcc1 drop
|
] callcc1 drop
|
||||||
|
@ -226,7 +240,7 @@ DEFER: show
|
||||||
store-callback-cc
|
store-callback-cc
|
||||||
redirect-enabled? [ redirect-to-here ] when
|
redirect-enabled? [ redirect-to-here ] when
|
||||||
[
|
[
|
||||||
t swap register-continuation swap
|
t swap register-continuation id>url swap
|
||||||
[ serving-html ] car swons with-string-stream
|
[ serving-html ] car swons with-string-stream
|
||||||
call-exit-continuation
|
call-exit-continuation
|
||||||
] callcc1
|
] callcc1
|
||||||
|
@ -235,6 +249,8 @@ DEFER: show
|
||||||
|
|
||||||
: cont-get-responder ( id-or-f -- )
|
: cont-get-responder ( id-or-f -- )
|
||||||
#! httpd responder that retrieves a continuation and calls it.
|
#! httpd responder that retrieves a continuation and calls it.
|
||||||
|
drop
|
||||||
|
"id" "query" get assoc
|
||||||
dup f-or-"" [
|
dup f-or-"" [
|
||||||
#! No continuation id given
|
#! No continuation id given
|
||||||
drop "root-continuation" get dup [
|
drop "root-continuation" get dup [
|
||||||
|
@ -255,7 +271,9 @@ DEFER: show
|
||||||
#! id and calls it with the POST data as a hashtable on the top
|
#! id and calls it with the POST data as a hashtable on the top
|
||||||
#! of the stack.
|
#! of the stack.
|
||||||
[
|
[
|
||||||
"response" get alist>hash swap resume-continuation
|
drop
|
||||||
|
"response" get alist>hash
|
||||||
|
"id" "query" get assoc resume-continuation
|
||||||
] with-exit-continuation
|
] with-exit-continuation
|
||||||
print drop ;
|
print drop ;
|
||||||
|
|
||||||
|
@ -271,7 +289,7 @@ DEFER: show
|
||||||
#! back to the most recent 'show' call (via the callback-cc).
|
#! back to the most recent 'show' call (via the callback-cc).
|
||||||
#! The text of the link will be the 'text' argument on the
|
#! The text of the link will be the 'text' argument on the
|
||||||
#! stack.
|
#! stack.
|
||||||
<a href= callback-quot t swap register-continuation a> write </a> ;
|
<a href= callback-quot t swap register-continuation id>url a> write </a> ;
|
||||||
|
|
||||||
: with-new-session ( quot -- )
|
: with-new-session ( quot -- )
|
||||||
#! Each cont-responder is bound inside their own
|
#! Each cont-responder is bound inside their own
|
||||||
|
|
|
@ -39,7 +39,7 @@
|
||||||
! eg.
|
! eg.
|
||||||
! <cont-test-state> [ test-cont-responder ] test-cont-function
|
! <cont-test-state> [ test-cont-responder ] test-cont-function
|
||||||
! => HTTP/1.1 302 Document Moved
|
! => HTTP/1.1 302 Document Moved
|
||||||
! Location: 8506502852110820
|
! Location: ?id=8506502852110820
|
||||||
! Content-Length: 0
|
! Content-Length: 0
|
||||||
! Content-Type: text/plain
|
! Content-Type: text/plain
|
||||||
!
|
!
|
||||||
|
@ -48,12 +48,12 @@
|
||||||
! Content-Type: text/html
|
! Content-Type: text/html
|
||||||
!
|
!
|
||||||
! <html><head><title>Page one</title></head><body>
|
! <html><head><title>Page one</title></head><body>
|
||||||
! <h1>Page one</h1><a href='5431597582800278'>Next</a>
|
! <h1>Page one</h1><a href='?id=5431597582800278'>Next</a>
|
||||||
! </body></html>
|
! </body></html>
|
||||||
!
|
!
|
||||||
! "5431597582800278" f test-cont-click
|
! "5431597582800278" f test-cont-click
|
||||||
! => HTTP/1.1 302 Document Moved
|
! => HTTP/1.1 302 Document Moved
|
||||||
! Location: 7944183606904129
|
! Location: ?id=7944183606904129
|
||||||
! Content-Length: 0
|
! Content-Length: 0
|
||||||
! Content-Type: text/plain
|
! Content-Type: text/plain
|
||||||
!
|
!
|
||||||
|
@ -63,14 +63,14 @@
|
||||||
!
|
!
|
||||||
! <html><head><title>Enter your name</title></head>
|
! <html><head><title>Enter your name</title></head>
|
||||||
! <body><h1>Enter your name</h1>
|
! <body><h1>Enter your name</h1>
|
||||||
! <form method='post'action='8503790719833723'>
|
! <form method='post' action='?id=8503790719833723'>
|
||||||
! Name: <input type='text' name='name'size='20'>
|
! Name: <input type='text' name='name'size='20'>
|
||||||
! <input type='submit' value='Ok'>
|
! <input type='submit' value='Ok'>
|
||||||
! </form></body></html>
|
! </form></body></html>
|
||||||
!
|
!
|
||||||
! "8503790719833723" [ [ "name" | "Chris" ] ] alist>hash test-cont-click
|
! "8503790719833723" [ [[ "name" "Chris" ]] ] alist>hash test-cont-click
|
||||||
! => HTTP/1.1 302 Document Moved
|
! => HTTP/1.1 302 Document Moved
|
||||||
! Location: 8879727708050260
|
! Location: ?id=8879727708050260
|
||||||
! Content-Length: 0
|
! Content-Length: 0
|
||||||
! Content-Type: text/plain
|
! Content-Type: text/plain
|
||||||
!
|
!
|
||||||
|
@ -80,7 +80,7 @@
|
||||||
!
|
!
|
||||||
! <html><head><title>Hello Chris</title></head>
|
! <html><head><title>Hello Chris</title></head>
|
||||||
! <body><h1>Hello Chris</h1>
|
! <body><h1>Hello Chris</h1>
|
||||||
! <a href='0937854264503953'>Next</a>
|
! <a href='?id=0937854264503953'>Next</a>
|
||||||
! </body></html>
|
! </body></html>
|
||||||
!
|
!
|
||||||
! etc.
|
! etc.
|
||||||
|
|
|
@ -47,7 +47,7 @@ USE: lists
|
||||||
[
|
[
|
||||||
"js/liveUpdater.js" get-live-updater-js write
|
"js/liveUpdater.js" get-live-updater-js write
|
||||||
] show
|
] show
|
||||||
] register-continuation ;
|
] register-continuation id>url ;
|
||||||
|
|
||||||
: include-live-updater-js ( -- )
|
: include-live-updater-js ( -- )
|
||||||
#! Write out the HTML script to include the live updater
|
#! Write out the HTML script to include the live updater
|
||||||
|
@ -96,7 +96,7 @@ USE: lists
|
||||||
"document.getElementById('" write
|
"document.getElementById('" write
|
||||||
write
|
write
|
||||||
"').onclick=liveUpdaterUri('" write
|
"').onclick=liveUpdaterUri('" write
|
||||||
register-live-anchor-quot write
|
register-live-anchor-quot id>url write
|
||||||
"');" write
|
"');" write
|
||||||
</script> ;
|
</script> ;
|
||||||
|
|
||||||
|
@ -153,7 +153,7 @@ USE: lists
|
||||||
"liveSearch('" write
|
"liveSearch('" write
|
||||||
write
|
write
|
||||||
"', '" write
|
"', '" write
|
||||||
register-live-search-quot write
|
register-live-search-quot id>url write
|
||||||
"');" write
|
"');" write
|
||||||
</script> ;
|
</script> ;
|
||||||
|
|
||||||
|
|
|
@ -107,7 +107,7 @@ USE: kernel
|
||||||
|
|
||||||
: todo-stylesheet-url ( -- url )
|
: todo-stylesheet-url ( -- url )
|
||||||
#! Generate an URL for the stylesheet.
|
#! Generate an URL for the stylesheet.
|
||||||
t [ [ drop todo-stylesheet write ] show ] register-continuation ;
|
t [ [ drop todo-stylesheet write ] show ] register-continuation id>url ;
|
||||||
|
|
||||||
: include-todo-stylesheet ( -- )
|
: include-todo-stylesheet ( -- )
|
||||||
#! Generate HTML to include the todo stylesheet
|
#! Generate HTML to include the todo stylesheet
|
||||||
|
|
|
@ -331,10 +331,10 @@ sequence the page shows. Any Factor code can be called and the
|
||||||
continuation based system will sequentially display each page. The
|
continuation based system will sequentially display each page. The
|
||||||
back button, browser window cloning, etc will all continue to work.
|
back button, browser window cloning, etc will all continue to work.
|
||||||
|
|
||||||
You'll notice the URL's in the browser have a number at the end of
|
You'll notice the URL's in the browser have an 'id' query parameter with
|
||||||
them. This is the 'continuation identifier' which is like a session id
|
a number as its value. This is the 'continuation identifier' which is
|
||||||
except that it identifies not just the data you have stored but your
|
like a session id except that it identifies not just the data you have
|
||||||
location within the responder as well.
|
stored but your location within the responder as well.
|
||||||
|
|
||||||
Forms and POST data
|
Forms and POST data
|
||||||
===================
|
===================
|
||||||
|
@ -603,7 +603,7 @@ calls the code we want to test and call the 'test-cont-function' word:
|
||||||
<cont-test-state> [ subroutine-example1 ] test-cont-function
|
<cont-test-state> [ subroutine-example1 ] test-cont-function
|
||||||
=>
|
=>
|
||||||
HTTP/1.1 302 Document Moved
|
HTTP/1.1 302 Document Moved
|
||||||
Location: 8209741119458310
|
Location: ?id=8209741119458310
|
||||||
Content-Length: 0
|
Content-Length: 0
|
||||||
Content-Type: text/plain
|
Content-Type: text/plain
|
||||||
|
|
||||||
|
@ -628,9 +628,9 @@ state on the stack:
|
||||||
Content-Type: text/html
|
Content-Type: text/html
|
||||||
<html><head><title>Subroutine Example 1</title></head>
|
<html><head><title>Subroutine Example 1</title></head>
|
||||||
<body><p>Please select:
|
<body><p>Please select:
|
||||||
<ol><li><a href='7687398605200513'>Flow1</a></li>
|
<ol><li><a href='?id=7687398605200513'>Flow1</a></li>
|
||||||
<li><a href='7856272029924613'>Flow2</a></li>
|
<li><a href='?id=7856272029924613'>Flow2</a></li>
|
||||||
<li><a href='4909116160485714'>Flow3</a></li>
|
<li><a href='?id=4909116160485714'>Flow3</a></li>
|
||||||
</ol>
|
</ol>
|
||||||
</p>
|
</p>
|
||||||
</body>
|
</body>
|
||||||
|
@ -645,7 +645,7 @@ written previously:
|
||||||
<cont-test-state> [ post-example1 ] test-cont-function
|
<cont-test-state> [ post-example1 ] test-cont-function
|
||||||
=>
|
=>
|
||||||
HTTP/1.1 302 Document Moved
|
HTTP/1.1 302 Document Moved
|
||||||
Location: 5829759941409535
|
Location: ?id=5829759941409535
|
||||||
Content-Length: 0
|
Content-Length: 0
|
||||||
Content-Type: text/plain
|
Content-Type: text/plain
|
||||||
|
|
||||||
|
@ -658,7 +658,7 @@ Again we skip past the forward:
|
||||||
|
|
||||||
<html><head><title>Please enter your name</title></head>
|
<html><head><title>Please enter your name</title></head>
|
||||||
<body>
|
<body>
|
||||||
<form action='5456539333180428' method='post'>
|
<form action='?id=5456539333180428' method='post'>
|
||||||
<p>Please enter your name:
|
<p>Please enter your name:
|
||||||
<input type='text'size='20'name='username'>
|
<input type='text'size='20'name='username'>
|
||||||
<input type='submit'value='Ok'>
|
<input type='submit'value='Ok'>
|
||||||
|
|
|
@ -28,10 +28,6 @@
|
||||||
! Not all functions have been wrapped yet. Only those directly involving
|
! Not all functions have been wrapped yet. Only those directly involving
|
||||||
! executing SQL calls and obtaining results.
|
! executing SQL calls and obtaining results.
|
||||||
!
|
!
|
||||||
! TODO: Do I have to free stuctures like <sqlite3> and <char*>, etc
|
|
||||||
! or do they get freed on garbage collection?
|
|
||||||
! How do I do pointers to pointers? Use the 'indirect' trick?
|
|
||||||
!
|
|
||||||
IN: sqlite
|
IN: sqlite
|
||||||
USE: kernel
|
USE: kernel
|
||||||
USE: alien
|
USE: alien
|
||||||
|
@ -98,77 +94,58 @@ END-STRUCT
|
||||||
: SQLITE_TRANSIENT -1 ;
|
: SQLITE_TRANSIENT -1 ;
|
||||||
|
|
||||||
: sqlite3_open ( filename sqlite3-indirect -- result )
|
: sqlite3_open ( filename sqlite3-indirect -- result )
|
||||||
"int" "sqlite" "sqlite3_open" [ "char*" "sqlite3-indirect*" ] alien-invoke ;
|
"int" "sqlite" "sqlite3_open" [ "char*" "sqlite3-indirect*" ] alien-invoke ; compiled
|
||||||
|
|
||||||
: sqlite3_close ( db -- )
|
: sqlite3_close ( db -- )
|
||||||
"int" "sqlite" "sqlite3_close" [ "sqlite3*" ] alien-invoke ;
|
"int" "sqlite" "sqlite3_close" [ "sqlite3*" ] alien-invoke ; compiled
|
||||||
|
|
||||||
: sqlite3_prepare ( db sql sql-len sqlite3-stmt-indirect tail -- result )
|
: sqlite3_prepare ( db sql sql-len sqlite3-stmt-indirect tail -- result )
|
||||||
"int" "sqlite" "sqlite3_prepare" [ "sqlite3*" "char*" "int" "sqlite3-stmt-indirect*" "char*-indirect*" ] alien-invoke ;
|
"int" "sqlite" "sqlite3_prepare" [ "sqlite3*" "char*" "int" "sqlite3-stmt-indirect*" "char*-indirect*" ] alien-invoke ; compiled
|
||||||
|
|
||||||
: sqlite3_finalize ( stmt -- result )
|
: sqlite3_finalize ( stmt -- result )
|
||||||
"int" "sqlite" "sqlite3_finalize" [ "sqlite3-stmt*" ] alien-invoke ;
|
"int" "sqlite" "sqlite3_finalize" [ "sqlite3-stmt*" ] alien-invoke ; compiled
|
||||||
|
|
||||||
: sqlite3_reset ( stmt -- result )
|
: sqlite3_reset ( stmt -- result )
|
||||||
"int" "sqlite" "sqlite3_reset" [ "sqlite3-stmt*" ] alien-invoke ;
|
"int" "sqlite" "sqlite3_reset" [ "sqlite3-stmt*" ] alien-invoke ; compiled
|
||||||
|
|
||||||
: sqlite3_step ( stmt -- result )
|
: sqlite3_step ( stmt -- result )
|
||||||
"int" "sqlite" "sqlite3_step" [ "sqlite3-stmt*" ] alien-invoke ;
|
"int" "sqlite" "sqlite3_step" [ "sqlite3-stmt*" ] alien-invoke ; compiled
|
||||||
|
|
||||||
: sqlite3_bind_blob ( stmt index pointer len destructor -- result )
|
: sqlite3_bind_blob ( stmt index pointer len destructor -- result )
|
||||||
"int" "sqlite" "sqlite3_bind_blob" [ "sqlite3-stmt*" "int" "void*" "int" "int" ] alien-invoke ;
|
"int" "sqlite" "sqlite3_bind_blob" [ "sqlite3-stmt*" "int" "void*" "int" "int" ] alien-invoke ; compiled
|
||||||
|
|
||||||
: sqlite3_bind_int ( stmt index int -- result )
|
: sqlite3_bind_int ( stmt index int -- result )
|
||||||
"int" "sqlite" "sqlite3_bind_int" [ "sqlite3-stmt*" "int" "int" ] alien-invoke ;
|
"int" "sqlite" "sqlite3_bind_int" [ "sqlite3-stmt*" "int" "int" ] alien-invoke ; compiled
|
||||||
|
|
||||||
: sqlite3_bind_null ( stmt index -- result )
|
: sqlite3_bind_null ( stmt index -- result )
|
||||||
"int" "sqlite" "sqlite3_bind_null" [ "sqlite3-stmt*" "int" ] alien-invoke ;
|
"int" "sqlite" "sqlite3_bind_null" [ "sqlite3-stmt*" "int" ] alien-invoke ; compiled
|
||||||
|
|
||||||
: sqlite3_bind_text ( stmt index text len destructor -- result )
|
: sqlite3_bind_text ( stmt index text len destructor -- result )
|
||||||
"int" "sqlite" "sqlite3_bind_text" [ "sqlite3-stmt*" "int" "char*" "int" "int" ] alien-invoke ;
|
"int" "sqlite" "sqlite3_bind_text" [ "sqlite3-stmt*" "int" "char*" "int" "int" ] alien-invoke ; compiled
|
||||||
|
|
||||||
: sqlite3_column_count ( stmt -- count )
|
: sqlite3_column_count ( stmt -- count )
|
||||||
"int" "sqlite" "sqlite3_column_count" [ "sqlite3-stmt*" ] alien-invoke ;
|
"int" "sqlite" "sqlite3_column_count" [ "sqlite3-stmt*" ] alien-invoke ; compiled
|
||||||
|
|
||||||
: sqlite3_column_blob ( stmt col -- void* )
|
: sqlite3_column_blob ( stmt col -- void* )
|
||||||
"void*" "sqlite" "sqlite3_column_blob" [ "sqlite3-stmt*" "int" ] alien-invoke ;
|
"void*" "sqlite" "sqlite3_column_blob" [ "sqlite3-stmt*" "int" ] alien-invoke ; compiled
|
||||||
|
|
||||||
: sqlite3_column_bytes ( stmt col -- int )
|
: sqlite3_column_bytes ( stmt col -- int )
|
||||||
"int" "sqlite" "sqlite3_column_bytes" [ "sqlite3-stmt*" "int" ] alien-invoke ;
|
"int" "sqlite" "sqlite3_column_bytes" [ "sqlite3-stmt*" "int" ] alien-invoke ; compiled
|
||||||
|
|
||||||
: sqlite3_column_decltype ( stmt col -- string )
|
: sqlite3_column_decltype ( stmt col -- string )
|
||||||
"char*" "sqlite" "sqlite3_column_decltype" [ "sqlite3-stmt*" "int" ] alien-invoke ;
|
"char*" "sqlite" "sqlite3_column_decltype" [ "sqlite3-stmt*" "int" ] alien-invoke ; compiled
|
||||||
|
|
||||||
: sqlite3_column_int ( stmt col -- int )
|
: sqlite3_column_int ( stmt col -- int )
|
||||||
"int" "sqlite" "sqlite3_column_int" [ "sqlite3-stmt*" "int" ] alien-invoke ;
|
"int" "sqlite" "sqlite3_column_int" [ "sqlite3-stmt*" "int" ] alien-invoke ; compiled
|
||||||
|
|
||||||
: sqlite3_column_name ( stmt col -- string )
|
: sqlite3_column_name ( stmt col -- string )
|
||||||
"char*" "sqlite" "sqlite3_column_name" [ "sqlite3-stmt*" "int" ] alien-invoke ;
|
"char*" "sqlite" "sqlite3_column_name" [ "sqlite3-stmt*" "int" ] alien-invoke ; compiled
|
||||||
|
|
||||||
: sqlite3_column_text ( stmt col -- string )
|
: sqlite3_column_text ( stmt col -- string )
|
||||||
"char*" "sqlite" "sqlite3_column_text" [ "sqlite3-stmt*" "int" ] alien-invoke ;
|
"char*" "sqlite" "sqlite3_column_text" [ "sqlite3-stmt*" "int" ] alien-invoke ; compiled
|
||||||
|
|
||||||
: sqlite3_column_type ( stmt col -- int )
|
: sqlite3_column_type ( stmt col -- int )
|
||||||
"int" "sqlite" "sqlite3_column_type" [ "sqlite3-stmt*" "int" ] alien-invoke ;
|
"int" "sqlite" "sqlite3_column_type" [ "sqlite3-stmt*" "int" ] alien-invoke ; compiled
|
||||||
|
|
||||||
\ sqlite3_open compile
|
|
||||||
\ sqlite3_close compile
|
|
||||||
\ sqlite3_prepare compile
|
|
||||||
\ sqlite3_finalize compile
|
|
||||||
\ sqlite3_reset compile
|
|
||||||
\ sqlite3_bind_blob compile
|
|
||||||
\ sqlite3_bind_int compile
|
|
||||||
\ sqlite3_bind_null compile
|
|
||||||
\ sqlite3_bind_text compile
|
|
||||||
\ sqlite3_step compile
|
|
||||||
\ sqlite3_column_count compile
|
|
||||||
\ sqlite3_column_blob compile
|
|
||||||
\ sqlite3_column_bytes compile
|
|
||||||
\ sqlite3_column_decltype compile
|
|
||||||
\ sqlite3_column_int compile
|
|
||||||
\ sqlite3_column_name compile
|
|
||||||
\ sqlite3_column_text compile
|
|
||||||
\ sqlite3_column_type compile
|
|
||||||
|
|
||||||
! High level sqlite routines
|
! High level sqlite routines
|
||||||
: sqlite-check-result ( result -- )
|
: sqlite-check-result ( result -- )
|
||||||
|
@ -220,26 +197,32 @@ END-STRUCT
|
||||||
#! from zero, as a string.
|
#! from zero, as a string.
|
||||||
sqlite3_column_text ;
|
sqlite3_column_text ;
|
||||||
|
|
||||||
: (sqlite-each)
|
: step-complete? ( step-result -- bool )
|
||||||
"statement" get sqlite3_step dup SQLITE_ROW = [
|
#! Return true if the result of a sqlite3_step is
|
||||||
drop
|
#! such that the iteration has completed (ie. it is
|
||||||
"statement" get "quot" get call (sqlite-each)
|
#! SQLITE_DONE). Throw an error if an error occurs.
|
||||||
|
dup SQLITE_ROW = [
|
||||||
|
drop f
|
||||||
] [
|
] [
|
||||||
dup SQLITE_DONE = [
|
dup SQLITE_DONE = [
|
||||||
drop
|
drop t
|
||||||
] [
|
] [
|
||||||
sqlite-check-result
|
sqlite-check-result
|
||||||
] ifte
|
] ifte
|
||||||
] ifte ;
|
] ifte ;
|
||||||
|
|
||||||
: sqlite-each ( statement quot -- )
|
: sqlite-each ( statement quot -- )
|
||||||
#! Excecute the SQL statement, and call the quotation for
|
#! Execute the SQL statement, and call the quotation for
|
||||||
#! each row returned from executing the statement with the
|
#! each row returned from executing the statement with the
|
||||||
#! statement on the top of the stack.
|
#! statement on the top of the stack.
|
||||||
#! TODO: Implement without named parameters
|
over sqlite3_step step-complete? [
|
||||||
<namespace> [
|
2drop
|
||||||
"quot" set
|
] [
|
||||||
"statement" set
|
2dup 2slip sqlite-each
|
||||||
(sqlite-each)
|
] ifte ;
|
||||||
] bind ;
|
|
||||||
|
|
||||||
|
! For comparison, here is the linrec implementation of sqlite-each
|
||||||
|
! [ drop sqlite3_step step-complete? ]
|
||||||
|
! [ 2drop ]
|
||||||
|
! [ 2dup 2slip ]
|
||||||
|
! [ ] linrec ;
|
|
@ -47,4 +47,9 @@ USE: prettyprint
|
||||||
sqlite-finalize
|
sqlite-finalize
|
||||||
sqlite-close ;
|
sqlite-close ;
|
||||||
|
|
||||||
|
: run-test2 ( -- )
|
||||||
|
"test.db" sqlite-open
|
||||||
|
dup "select * from test" sqlite-prepare
|
||||||
|
dup [ show-people ] ;
|
||||||
|
|
||||||
run-test
|
run-test
|
Loading…
Reference in New Issue