added clocking data to sql archive
This commit is contained in:
parent
224ebf6db0
commit
1182633506
172
conf.org
172
conf.org
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue