Coverage report: /development/source/library/org/datagraph/spocq-shard/src/odbc/service.lisp
| Kind | Covered | All | % |
| expression | 0 | 256 | 0.0 |
| branch | 0 | 10 | 0.0 |
Key
Not instrumented
Conditionalized out
Executed
Not executed
Both branches taken
One branch taken
Neither branch taken
1
;;; -*- Mode: lisp; Syntax: ansi-common-lisp; Base: 10; Package: org.datagraph.spocq.implementation; -*-
3
(in-package :org.datagraph.spocq.implementation)
5
(:documentation "service operation implementation for odbc-based sql processing.")
7
(defclass hydra:|ODBCView| (hydra:|Operation|)
9
:initform (make-registry :test 'eql)
10
:reader repository-sql-cache)
12
:initform nil :initarg :connection
13
:reader get-repository-connection
14
:writer setf-repository-connection)))
16
(defclass hydra:|PostgresView| (hydra:|ODBCView|)
19
(defmethod call-with-repository-connection (op (repository hydra:|ODBCView|))
20
(let* ((odbc-uri (repository-uri repository))
21
(driver (spocq:odbc-uri-driver odbc-uri))
22
(uri-authority (spocq:odbc-uri-authority odbc-uri))
23
(authority (when uri-authority (authority uri-authority)))
24
(user (if authority (agent-name authority) (spocq:odbc-uri-user odbc-uri)))
25
(password (if authority (agent-password authority) (spocq:odbc-uri-password odbc-uri))))
26
(clsql:with-database (db-connection (list driver user password)
27
:database-type :odbc :pool t :if-exists :new)
28
(funcall op db-connection))))
31
(defmethod repository-connection ((repository hydra:|ODBCView|))
32
(or (get-repository-connection repository)
33
(setf-repository-connection (let* ((odbc (repository-uri repository))
34
(uri-authority (spocq:odbc-uri-authority odbc))
35
(authority (when uri-authority (authority uri-authority)))
36
(user (if authority (agent-name authority) (spocq:odbc-uri-user odbc)))
37
(password (if authority (agent-password authority) (spocq:odbc-uri-password odbc))))
38
(clsql:connect `(;;,(spocq:odbc-uri-database odbc)
39
,(spocq:odbc-uri-driver odbc)
42
:database-type :odbc))
47
;;; remote service operations
49
(defmethod spocq.e:service ((service-repository hydra:|ODBCView|) (query-expression t) &key (verbose t) user-id query-text)
50
"For external view processing, compute a generator which will start an external process to run
51
the remote query as a view and intern the result solution stream."
52
(declare (ignore user-id query-text))
53
(authorize-service-request *task* service-repository)
54
(odbc-view-generator service-repository (expression-dimensions query-expression)
58
(defmethod repository-sparql-sql ((repository hydra:|ODBCView|) expression)
59
(let ((entry (get-registry expression (repository-sql-cache repository))))
61
(setf entry (multiple-value-list (call-next-method)))
62
(setf (get-registry expression (repository-sql-cache repository)) entry))
63
(apply #'values entry)))
65
(defun odbc-view-generator (repository pattern-dimensions query-expression &key verbose)
66
"Construct a generator which will delegate request/response processing for a remote view
67
to an external thread.
68
In the event of error, unless verbose, suppress it and proceed with a table solution field.
69
When verbose, decline to handle the error and delegate it to the context."
70
(handler-bind ((error (lambda (c)
71
(log-warn "odbc service view failure: ~a: ~a" repository c)
73
(return-from odbc-view-generator
74
(singleton-generator pattern-dimensions))))))
75
;;(bt:with-lock-held ((repository-lock repository))
76
(multiple-value-bind (sql-query sql-environment)
77
(repository-sparql-sql repository query-expression)
78
(with-repository-connection (db-connection repository)
79
(multiple-value-bind (sql-solutions attribute-names)
80
(clsql:query sql-query :database db-connection)
81
(let* ((count (length sql-solutions))
82
;; either known results, or respective undistinguished variables
83
(sql-dimensions (loop for attribute in attribute-names
84
for dimension = (cond ((sql-attribute-variable attribute sql-environment))
86
(warn "attribute not in sql environment: ~s: ~s"
88
(sql-environment-av-map sql-environment))
90
collect (or dimension (make-variable attribute)))))
91
(trace-algebra odbc-view-generator :sql-env sql-environment :pd pattern-dimensions :sd sql-dimensions)
92
(unless (equal pattern-dimensions sql-dimensions)
93
(setf sql-solutions (loop for solution in sql-solutions
94
collect (loop for pattern-dimension in pattern-dimensions
95
collect (loop for term in solution for sql-dimension in sql-dimensions
96
when (eq pattern-dimension sql-dimension)
98
finally (return (spocq:make-unbound-variable pattern-dimension)))))))
99
(typecase *transaction*
101
(let ((result-field (make-matrix-field :dimensions sql-dimensions :row-count count)))
102
(set-solution-field-solutions result-field sql-solutions)
103
(complete-field-data result-field)
106
(let ((result-channel (make-channel :name (list 'spocq.a:|service| (task-id *query*))
107
:dimensions pattern-dimensions)))
108
(make-solution-generator :operator 'spocq.a:|service|
109
:dimensions pattern-dimensions
110
:expression (list #'run-service-thread result-channel sql-solutions pattern-dimensions)
111
:channel result-channel
112
:constituents ()))))))))));)
114
(defmethod run-sip-service-step ((repository hydra:|ODBCView|) destination pattern-expression bindings &rest args)
115
"A postgres repository handles a service operation w/ sip by translating the sparql expression into SQL,
116
serializing that wrt the given solution, executing the SQL query through a remote connection, interning the
117
response, and emitting it to the given destination."
118
(declare (ignore args))
119
(authorize-service-request *task* repository)
120
(multiple-value-bind (sql-query sql-environment)
121
(repository-sparql-sql repository pattern-expression)
122
(with-repository-connection (db-connection repository)
123
(multiple-value-bind (sql-solutions attribute-names)
124
(clsql:query sql-query :database db-connection)
125
(let* ((count (length sql-solutions))
126
(sql-dimensions (loop for attribute in attribute-names
127
for dimension = (cond ((sql-attribute-variable attribute sql-environment))
129
(warn "attribute not in sql environment: ~s" attribute)
131
collect (or dimension (cons-variable attribute))))
132
(result-dimensions (channel-dimensions destination))
133
(width (length result-dimensions))
134
(page (new-field-page destination count width)))
135
(trace-algebra odbc-view-generator :sql-env sql-environment :rd result-dimensions :sd sql-dimensions)
136
(cond ((equal result-dimensions sql-dimensions)
137
(term-number-field sql-solutions :field page))
139
(let ((interned-sip-solution (loop for (nil . term) in bindings
140
collect (rdfcache-object-term-number *transaction* term))))
141
(transaction-intern-shuffeled-field *transaction* sql-solutions sql-dimensions result-dimensions :field page :partial t)
142
(loop for i below count
143
do (loop for j from 0
144
for dimension in result-dimensions
145
;; if the dimension was in the sip and not in the view, the assert the term
146
unless (find dimension sql-dimensions)
147
do (loop for (sip-dimension . nil) in bindings
148
for term-number in interned-sip-solution
149
when (eq dimension sip-dimension)
150
do (setf (aref page i j) term-number)))))))
151
(trace-data run-sip-service-step :page page (term-value-field page))
152
(put-field-page destination page)