all repos — litestore @ 63fa54a4b8228bb2ee19b2039b4dcd8d0aa0cd3b

A minimalist nosql document store.

Implemented info table
* Closes #24.
h3rald h3rald@h3rald.com
Sat, 16 May 2015 21:57:18 +0200
commit

63fa54a4b8228bb2ee19b2039b4dcd8d0aa0cd3b

parent

1f6fee50ef790e053da1cf113c2e95ca0561b2b7

7 files changed, 51 insertions(+), 18 deletions(-)

jump to
M lib/api_v1.nimlib/api_v1.nim

@@ -179,11 +179,14 @@ result.content = content.pretty

result.code = Http200 proc getInfo(LS: LiteStore): Response = - let total_docs = LS.store.countDocuments() + let info = LS.store.retrieveInfo() + let version = info[0] + let total_documents = info[1] let total_tags = LS.store.countTags() let tags = LS.store.retrieveTagsWithTotals() var content = newJObject() content["version"] = %(LS.appname & " v" & LS.appversion) + content["datastore_version"] = %version content["size"] = %($((LS.file.getFileSize().float/(1024*1024)).formatFloat(ffDecimal, 2)) & " MB") content["read_only"] = %LS.readonly content["log_level"] = %LS.loglevel

@@ -192,7 +195,7 @@ content["directory"] = newJNull()

else: content["directory"] = %LS.directory content["mount"] = %LS.mount - content["total_documents"] = %total_docs + content["total_documents"] = %total_documents content["total_tags"] = %total_tags content["tags"] = tags result.headers = ctJsonHeader()
M lib/cli.nimlib/cli.nim

@@ -15,7 +15,6 @@ directory:string = nil

readonly = false logLevel = "info" mount = false - reset = false let usage* = appname & " v" & version & " - Lightweight REST Document Store" & """

@@ -121,4 +120,3 @@ LS.readonly = readonly

LS.favicon = favicon LS.loglevel = loglevel LS.mount = mount -LS.reset = reset
M lib/core.nimlib/core.nim

@@ -42,11 +42,13 @@ LOG.debug("Creating tables")

data.exec(SQL_CREATE_DOCUMENTS_TABLE) data.exec(SQL_CREATE_SEARCHDATA_TABLE) data.exec(SQL_CREATE_TAGS_TABLE) + data.exec(SQL_CREATE_INFO_TABLE) + data.exec(SQL_INSERT_INFO, 1, 0, 0) LOG.debug("Creating indexes") data.createIndexes() LOG.debug("Database created") -proc closeDatastore*(store:Datastore) = +proc closeDatastore*(store: Datastore) = try: db.close(store.db) except:

@@ -78,6 +80,10 @@ result.mount = ""

except: raise newException(EDatastoreUnavailable, "Datastore '$1' cannot be opened." % file) +proc retrieveInfo*(store: Datastore): array[0..1, int] = + var data = store.db.getRow(SQL_SELECT_INFO) + return [data[0].parseInt, data[1].parseInt] + proc hasMirror(store: Datastore): bool = return store.mount.len > 0

@@ -103,14 +109,20 @@ # Manage Tags

proc createTag*(store: Datastore, tagid, documentid: string, system=false) = if tagid.match(PEG_USER_TAG) or system and tagid.match(PEG_TAG): + store.begin() store.db.exec(SQL_INSERT_TAG, tagid, documentid) + store.commit() else: + store.rollback() raise newException(EInvalidTag, "Invalid Tag: $1" % tagid) proc destroyTag*(store: Datastore, tagid, documentid: string, system=false): int64 = if tagid.match(PEG_USER_TAG) or system and tagid.match(PEG_TAG): - return store.db.execAffectedRows(SQL_DELETE_TAG, tagid, documentid) + store.begin() + result = store.db.execAffectedRows(SQL_DELETE_TAG, tagid, documentid) + store.commit() else: + store.rollback() raise newException(EInvalidTag, "Invalid Tag: $1" % tagid) proc retrieveTag*(store: Datastore, id: string, options: QueryOptions = newQueryOptions()): string =

@@ -168,6 +180,7 @@ try:

store.begin() var res = store.db.insertID(SQL_INSERT_DOCUMENT, id, data, contenttype, binary, searchable, currentTime()) if res > 0: + store.db.exec(SQL_INCREMENT_DOCS) if binary <= 0 and searchable >= 0: # Add to search index store.db.exec(SQL_INSERT_SEARCHCONTENT, res, id, data.toPlainText)

@@ -228,6 +241,7 @@ let singleOp = not LS_TRANSACTION

store.begin() result = store.db.execAffectedRows(SQL_DELETE_DOCUMENT, id) if result > 0: + store.db.exec(SQL_DECREMENT_DOCS) store.db.exec(SQL_DELETE_SEARCHCONTENT, id) store.db.exec(SQL_DELETE_DOCUMENT_TAGS, id) if store.hasMirror and id.startsWith(store.mount):

@@ -319,7 +333,6 @@ quit(203)

quit(0) proc importDir*(store: Datastore, dir: string) = - # TODO: Only allow directory names (not paths)? var files = newSeq[string]() if not dir.dirExists: raise newException(EDirectoryNotFound, "Directory '$1' not found." % dir)

@@ -374,12 +387,9 @@ store.db.exec(SQL_DELETE_DOCUMENTS_BY_TAG, "$dir:"&dir)

store.db.exec(SQL_DELETE_SEARCHDATA_BY_TAG, "$dir:"&dir) store.db.exec(SQL_DELETE_TAGS_BY_TAG, "$dir:"&dir) -proc mountDir*(store: var Datastore, dir:string, reset=false) = +proc mountDir*(store: var Datastore, dir:string) = if not dir.dirExists: raise newException(EDirectoryNotFound, "Directory '$1' not found." % dir) - if reset: - store.deleteDir(dir) - store.importDir(dir) store.mount = dir proc destroyDocumentsByTag*(store: Datastore, tag: string): int64 =
M lib/queries.nimlib/queries.nim

@@ -14,9 +14,6 @@ searchable INTEGER,

created TEXT, modified TEXT) """ - - - const SQL_CREATE_INDEX_DOCUMENTS_DOCID* = sql"CREATE INDEX IF NOT EXISTS documents_docid ON documents(docid)" SQL_CREATE_INDEX_DOCUMENTS_ID* = sql"CREATE INDEX IF NOT EXISTS documents_id ON documents(id)"

