/src/core/design-document.lisp

http://github.com/sykopomp/chillax · Lisp · 152 lines · 133 code · 8 blank · 11 comment · 6 complexity · 3f74d989f28503621dac29fe3e72027f MD5 · raw file

  1. (in-package :chillax.core)
  2. ;;;
  3. ;;; Design Doc errors
  4. ;;;
  5. (define-condition view-not-found (couchdb-error)
  6. ((view :initarg :view :reader view-404-view)
  7. (design-doc :initarg :ddoc :reader view-404-design-document)
  8. (db :initarg :db :reader view-404-db))
  9. (:report (lambda (e s)
  10. (format s "No view \"_design/~A/_view/~A\" was found in ~A"
  11. (view-404-design-document e)
  12. (view-404-view e)
  13. (view-404-db e)))))
  14. ;;;
  15. ;;; Design Doc basics
  16. ;;;
  17. (defun view-cleanup (db)
  18. "Invokes _view_cleanup on DB. Old view output will remain on disk until this is invoked."
  19. (handle-request (response db "_view_cleanup" :method :post)
  20. (:accepted response)))
  21. (defun compact-design-doc (db design-doc-name)
  22. "Compaction can really help when you have very large views, very little space, or both."
  23. (handle-request (response db (strcat "_compact/" design-doc-name) :method :post)
  24. (:accepted response)
  25. (:not-found (error 'document-not-found :db db :id (strcat "_design/" design-doc-name)))))
  26. (defun design-doc-info (db design-doc-name)
  27. "Returns an object with various bits of status information. Refer to CouchDB documentation for
  28. specifics on each value."
  29. (let ((ddoc (strcat "_design/" design-doc-name)))
  30. (handle-request (response db (strcat ddoc "/_info"))
  31. (:ok response)
  32. (:not-found (error 'document-not-found :db db :id ddoc)))))
  33. (defun build-view-params (database &key
  34. (key nil key-given)
  35. (startkey nil startkey-given)
  36. (endkey nil endkey-given)
  37. startkey-docid endkey-docid limit skip
  38. (descendingp nil descendingpp)
  39. (groupp nil grouppp) group-level
  40. (reducep t reducepp) stalep
  41. (include-docs-p nil include-docs-p-p)
  42. (inclusive-end-p t inclusive-end-p-p)
  43. &allow-other-keys)
  44. (let ((params ()))
  45. (labels ((%param (key value)
  46. (push (cons key (princ-to-string value)) params))
  47. (maybe-param (test name value)
  48. (when test (%param name value)))
  49. (param (name value)
  50. (maybe-param value name value))
  51. (encode (value)
  52. (data->json (database-server database) value)))
  53. (maybe-param key-given "key" (encode key))
  54. (maybe-param startkey-given "startkey" (encode startkey))
  55. (maybe-param endkey-given "endkey" (encode endkey))
  56. (maybe-param inclusive-end-p-p "inclusive_end" (if inclusive-end-p "true" "false"))
  57. (param "startkey_docid" startkey-docid)
  58. (param "endkey_docid" endkey-docid)
  59. (param "limit" limit)
  60. (maybe-param stalep "stale" "ok")
  61. (maybe-param descendingpp "descending" (if descendingp "true" "false"))
  62. (param "skip" skip)
  63. (maybe-param grouppp "group" (if groupp "true" "false"))
  64. (param "group_level" group-level)
  65. (maybe-param reducepp "reduce" (if reducep "true" "false"))
  66. (maybe-param include-docs-p-p "include_docs" (if include-docs-p "true" "false")))
  67. params))
  68. (defun query-view (db design-doc-name view-name &rest all-keys
  69. &key key startkey startkey-docid endkey
  70. multi-keys endkey-docid limit skip
  71. descendingp groupp group-level
  72. reducep stalep include-docs-p
  73. inclusive-end-p)
  74. "Queries view named by VIEW-NAME in DESIGN-DOC-NAME. Keyword arguments correspond to CouchDB view
  75. query arguments.
  76. * key - Single key to search for.
  77. * multi-keys - Multiple keys to search for.
  78. * startkey - When searching for a range of keys, the key to start from.
  79. * endkey - When searching for a range of keys, the key to end at. Whether this is inclusive or not
  80. depends on inclusive-end-p (default: true)
  81. * inclusive-end-p - If TRUE, endkey is included in the result. (default: true)
  82. * startkey-docid - Like startkey, but keyed on the result documents' doc-ids.
  83. * endkey-docid - Like endkey, but keyed on the result documents' doc-ids.
  84. * limit - Maximum number of results to return.
  85. * stalep - If TRUE, CouchDB will not refresh the view, even if it is stalled. (default: false)
  86. * descendingp - If TRUE, will return reversed results. (default: false)
  87. * skip - Number of documents to skip while querying.
  88. * groupp - Controls whether the reduce function reduces to a set of distinct keys, or to a single
  89. result row.
  90. * group-level - It's complicated. Google it!
  91. * reducep - If FALSE, return the view without applying its reduce function (if any). (default: true)
  92. * include-docs-p - If TRUE, includes the entire document with the result of the query. (default: false)"
  93. (declare (ignore key startkey startkey-docid endkey endkey-docid limit skip descendingp
  94. groupp group-level reducep stalep include-docs-p inclusive-end-p))
  95. (let ((params (apply #'build-view-params db all-keys))
  96. (doc-name (strcat "_design/" design-doc-name "/_view/" view-name)))
  97. (if multi-keys
  98. (let* ((server (database-server db))
  99. (content (with-output-to-string (s)
  100. (write-string "{\"keys\":[" s)
  101. (mapl (lambda (kl)
  102. (write-string (data->json server (car kl)) s)
  103. (unless (null (cdr kl))
  104. (write-string "," s)))
  105. multi-keys)
  106. (write-string "]}" s))))
  107. ;; If we receive the MULTI-KEYS argument, we have to do a POST instead.
  108. (handle-request (response db doc-name :method :post
  109. :parameters params
  110. :content content
  111. :convert-data-p nil)
  112. (:ok response)
  113. (:not-found (error 'view-not-found :db db :view view-name :ddoc design-doc-name))))
  114. (handle-request (response db doc-name :parameters params)
  115. (:ok response)
  116. (:not-found (error 'view-not-found :db db :view view-name :ddoc design-doc-name))))))
  117. ;;;
  118. ;;; Views
  119. ;;;
  120. (defun query-temporary-view (db &rest all-keys &key (language "javascript") reduce
  121. (map (error "Must provide a map function for temporary views."))
  122. key startkey startkey-docid endkey
  123. endkey-docid limit skip
  124. descendingp groupp group-level
  125. reducep stalep include-docs-p
  126. inclusive-end-p)
  127. "Queries a temporary view. These views are meant to be for testing and development purposes, and
  128. should _not_ be used in actual code."
  129. ;; I'm not sure CouchDB actually accepts all the view parameters for temporary views...
  130. (declare (ignore key startkey startkey-docid endkey endkey-docid limit skip descendingp
  131. groupp group-level reducep stalep include-docs-p inclusive-end-p))
  132. (let ((json (with-output-to-string (s)
  133. (format s "{")
  134. (format s "\"language\":~S" language)
  135. (format s ",\"map\":~S" map)
  136. (when reduce
  137. (format s ",\"reduce\":~S" reduce))
  138. (format s "}")))
  139. (params (apply #'build-view-params db all-keys)))
  140. (handle-request (response db "_temp_view" :method :post
  141. :parameters params
  142. :content json
  143. :convert-data-p nil)
  144. (:ok response))))