added clocking data to sql archive

This commit is contained in:
ndwarshuis 2018-12-23 12:56:12 -05:00
parent 224ebf6db0
commit 1182633506
1 changed files with 121 additions and 51 deletions

172
conf.org
View File

@ -2677,13 +2677,13 @@ Org mode is great and all, but in many cases, text files just won't cut it. Hard
(unless (file-exists-p nd/org-sqlite-db-path) (unless (file-exists-p nd/org-sqlite-db-path)
(process-file-shell-command (concat "touch " nd/org-sqlite-db-path)) (process-file-shell-command (concat "touch " nd/org-sqlite-db-path))
(nd/sql-cmd nd/org-sqlite-db-path nd/org-sqlite-header-schema) (nd/sql-cmd nd/org-sqlite-db-path nd/org-sqlite-header-schema)
(nd/sql-cmd nd/org-sqlite-db-path nd/org-sqlite-state-changes-schema) (nd/sql-cmd nd/org-sqlite-db-path nd/org-sqlite-clocking-schema)))
(nd/sql-cmd nd/org-sqlite-db-path nd/org-sqlite-clocking-schema) ;; (nd/sql-cmd nd/org-sqlite-db-path nd/org-sqlite-state-changes-schema)
(nd/sql-cmd nd/org-sqlite-db-path nd/org-sqlite-notes-schema) ;; (nd/sql-cmd nd/org-sqlite-db-path nd/org-sqlite-notes-schema)
(nd/sql-cmd nd/org-sqlite-db-path nd/org-sqlite-deadline-changes-schema) ;; (nd/sql-cmd nd/org-sqlite-db-path nd/org-sqlite-deadline-changes-schema)
(nd/sql-cmd nd/org-sqlite-db-path nd/org-sqlite-schedule-changes-schema) ;; (nd/sql-cmd nd/org-sqlite-db-path nd/org-sqlite-schedule-changes-schema)
(nd/sql-cmd nd/org-sqlite-db-path nd/org-sqlite-properties-schema) ;; (nd/sql-cmd nd/org-sqlite-db-path nd/org-sqlite-properties-schema)
(nd/sql-cmd nd/org-sqlite-db-path nd/org-sqlite-tags-schema))) ;; (nd/sql-cmd nd/org-sqlite-db-path nd/org-sqlite-tags-schema)))
(defun nd/sql-cmd (db sql) (defun nd/sql-cmd (db sql)
"Execute string SQL on database DB executing `sql-sqlite-program'. "Execute string SQL on database DB executing `sql-sqlite-program'.
@ -2714,39 +2714,30 @@ converted to their symbol name."
(data-joined (string-join data-str ","))) (data-joined (string-join data-str ",")))
(nd/sql-cmd db (concat "insert into " tbl " values(" data-joined ");")))) (nd/sql-cmd db (concat "insert into " tbl " values(" data-joined ");"))))
(defun nd/org-element-header-to-sql (db tbl headline) (defun nd/org-element-timestamp-raw (prop obj)
"Parses org-element HEADLINE and inserts data into TBL in sqlite DB." "Return the raw-value of the timestamp PROP in OBJ if exists."
(let* ((src-path (nd/org-element-property-inherited :ARCHIVE_OLPATH headline)) (when obj
(src (nd/org-element-property-inherited :ARCHIVE_FILE headline)) (let ((ts (org-element-property prop obj)))
(offset (org-element-property :begin headline)) (when ts (org-element-property :raw-value ts)))))
(header-txt (org-element-property :raw-value headline))
(parent-tree (nd/org-element-get-parent-tree headline))
(creation-time (org-element-property :CREATED headline))
;; TODO get higher level source tree
;; TODO add contents
(closed-ts (org-element-property :closed headline))
(closed-time (org-element-property :raw-value closed-ts))
(rxv-file rxv-path)
(parent (org-element-property :parent headline))
(sql-data (list rxv-file offset parent-tree header-txt
creation-time closed-time src-path src nil)))
(nd/sql-insert db tbl sql-data)))
(defun nd/org-archive-to-db () (defun nd/org-element-find-type (type obj)
"Transfer archive files to sqlite database." "Find and return the first instance of TYPE in OBJ.
(let* ((db nd/org-sqlite-db-path) TYPE is an org element type symbol and OBJ is a list of elements/objects."
(rxv-path (expand-file-name "test.org_archive" org-directory)) (let ((obj-cur (car obj))
;; (dump-path (expand-file-name "dump.el" org-directory)) (obj-rem (cdr obj)))
(tree (with-current-buffer (find-file-noselect rxv-path) (if (eq type (org-element-type obj-cur))
(org-element-parse-buffer)))) obj-cur
(org-element-map tree 'headline (nd/org-element-find-type type obj-rem))))
(lambda (h) (nd/org-element-header-to-sql
nd/org-sqlite-db-path "headers" h)))))
;; (write-region "" nil dump-path)
;; (with-temp-file dump-path
;; (insert-file-contents dump-path)
;; (prin1 buf-data (current-buffer)))))
(defun nd/org-element-get-parent-headline (obj)
"Get the parent headline element (if any) of org-element OBJ."
(when obj
(let ((parent (org-element-property :parent obj)))
(if (eq 'headline (org-element-type parent))
parent
(nd/org-element-get-parent-headline parent)))))
;; TODO merge thing above with thing below
(defun nd/org-element-get-parent-tree (obj &optional acc) (defun nd/org-element-get-parent-tree (obj &optional acc)
"Construct parent tree path for object OBJ and concatenate to ACC. "Construct parent tree path for object OBJ and concatenate to ACC.
Returns '/' delimited path of headlines or nil if obj is in a toplevel Returns '/' delimited path of headlines or nil if obj is in a toplevel
@ -2794,31 +2785,110 @@ This includes everything except drawers, subheadings, and planning."
;; ((stringp (car e)) (car e)) ;; ((stringp (car e)) (car e))
;; (t (error (concat "unknown type: " (org-element-type e)))))) ;; (t (error (concat "unknown type: " (org-element-type e))))))
;; contents-list))))) ;; contents-list)))))
(defun nd/org-element-header-to-sql (db tbl headline archive-file-path)
"Parse org-element HEADLINE and insert data into TBL in sqlite DB.
ARCHIVE-FILE-PATH is the file path to the currently parsed archive file."
(let* ((headline-file-offset (org-element-property :begin headline))
(archive-tree-path (nd/org-element-get-parent-tree headline))
(source-file-path (nd/org-element-property-inherited :ARCHIVE_FILE headline))
(source-tree-path (nd/org-element-property-inherited :ARCHIVE_OLPATH headline))
(headline-text (org-element-property :raw-value headline))
(time-created (org-element-property :CREATED headline))
(time-closed (nd/org-element-timestamp-raw :closed headline))
(time-scheduled (nd/org-element-timestamp-raw :scheduled headline))
(time-deadline (nd/org-element-timestamp-raw :deadline headline))
(effort (org-element-property :EFFORT headline))
(priority (org-element-property :priority headline)))
(nd/sql-insert db tbl (list archive-file-path
headline-file-offset
archive-tree-path
source-file-path
source-tree-path
headline-text
time-created
time-closed
time-scheduled
time-deadline
effort
priority
;; TODO add contents
nil))))
(defun nd/org-element-clock-to-sql (db tbl clock archive-file-path)
"Parse org-element CLOCK and insert data into TBL in sqlite DB.
ARCHIVE-FILE-PATH is the file path to the currently parsed archive file."
(let* ((parent-headline (nd/org-element-get-parent-headline clock))
(headline-file-offset (org-element-property :begin parent-headline))
(clock-file-offset (org-element-property :begin clock))
(timestamp-obj (org-element-property :value clock))
(timestamp-type (org-element-property :type timestamp-obj))
time-start time-end)
;; process timestamp depending on if it is a range or singular
(cond ((eq 'inactive-range timestamp-type)
(setq time-start (org-timestamp-split-range timestamp-obj)
time-end (org-timestamp-split-range timestamp-obj t)))
((eq 'inactive timestamp-type)
(setq time-start timestamp-obj))
;; should never happen
(t (error (concat "unknown timestamp type: "
(symbol-name timestamp-type)))))
(setq time-start (org-element-property :raw-value time-start)
time-end (org-element-property :raw-value time-end))
(nd/sql-insert db tbl (list archive-file-path
headline-file-offset
clock-file-offset
time-start
time-end))))
(defun nd/org-archive-to-db ()
"Transfer archive files to sqlite database."
(let* ((db nd/org-sqlite-db-path)
(rxv-path (expand-file-name "test.org_archive" org-directory))
;; (dump-path (expand-file-name "dump.el" org-directory))
(tree (with-current-buffer (find-file-noselect rxv-path)
(org-element-parse-buffer))))
(org-element-map tree 'headline
(lambda (h) (nd/org-element-header-to-sql
nd/org-sqlite-db-path "headlines" h rxv-path)))
(org-element-map tree 'clock
(lambda (c) (nd/org-element-clock-to-sql
nd/org-sqlite-db-path "clocking" c rxv-path)))))
;; (write-region "" nil dump-path)
;; (with-temp-file dump-path
;; (insert-file-contents dump-path)
;; (prin1 buf-data (current-buffer)))))
#+END_SRC #+END_SRC
**** schemas **** schemas
The database is going to hold all header information in the archive files according to these schemas. The data structure consists of one master table =headers= for all headers and and one layer of auxilary tables for information in the property and logging drawers. The database is going to hold all header information in the archive files according to these schemas. The data structure consists of one master table =headers= for all headers and and one layer of auxilary tables for information in the property and logging drawers.
#+BEGIN_SRC emacs-lisp #+BEGIN_SRC emacs-lisp
(defconst nd/org-sqlite-header-schema (defconst nd/org-sqlite-header-schema
"CREATE TABLE headers ( "CREATE TABLE headlines (
archive_path TEXT, archive_file_path TEXT,
archive_offset INTEGER, headline_file_offset INTEGER,
archive_tree INTEGER, archive_tree_path TEXT,
header TEXT NOT NULL, source_file_path TEXT NOT NULL,
source_tree_path TEXT,
headline_text TEXT NOT NULL,
time_created DATE, time_created DATE,
time_closed DATE, time_closed DATE,
source_tree TEXT, time_scheduled DATE,
source_path TEXT, time_deadlined DATE,
effort TIME,
priority INTEGER,
content TEXT, content TEXT,
PRIMARY KEY (archive_path, archive_offset ASC));" PRIMARY KEY (archive_file_path, headline_file_offset ASC));"
"Schema to build the headers table in the org archive db.") "Schema to build the headers table in the org archive db.")
(defconst nd/org-sqlite-clocking-schema (defconst nd/org-sqlite-clocking-schema
"CREATE TABLE clocking ( "CREATE TABLE clocking (
path TEXT, archive_file_path TEXT,
\"offset\" INTEGER, headline_file_offset INTEGER,
time_in DATE NOT NULL, clock_file_offset INTEGER PRIMARY KEY,
time_out DATE NOT NULL, time_start DATE NOT NULL,
FOREIGN KEY (path, \"offset\") REFERENCES header (archive_path, archive_offset));" time_end DATE,
FOREIGN KEY (archive_file_path, headline_file_offset)
REFERENCES headlines (archive_file_path, headline_file_offset));"
"Schema to build the clocking table in the org archive db.") "Schema to build the clocking table in the org archive db.")
(defconst nd/org-sqlite-state-changes-schema (defconst nd/org-sqlite-state-changes-schema