CouchDB Library

Creating desktop or client-server database solutions?

Moderators: FourthWorld, heatherlaine, Klaus, kevinmiller, robinmiller

pink
Posts: 272
Joined: Wed Mar 12, 2014 6:18 pm

CouchDB Library

Post by pink » Mon Jul 27, 2015 9:48 pm

I have been working on a library for Apache CouchDB which I'm going to say is about 50% done.
Looking for users who are familiar with CouchDB who'd like to help test.
Also, this is really my first time sharing code with anyone other than people I work with, so any comments critiques or criticisms would be helpful for future projects I want to share. You can message me here, or email me at pink@mad.pink

The code is on Github here:
https://github.com/madpink/couchdb4live ... /daybed.lc

I'm calling this version: 0.0.23 July 27, 2015

This is a simple library that calls CouchDB's REST functions and then decodes them using EasyJSON.
EasyJSON is included in the code.

There are 4 main groups of functions:
Server Commands (50% implemented)
Document Commands (80% implemented)
Database Commands (60% implemented)
Design Document Commands (0%)

Long term to do plans:
A 5th group of functions is being worked on for creating a local store.
A stack called Daybed is in the works which will hopefully be a full Livecode replacement for Futon.

I've tested using versions 1.5.0. 1.6.0 and 1.6.1, nothing earlier has been tested.
I've tested with the following hosts: IrisCouch & SmileUpps

This library has not been tested on Cloudant or the beta of 2.0.0

Documentation is incomplete

Most of these functions take one or more these parameters:

pURL - the URL of the CouchDB installation, including "http://", the port numer and a trailing slash
For example: "http://192.168.23.42:5984/"
With username/password: "http://admin:trustno1@192.168.23.42:5984/"

pDB - the name of the database being accessed

pParams - an array with any OPTIONAL parameters, with the parameter as a key.
For example: to download documents when running the _all_docs function, and limit the list to only 10 records:
put true into tOptions["include_docs"]
put 10 into tOptions["limit"]
(then pass tOptions in the function)

pDocID - (used in GET functions) the "_id" value of the document you are downloading

pDoc - (used in PUT functions) an array with the data to be converted to JSON and uploaded to CouchDB.

When a specific revision number is required by CouchDB, two approaches can be used:
1. add it to the array being used for pParams, for example: put "2-95a8c0a9268e896dd9c46a1b2a6e9c80" into tOptions["rev"]
2. include it in the pDoc array (with an underscore): put "2-95a8c0a9268e896dd9c46a1b2a6e9c80" into tDocument["_rev"]
Greg (pink) Miller

MadPink, LLC
I'm Mad, Pink and Dangerous to Know

FourthWorld
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 9801
Joined: Sat Apr 08, 2006 7:05 am
Location: Los Angeles
Contact:

Re: CouchDB Library

Post by FourthWorld » Mon Jul 27, 2015 11:42 pm

Nice work, Greg. What license is this released under?
Richard Gaskin
LiveCode development, training, and consulting services: Fourth World Systems
LiveCode Group on Facebook
LiveCode Group on LinkedIn

pink
Posts: 272
Joined: Wed Mar 12, 2014 6:18 pm

Re: CouchDB Library

Post by pink » Tue Jul 28, 2015 12:49 am

that's an excellent question, I would probably go with Apache, but since I included EasyJSON in the code I should check and see what license to see if they are compatible
Greg (pink) Miller

MadPink, LLC
I'm Mad, Pink and Dangerous to Know

pink
Posts: 272
Joined: Wed Mar 12, 2014 6:18 pm

Re: CouchDB Library

Post by pink » Thu Jul 30, 2015 4:55 pm

For anyone who is tinkering with this, I have a simple function for getting documents based on a view.

pDesign is the name of the design document
pView is the name of the view in the design document

Code: Select all

function couchdb.view pURL pDB pParams pDesign pView
     put couch.DBURL(pURL,pDB) into tURL
     put "/_design/" & pDesign & "/_view/" & pView after tURL
     if pParams is not empty then put couch.parseParams(pParams) after tURL
     put URL (tURL) into tResult
     put arrayFromJson(tResult) into tReturn
     --note: if there are no results, arrayFromJson will throw an error
     if tReturn is not an array then put empty into tReturn
     return tReturn     
