| 
									
										
										
										
											2009-04-14 20:54:10 -04:00
										 |  |  | ! Copyright (C) 2008, 2009 Alex Chapman | 
					
						
							| 
									
										
										
										
											2008-09-30 20:38:54 -04:00
										 |  |  | ! See http://factorcode.org/license.txt for BSD license. | 
					
						
							| 
									
										
										
										
											2009-04-14 20:54:10 -04:00
										 |  |  | USING: accessors arrays assocs continuations debugger hashtables http | 
					
						
							|  |  |  | http.client io io.encodings.string io.encodings.utf8 json.reader | 
					
						
							| 
									
										
										
										
											2009-11-05 16:34:31 -05:00
										 |  |  | json.writer kernel locals make math math.parser namespaces sequences | 
					
						
							|  |  |  | strings urls urls.encoding vectors ;
 | 
					
						
							| 
									
										
										
										
											2008-09-30 20:38:54 -04:00
										 |  |  | IN: couchdb | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-11-01 00:36:56 -04:00
										 |  |  | ! NOTE: This code only works with the latest couchdb (0.9.*), because old | 
					
						
							|  |  |  | ! versions didn't provide the /_uuids feature which this code relies on when | 
					
						
							|  |  |  | ! creating new documents. | 
					
						
							| 
									
										
										
										
											2008-09-30 20:38:54 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-11-01 00:36:56 -04:00
										 |  |  | SYMBOL: couch | 
					
						
							|  |  |  | : with-couch ( db quot -- )
 | 
					
						
							|  |  |  |     couch swap with-variable ; inline
 | 
					
						
							| 
									
										
										
										
											2008-09-30 20:38:54 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-11-01 00:36:56 -04:00
										 |  |  | ! errors | 
					
						
							| 
									
										
										
										
											2008-09-30 20:38:54 -04:00
										 |  |  | TUPLE: couchdb-error { data assoc } ;
 | 
					
						
							|  |  |  | C: <couchdb-error> couchdb-error | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | M: couchdb-error error. ( error -- )
 | 
					
						
							|  |  |  |     "CouchDB Error: " write data>> | 
					
						
							|  |  |  |     "error" over at [ print ] when*
 | 
					
						
							|  |  |  |     "reason" swap at [ print ] when* ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-11-01 00:36:56 -04:00
										 |  |  | PREDICATE: file-exists-error < couchdb-error | 
					
						
							|  |  |  |     data>> "error" swap at "file_exists" = ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ! http tools | 
					
						
							|  |  |  | : couch-http-request ( request -- data )
 | 
					
						
							|  |  |  |     [ http-request ] [ | 
					
						
							|  |  |  |         dup download-failed? [ | 
					
						
							| 
									
										
										
										
											2009-04-14 20:54:10 -04:00
										 |  |  |             response>> body>> json> <couchdb-error> throw
 | 
					
						
							| 
									
										
										
										
											2008-11-01 00:36:56 -04:00
										 |  |  |         ] [ | 
					
						
							|  |  |  |             rethrow
 | 
					
						
							|  |  |  |         ] if
 | 
					
						
							|  |  |  |     ] recover nip ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : couch-request ( request -- assoc )
 | 
					
						
							|  |  |  |     couch-http-request json> ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : couch-get ( url -- assoc )
 | 
					
						
							|  |  |  |     <get-request> couch-request ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : couch-put ( post-data url -- assoc )
 | 
					
						
							|  |  |  |     <put-request> couch-request ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : couch-post ( post-data url -- assoc )
 | 
					
						
							|  |  |  |     <post-request> couch-request ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : couch-delete ( url -- assoc )
 | 
					
						
							| 
									
										
										
										
											2009-04-14 20:54:10 -04:00
										 |  |  |     <delete-request> couch-request ;
 | 
					
						
							| 
									
										
										
										
											2008-11-01 00:36:56 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | : response-ok ( assoc -- assoc )
 | 
					
						
							|  |  |  |     "ok" over delete-at* and t assert= ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : response-ok* ( assoc -- )
 | 
					
						
							|  |  |  |     response-ok drop ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ! server | 
					
						
							|  |  |  | TUPLE: server { host string } { port integer } { uuids vector } { uuids-to-cache integer } ;
 | 
					
						
							| 
									
										
										
										
											2008-09-30 20:38:54 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-13 20:00:09 -04:00
										 |  |  | : default-couch-host ( -- host ) "localhost" ; inline
 | 
					
						
							|  |  |  | : default-couch-port ( -- port ) 5984 ; inline
 | 
					
						
							|  |  |  | : default-uuids-to-cache ( -- n ) 100 ; inline
 | 
					
						
							| 
									
										
										
										
											2008-09-30 20:38:54 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-11-01 00:36:56 -04:00
										 |  |  | : <server> ( host port -- server )
 | 
					
						
							|  |  |  |     V{ } clone default-uuids-to-cache server boa ;
 | 
					
						
							| 
									
										
										
										
											2008-09-30 20:38:54 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-11-01 00:36:56 -04:00
										 |  |  | : <default-server> ( -- server )
 | 
					
						
							|  |  |  |     default-couch-host default-couch-port <server> ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : (server-url) ( server -- )
 | 
					
						
							|  |  |  |     "http://" % [ host>> % ] [ CHAR: : , port>> number>string % ] bi CHAR: / , ; inline
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : server-url ( server -- url )
 | 
					
						
							|  |  |  |     [ (server-url) ] "" make ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : all-dbs ( server -- dbs )
 | 
					
						
							|  |  |  |     server-url "_all_dbs" append couch-get ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : uuids-url ( server -- url )
 | 
					
						
							|  |  |  |     [ dup server-url % "_uuids?count=" % uuids-to-cache>> number>string % ] "" make ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-14 20:54:10 -04:00
										 |  |  | : uuids-get ( server -- uuids )
 | 
					
						
							|  |  |  |      uuids-url couch-get "uuids" swap at >vector ;
 | 
					
						
							| 
									
										
										
										
											2008-11-01 00:36:56 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | : get-uuids ( server -- server )
 | 
					
						
							| 
									
										
										
										
											2009-04-14 20:54:10 -04:00
										 |  |  |     dup uuids-get [ nip ] curry change-uuids ;
 | 
					
						
							| 
									
										
										
										
											2008-11-01 00:36:56 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | : ensure-uuids ( server -- server )
 | 
					
						
							|  |  |  |     dup uuids>> empty? [ get-uuids ] when ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : next-uuid ( server -- uuid )
 | 
					
						
							|  |  |  |     ensure-uuids uuids>> pop ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ! db  | 
					
						
							|  |  |  | TUPLE: db { server server } { name string } ;
 | 
					
						
							|  |  |  | C: <db> db | 
					
						
							| 
									
										
										
										
											2008-09-30 20:38:54 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-11-01 00:36:56 -04:00
										 |  |  | : (db-url) ( db -- )
 | 
					
						
							|  |  |  |     [ server>> server-url % ] [ name>> % ] bi CHAR: / , ; inline
 | 
					
						
							| 
									
										
										
										
											2008-09-30 20:38:54 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-11-01 00:36:56 -04:00
										 |  |  | : db-url ( db -- url )
 | 
					
						
							|  |  |  |     [ (db-url) ] "" make ;
 | 
					
						
							| 
									
										
										
										
											2008-09-30 20:38:54 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-11-01 00:36:56 -04:00
										 |  |  | : create-db ( db -- )
 | 
					
						
							|  |  |  |     f swap db-url couch-put response-ok* ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : ensure-db ( db -- )
 | 
					
						
							|  |  |  |     [ create-db ] [ | 
					
						
							|  |  |  |         dup file-exists-error? [ 2drop ] [ rethrow ] if
 | 
					
						
							|  |  |  |     ] recover ;
 | 
					
						
							| 
									
										
										
										
											2008-10-13 02:01:29 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | : delete-db ( db -- )
 | 
					
						
							| 
									
										
										
										
											2008-11-01 00:36:56 -04:00
										 |  |  |     db-url couch-delete drop ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : db-info ( db -- info )
 | 
					
						
							|  |  |  |     db-url couch-get ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : compact-db ( db -- )
 | 
					
						
							|  |  |  |     f swap db-url "_compact" append couch-post response-ok* ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : all-docs ( db -- docs )
 | 
					
						
							|  |  |  |     ! TODO: queries. Maybe pass in a hashtable with options | 
					
						
							|  |  |  |     db-url "_all_docs" append couch-get ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : <json-post-data> ( assoc -- post-data )
 | 
					
						
							| 
									
										
										
										
											2009-04-14 20:54:10 -04:00
										 |  |  |     >json utf8 encode "application/json" <post-data> swap >>data ;
 | 
					
						
							| 
									
										
										
										
											2008-11-01 00:36:56 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | ! documents | 
					
						
							|  |  |  | : id> ( assoc -- id ) "_id" swap at ;  | 
					
						
							|  |  |  | : >id ( assoc id -- assoc ) "_id" pick set-at ;
 | 
					
						
							|  |  |  | : rev> ( assoc -- rev ) "_rev" swap at ;
 | 
					
						
							|  |  |  | : >rev ( assoc rev -- assoc ) "_rev" pick set-at ;
 | 
					
						
							| 
									
										
										
										
											2008-11-01 05:38:50 -04:00
										 |  |  | : attachments> ( assoc -- attachments ) "_attachments" swap at ;
 | 
					
						
							|  |  |  | : >attachments ( assoc attachments -- assoc ) "_attachments" pick set-at ;
 | 
					
						
							| 
									
										
										
										
											2008-11-01 00:36:56 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-05 16:34:31 -05:00
										 |  |  | :: copy-key ( to from to-key from-key -- )
 | 
					
						
							|  |  |  |     from-key from at
 | 
					
						
							|  |  |  |     to-key to set-at ;
 | 
					
						
							| 
									
										
										
										
											2008-11-01 00:36:56 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | : copy-id ( to from -- )
 | 
					
						
							|  |  |  |     "_id" "id" copy-key ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : copy-rev ( to from -- )
 | 
					
						
							|  |  |  |     "_rev" "rev" copy-key ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : id-url ( id -- url )
 | 
					
						
							| 
									
										
										
										
											2008-11-01 05:38:50 -04:00
										 |  |  |     couch get db-url swap url-encode-full append ;
 | 
					
						
							| 
									
										
										
										
											2008-11-01 00:36:56 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | : doc-url ( assoc -- url )
 | 
					
						
							|  |  |  |     id> id-url ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-11-01 05:38:50 -04:00
										 |  |  | : temp-view ( view -- results )
 | 
					
						
							|  |  |  |     <json-post-data> couch get db-url "_temp_view" append couch-post ;
 | 
					
						
							| 
									
										
										
										
											2008-11-01 00:36:56 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-11-01 05:38:50 -04:00
										 |  |  | : temp-view-map ( map -- results )
 | 
					
						
							|  |  |  |     "map" H{ } clone [ set-at ] keep temp-view ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : save-doc-as ( assoc id -- )
 | 
					
						
							|  |  |  |     [ dup <json-post-data> ] dip id-url couch-put response-ok | 
					
						
							| 
									
										
										
										
											2008-11-01 00:36:56 -04:00
										 |  |  |     [ copy-id ] [ copy-rev ] 2bi ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-11-01 05:38:50 -04:00
										 |  |  | : save-new-doc ( assoc -- )
 | 
					
						
							|  |  |  |     couch get server>> next-uuid save-doc-as ;
 | 
					
						
							| 
									
										
										
										
											2008-11-01 00:36:56 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-11-01 05:38:50 -04:00
										 |  |  | : save-doc ( assoc -- )
 | 
					
						
							|  |  |  |     dup id> [ save-doc-as ] [ save-new-doc ] if* ;  | 
					
						
							| 
									
										
										
										
											2008-11-01 00:36:56 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-11-01 05:38:50 -04:00
										 |  |  | : load-doc ( id -- assoc )
 | 
					
						
							| 
									
										
										
										
											2008-11-01 00:36:56 -04:00
										 |  |  |     id-url couch-get ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-11-01 05:38:50 -04:00
										 |  |  | : delete-doc ( assoc -- deletion-revision )
 | 
					
						
							| 
									
										
										
										
											2008-11-01 00:36:56 -04:00
										 |  |  |     [ | 
					
						
							|  |  |  |         [ doc-url % ] | 
					
						
							|  |  |  |         [ "?rev=" % "_rev" swap at % ] bi
 | 
					
						
							| 
									
										
										
										
											2008-11-01 05:38:50 -04:00
										 |  |  |     ] "" make couch-delete response-ok "rev" swap at  ;
 | 
					
						
							| 
									
										
										
										
											2008-11-01 00:36:56 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | : remove-keys ( assoc keys -- )
 | 
					
						
							|  |  |  |     swap [ delete-at ] curry each ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : remove-couch-info ( assoc -- )
 | 
					
						
							|  |  |  |     { "_id" "_rev" "_attachments" } remove-keys ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-11-01 05:38:50 -04:00
										 |  |  | ! : construct-attachment ( content-type data -- assoc ) | 
					
						
							|  |  |  | !     H{ } clone "name" pick set-at "content-type" pick set-at ; | 
					
						
							|  |  |  | ! 
 | 
					
						
							|  |  |  | ! : add-attachment ( assoc name attachment -- ) | 
					
						
							|  |  |  | !     pick attachments> [ H{ } clone ] unless*  | 
					
						
							|  |  |  | ! 
 | 
					
						
							|  |  |  | ! : attach ( assoc name content-type data -- ) | 
					
						
							|  |  |  | !     construct-attachment H{ } clone | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-11-01 00:36:56 -04:00
										 |  |  | ! TODO: | 
					
						
							| 
									
										
										
										
											2009-04-14 20:54:10 -04:00
										 |  |  | ! - startkey, limit, descending, etc. | 
					
						
							| 
									
										
										
										
											2008-11-01 00:36:56 -04:00
										 |  |  | ! - loading specific revisions | 
					
						
							|  |  |  | ! - views | 
					
						
							|  |  |  | ! - attachments | 
					
						
							|  |  |  | ! - bulk insert/update | 
					
						
							|  |  |  | ! - ...? |