Coverage report: /home/ati/workspace/perec/query/runtime.lisp
Kind | Covered | All | % |
expression | 161 | 192 | 83.9 |
branch | 33 | 42 | 78.6 |
Key
Not instrumented
Conditionalized out
Executed
Not executed
Both branches taken
One branch taken
Neither branch taken
1
;; -*- mode: Lisp; Syntax: Common-Lisp; -*-
3
;;; Copyright (c) 2006 by the authors.
5
;;; See LICENCE for details.
9
;;;; Functions called from compiled queries.
12
;;; Lisp implementation of some SQL funtion
14
(defun like (str pattern)
15
"Matches STR with PATTERN. In the pattern _ and % wildcards can be used"
16
(flet ((like-pattern->regex (pattern)
17
(setf pattern (regex-replace-all "([.*+?(){}|^$])" pattern "\\\\\\1"))
18
(setf pattern (regex-replace-all "(?<!\\\\)_" pattern "."))
19
(setf pattern (regex-replace-all "(?<!\\\\)%" pattern ".*"))))
20
(if (scan (like-pattern->regex pattern) str) #t #f)))
23
"Returns the sum of non NIL elements of SEQ."
24
(iter (for val in-sequence seq)
28
"Returns the average of non NIL elements of SEQ."
29
(iter (for val in-sequence seq)
30
(sum (or val 0) into sum)
31
(counting val into count)
32
(finally (return (if (> count 0) (/ sum count) 0)))))
37
(defun cache-object-with-prefetched-slots (row start prefetched-slots)
38
"Caches the objects whose oid and slots are contained by ROW starting at START."
39
(bind ((oid-width (length +oid-column-names+))
40
(oid (subseq row start (+ start oid-width)))
42
(iter (for slot in prefetched-slots)
43
(for width = (column-count-of slot))
44
(for index initially (+ start oid-width) then (+ index width))
45
(collect (subseq row index (+ index width))))))
46
(cache-object* oid prefetched-slots rdbms-values)))
48
(defun cache-object* (oid slots rdbms-values)
49
"Caches the objects whose oid and slots are contained by ROW starting at START."
50
(bind ((object (cache-object oid)))
51
(mapc (lambda (slot rdbms-value)
52
;; we use the slot-name here because we can't guarantee that the effective slot will match with the class of the object
53
(setf (cached-slot-boundp-or-value object (slot-definition-name slot))
54
(restore-slot-value slot rdbms-value)))
58
(defun column-count-of (slot)
59
(length (columns-of slot)))
61
(defun invalidate-persistent-flag-of-cached-objects (class)
62
"Sets the persistent slot to unbound for instances of class in the transaction cache."
65
(declare (ignore oid))
66
(when (typep object class)
67
(slot-makunbound object 'persistent)))
68
(objects-of (current-object-cache))))
71
;;; Conversion between lisp and sql values
73
(defgeneric value->sql-literal (value type &optional args)
77
(:method (value type &optional args)
78
(error "Can not cast ~A to ~A" value (compose-type type args)))
82
(:method (value (type symbol) &optional args)
83
(sql-literal :value (value->sql-value value (compose-type type args))))
85
(:method (value (type persistent-class) &optional args)
87
(assert (typep value type))
88
(value->sql-literal value (class-name type)))
90
(:method (value (type cons) &optional args)
92
(value->sql-literal value (first type) (rest type)))
94
;; Infer type from value
96
(:method ((value persistent-object) (type (eql +unknown-type+)) &optional args)
98
(value->sql-literal value (type-of value)))
100
(:method ((value string) (type (eql +unknown-type+)) &optional args) ; TODO
102
(value->sql-literal value 'string))
104
(:method ((value number) (type (eql +unknown-type+)) &optional args) ; TODO BIT
106
(value->sql-literal value 'number))
110
(:method ((value list) (type (eql 'set)) &optional args)
111
(assert (not (null args)))
112
(assert (every #L(typep !1 (first args)) value))
113
(sql-literal :value (mapcar #L(value->sql-literal !1 (first args)) value)))
115
(:method ((value list) (type (eql +unknown-type+)) &optional args) ; FIXME hopefully not a form
117
(sql-literal :value (mapcar #L(value->sql-literal !1 type) value))))
119
(defun value->sql-value (value type)
120
(assert (not (eq type +unknown-type+)))
121
(bind ((sql-values (value->sql-values value type)))
122
(case (length sql-values)
123
(1 (first sql-values))
125
((persistent-class-type-p (normalized-type-for type)) ; only id column used
127
((and (null-subtype-p type) (unbound-subtype-p type))
128
(assert (first sql-values)) ; check if BOUND
129
(second sql-values)) ; omit BOUND column
131
(error "unsupported multi-column type: ~A" type))))
132
(t (error "unsupported multi-column type: ~A" type)))))
134
(defun value->sql-values (value type)
135
(assert (not (eq type +unknown-type+)))
137
(compute-writer nil type)
140
(defun compose-type (type args)
141
(if args (cons type args) type))