end couchdb.view
There's one big problem, if it turns out there are no results, then the result comes back with an empty JSON array for the key "rows". EasyJSON does not like this at all and will return an error. For the time being, I set it up so that the error is replaced by empty when it comes back.

Here's what the raw data looks like when returned:

Code: Select all

{"total_rows":0,"offset":0,"rows":[

]}
Greg (pink) Miller

MadPink, LLC
I'm Mad, Pink and Dangerous to Know

pink
Posts: 272
Joined: Wed Mar 12, 2014 6:18 pm

Re: CouchDB Library

Post by pink » Tue Aug 04, 2015 12:01 pm

library updated with the first View function

one major change:
returned value will still be an array by default, but by setting a stack property, you can switch the returned value to alternatively be the raw JSON or a prettier JSON with each key/value on it's own line
Greg (pink) Miller

MadPink, LLC
I'm Mad, Pink and Dangerous to Know

FourthWorld
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 9801
Joined: Sat Apr 08, 2006 7:05 am
Location: Los Angeles
Contact:

Re: CouchDB Library

Post by FourthWorld » Tue Aug 04, 2015 4:05 pm

Great work, Greg, much appreciated. I have a project on the horizon for which I've been considering CouchDB, and with your handy library I'm even more inclined to use that DB.
Richard Gaskin
LiveCode development, training, and consulting services: Fourth World Systems
LiveCode Group on Facebook
LiveCode Group on LinkedIn

pink
Posts: 272
Joined: Wed Mar 12, 2014 6:18 pm

Re: CouchDB Library

Post by pink » Tue Aug 04, 2015 4:07 pm

I better get working on documentation then :D
Greg (pink) Miller

MadPink, LLC
I'm Mad, Pink and Dangerous to Know

FourthWorld
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 9801
Joined: Sat Apr 08, 2006 7:05 am
Location: Los Angeles
Contact:

Re: CouchDB Library

Post by FourthWorld » Tue Aug 04, 2015 4:43 pm

pink wrote:I better get working on documentation then :D
If you want some help with that I'd be happy to move this thread into the Open Source Projects section of the forums to raise visibility as a collaborative effort.
Richard Gaskin
LiveCode development, training, and consulting services: Fourth World Systems
LiveCode Group on Facebook
LiveCode Group on LinkedIn

pink
Posts: 272
Joined: Wed Mar 12, 2014 6:18 pm

Re: CouchDB Library

Post by pink » Fri Sep 18, 2015 2:42 pm

I am up in the process of updating and cleaning up this Library and need some advice.


Consideration 1: Currently I have a seperate commands for each CouchDB function, but I am thinking of uniting them into a few sets of commands instead.

For example, here are 3 "get" commands which retrieve a document, info on the database, or all documents in the database respectively.

Code: Select all

function couch.getdoc pURL pDB pParams pDocID
     local tResult
     put URL (couch.DBURL(pURL,pDB,pParams,,pDocID)) into tResult
     return returnFormat(tResult)
end couch.getdoc
 
 
function couch.getdb pURL pDB
     local tResult
     put URL (couch.DBURL(pURL,pDB)) into tResult
     return returnFormat(tResult)
end couch.getdb

function couch.all_docs pURL pDB pParams pDocsOnly
     local tFunk,tURL,tResult,tForm
     put "_all_docs" into tFunk
     put URL (couch.DBURL(pURL,pDB,pParams,tFunk)) into temp
     put returnFormat(temp) into tResult
     put the preferredFormat of this stack into tForm
     if pDocsOnly is true and tForm is "array" then 
          return tResult["rows"]
     else
          return tResult
     end if
end couch.all_docs
Here's a proposed "unified" command:

Code: Select all

function couch.get pFunk pURL pDB pParams pDocID pModifier
     local tResult
     couch.setheaders
     switch pFunk
          case "doc"
               put URL (couch.DBURL(pURL,pDB,pParams,,pDocID)) into tResult
               return returnFormat(tResult)
               break
          case "db"
               put URL (couch.DBURL(pURL,pDB)) into tResult
               return returnFormat(tResult)
               break
          case "_all_docs"
               local tForm
               put URL (couch.DBURL(pURL,pDB,pParams,pFunk)) into tResult
               put returnFormat(tResult) into tResult
               put the preferredFormat of this stack into tForm
               if pModifier is true and tForm is "array" then 
                    return tResult["rows"]
               else
                    return tResult
               end if
               break
     end switch
