lib/utils.nim
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 |
import json, db_sqlite, strutils, pegs, asyncdispatch, asynchttpserver2, times, logging
import types, queries, contenttypes
proc dbQuote*(s: string): string =
result = "'"
for c in items(s):
if c == '\'': add(result, "''")
else: add(result, c)
add(result, '\'')
proc currentTime*(): string =
return getTime().getGMTime().format("yyyy-MM-dd'T'hh:mm:ss'Z'")
proc selectDocumentsByTags(tags: string): string =
var select_tagged = "SELECT document_id FROM tags WHERE tag_id = \""
result = ""
for tag in tags.split(','):
if not tag.match(PEG_TAG):
raise newException(EInvalidTag, "Invalid tag '$1'" % tag)
result = result & "AND id IN (" & select_tagged & tag & "\") "
proc prepareSelectDocumentsQuery*(options: QueryOptions): string =
result = "SELECT " & options.select & " "
if options.search.len > 0:
result = result & "FROM documents, searchcontents "
result = result & "WHERE documents.id = searchcontents.document_id "
else:
result = result & "FROM documents WHERE 1=1 "
if options.single:
result = result & "AND id = ?"
if options.tags.len > 0:
result = result & options.tags.selectDocumentsByTags()
if options.search.len > 0:
result = result & "AND content MATCH \"" & options.search & "\""
if options.orderby.len > 0:
result = result & "ORDER BY " & options.orderby & " "
if options.limit > 0:
result = result & "LIMIT " & $options.limit & " "
if options.offset > 0:
result = result & "OFFSET " & $options.offset & " "
proc prepareSelectTagsQuery*(options: QueryOptions): string =
result = "SELECT tag_id, COUNT(document_ID) "
result = result & "FROM tags "
if options.single:
result = result & "WHERE tag_id = ?"
result = result & "GROUP BY tag_id"
if options.orderby.len > 0:
result = result & "ORDER BY " & options.orderby&" "
if options.limit > 0:
result = result & "LIMIT " & $options.limit & " "
proc prepareJsonDocument*(store:Datastore, doc: TRow): JsonNode =
var raw_tags = store.db.getAllRows(SQL_SELECT_DOCUMENT_TAGS, doc[0])
var tags = newSeq[JsonNode](0)
for tag in raw_tags:
tags.add(%($(tag[0])))
if doc.len == 1:
# COUNT(id)
return %(doc[0].parseInt)
elif doc.len > 6:
return % [("id", %doc[0]),
("data", %doc[1]),
("created", %doc[5]),
("modified", %doc[6]),
("tags", %tags)]
else:
# data was not retrieved
return % [("id", %doc[0]),
("created", %doc[4]),
("modified", %doc[5]),
("tags", %tags)]
proc checkIfBinary*(binary:int, contenttype:string): int =
if binary == -1 and contenttype.isBinary:
return 1
else:
return binary
proc addDocumentSystemTags*(store: Datastore, docid, contenttype: string) =
var splittype = contenttype.split("/")
var tags = newSeq[string](0)
tags.add "$type:"&splittype[0]
tags.add "$subtype:"&splittype[1]
var binary = checkIfBinary(-1, contenttype)
if binary == 1:
tags.add "$format:binary"
else:
tags.add "$format:text"
for tag in tags:
store.db.exec(SQL_INSERT_TAG, tag, docid)
proc destroyDocumentSystemTags*(store: Datastore, docid) =
store.db.exec(SQL_DELETE_DOCUMENT_SYSTEM_TAGS, docid)
proc fail*(code, msg) =
stderr.writeln(msg)
quit(code)
proc resError*(code: HttpCode, message: string): Response =
warn(message)
result.code = code
result.content = """{"error":"$1"}""" % message
result.headers = ctJsonHeader()
proc resDocumentNotFound*(id): Response =
resError(Http404, "Document '$1' not found." % id)
|