@@ -46,6 +43,32 @@ CREATE TABLE tags (

tag_id TEXT, document_id TEXT, PRIMARY KEY (tag_id, document_id)) +""" + +const SQL_CREATE_INFO_TABLE* = sql""" +CREATE TABLE info ( +version INT, +total_documents INT) +""" + +const SQL_INSERT_INFO* = sql""" +INSERT INTO info +(version, total_documents) +VALUES (?, ?) +""" + +const SQL_SELECT_INFO* = sql""" +SELECT * FROM info +""" + +const SQL_INCREMENT_DOCS* = sql""" +UPDATE info +SET total_documents = total_documents + 1 +""" + +const SQL_DECREMENT_DOCS* = sql""" +UPDATE info +SET total_documents = total_documents - 1 """ const SQL_INSERT_DOCUMENT* = sql"""
M lib/types.nimlib/types.nim

@@ -62,7 +62,6 @@ appname*: string

appversion*: string favicon*:string loglevel*:string - reset*: bool Response* = tuple[ code: HttpCode, content: string,
M lib/utils.nimlib/utils.nim

@@ -137,7 +137,7 @@ for tag in tags:

store.db.exec(SQL_INSERT_TAG, tag, docid) proc destroyDocumentSystemTags*(store: Datastore, docid: string) = - store.db.exec(SQL_DELETE_DOCUMENT_SYSTEM_TAGS, docid) + let n = store.db.execAffectedRows(SQL_DELETE_DOCUMENT_SYSTEM_TAGS, docid) proc fail*(code: int, msg: string) = LOG.error(msg)

@@ -145,7 +145,7 @@ quit(code)

proc ctHeader*(ct: string): StringTableRef = var h = TAB_HEADERS.newStringTable - h["Content-Tyoe"] = ct + h["Content-Type"] = ct return h proc ctJsonHeader*(): StringTableRef =
M litestore.nimlitestore.nim

@@ -42,7 +42,7 @@ try:

LS.store = LS.file.openDatastore() if LS.mount: try: - LS.store.mountDir(LS.directory, LS.reset) + LS.store.mountDir(LS.directory) except: eWarn() fail(202, "Unable to mount directory '$1'" % [LS.directory])