end couch.get
One of my concerns was the parameters that get passed into each command.

Now in the combined function, not all of the parameters are used, so it might be confusing. (Although sending unnecessary parameters would not be detrimental)
On the other hand, all of the parameters would be in exactly the same place regardless of whether used or not.

Consideration 2: In my usage of this library, I actually found it a bit cumbersome to constantly have to include the URL with each command. Originally my desire was to allow users to switch hosts if wanted. In my own usage, I've gotten in the habit of setting a constant (kURL) and using it in the command.

thought 1: leave as-is, require URL to be included in all calls

thought 2: create a getProp/setProp for the URL
the user can set it and forget it, or change it on the fly if needed
during the URL assembly stage, the URL can be "getted" and put into place
the only downside I see is that if the user doesn't set it, the entire command will fail without warning

thoughts?
Greg (pink) Miller

MadPink, LLC
I'm Mad, Pink and Dangerous to Know

jiml
Posts: 336
Joined: Sat Dec 09, 2006 1:27 am
Location: Los Angeles

Re: CouchDB Library

Post by jiml » Sun Sep 20, 2015 7:36 pm

Combining multiple functions into one can sometimes result in code that's difficult to follow. But in this case I think your unified function is simple enough to understand.

jiml
Posts: 336
Joined: Sat Dec 09, 2006 1:27 am
Location: Los Angeles

Re: CouchDB Library

Post by jiml » Sun Sep 20, 2015 7:39 pm

P.S. I think RETURN stops the current handler, so those following BREAKs may not be needed.

Klaus
Posts: 13793
Joined: Sat Apr 08, 2006 8:41 am
Location: Germany
Contact:

Re: CouchDB Library

Post by Klaus » Sun Sep 20, 2015 10:05 pm

jiml wrote:P.S. I think RETURN stops the current handler, so those following BREAKs may not be needed.
Maybe, but that makes the script better readable and is good style! :D

pink
Posts: 272
Joined: Wed Mar 12, 2014 6:18 pm

Re: CouchDB Library

Post by pink » Sun Sep 20, 2015 10:47 pm

I threw the switch command together from the original commands, in final form, I would probably leave the breaks in and move the return statement to the bottom since almost all of the commands return exactly the same thing
Greg (pink) Miller

MadPink, LLC
I'm Mad, Pink and Dangerous to Know

FourthWorld
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 9801
Joined: Sat Apr 08, 2006 7:05 am
Location: Los Angeles
Contact:

Re: CouchDB Library

Post by FourthWorld » Fri Oct 23, 2015 9:17 pm

Looks like I may have a use for this coming up in a few weeks. Still need testing on it? How complete is it at this point?
Richard Gaskin
LiveCode development, training, and consulting services: Fourth World Systems
LiveCode Group on Facebook
LiveCode Group on LinkedIn

pink
Posts: 272
Joined: Wed Mar 12, 2014 6:18 pm

Re: CouchDB Library

Post by pink » Fri Oct 23, 2015 10:14 pm

as coincidence has it, I just posted a new version to Github yesterday

I've really simplified it, basically it consists of 4 functions (couch.get, couch.post, couch.put and couch.delete) which so far can handle pretty much all of the important CouchDB API calls.

I have been using this library in a production environment for a few months now with great success.

Originally I had incorporated EasyJSON into the library, but have since taken it out. Users will need to insert a JSON-Array converter somewhere. For my own projects, I've switched over to FastJSON and it has been working very well.

This weekend I will be creating some documentation with examples.

ROADMAP:
-need to reintroduce support for design documents
-still working code for an offline syncing database (really it's just converting database calls into Livecode arrays and saving those arrays as custom properties of a storage stack)
-will post my "Daybed Toolbox" stack soon
-debating as to whether I want to handle error messages internally, or to just pass on the information to whatever variable the result is being sent to
Greg (pink) Miller

MadPink, LLC
I'm Mad, Pink and Dangerous to Know

Post Reply

Return to “Databases”