| Kind | Covered | All | % |
| expression | 7 | 358 | 2.0 |
| branch | 0 | 6 | 0.0 |
1 ;;; -*- Mode: lisp; Syntax: ansi-common-lisp; Base: 10; Package: org.datagraph.spocq.implementation; -*-2 3 (in-package :org.datagraph.spocq)4 5 ;;; define representation and manipularion for odbc uri6 ;;; (load "patches/odbc-uri.lisp")7 8 (dsu:modpackage :org.datagraph.spocq9 (:export :mysql-uri10 :mysql-uri-p11 :make-mysql-uri12 :parse-mysql-uri13 :mysql-uri-user14 :mysql-uri-password15 :mysql-uri-authority16 :mysql-uri-port17 :mysql-uri-database18 :mysql-uri-parameters19 :mysql-uri-table20 :mysql-uri-schema21 22 :odbc-uri23 :odbc-uri-p24 :make-odbc-uri25 :parse-odbc-uri26 :odbc-uri-driver27 :odbc-uri-user28 :odbc-uri-password29 :odbc-uri-authority30 :odbc-uri-port31 :odbc-uri-database32 :odbc-uri-table33 :odbc-uri-query34 35 :postgresql-uri36 :postgresql-uri-p37 :make-postgresql-uri38 :parse-postgresql-uri39 :postgresql-uri-user40 :postgresql-uri-password41 :postgresql-uri-authority42 :postgresql-uri-port43 :postgresql-uri-database44 :postgresql-uri-parameters45 :postgresql-uri-schema46 47 :sql-uri48 :sql-uri-p49 :sql-uri-user50 :sql-uri-password51 :sql-uri-authority52 :sql-uri-port53 :sql-uri-database54 ))55 56 (defstruct (sql-uri (:include iri (lexical-form "")))57 ;; retain the default constructor58 user59 password60 authority61 port62 database63 )64 65 (defstruct (odbc-uri (:include sql-uri))66 ;; retain the default constructor67 driver68 table69 query70 )71 72 (defstruct (postgresql-uri (:include sql-uri))73 "the postgres url is defined as74 postgresql://[user[:password]@][netloc][:port][/dbname][?param1=value1&...]75 (see http://www.postgresql.org/docs/current/static/libpq-connect.html#LIBPQ-CONNSTRING)"76 parameters77 )78 79 (defstruct (mysql-uri (:include sql-uri))80 "the postgres url is defined as81 postgresql://[user[:password]@][netloc][:port][/dbname][.table][?param1=value1&...]"82 table83 parameters84 )85 86 ;;;87 88 (defmethod print-object ((object sql-uri) stream)89 (format stream "<~a>" (ensure-iri-lexical-form object)))90 91 (defun spocq.i::sql-uri (lexical-form)92 (spocq.i::construct-uri-term (spocq.i::parse-uri-scheme lexical-form) lexical-form))93 94 95 ;;; mysql96 97 (defparameter *mysql-uri-scanner*98 (cl-ppcre:create-scanner `(:sequence :start-anchor99 (:sequence "mysql://"100 (:greedy-repetition101 0 1102 (:sequence103 (:greedy-repetition104 0 1105 (:sequence106 (:greedy-repetition 0 1107 (:register108 (:greedy-repetition 1 nil (:inverted-char-class #\:))))109 ":"110 (:greedy-repetition 0 1111 (:register112 (:greedy-repetition 1 nil (:inverted-char-class #\@))))113 "@"))114 (:greedy-repetition 0 1115 (:register116 (:greedy-repetition 1 nil (:inverted-char-class #\: #\/))))117 (:greedy-repetition 0 1118 (:sequence ":"119 (:register120 (:greedy-repetition 1 nil (:inverted-char-class #\/)))))))121 "/"122 (:greedy-repetition123 0 1124 (:register125 (:greedy-repetition 1 nil (:inverted-char-class #\? #\.))))126 (:greedy-repetition127 0 1128 (:sequence #\.129 (:register130 (:greedy-repetition 1 nil (:inverted-char-class #\? #\.)))))131 (:greedy-repetition132 0 1133 (:sequence134 "?"135 (:greedy-repetition 0 1136 (:register137 (:greedy-repetition 1 nil :everything)))138 )))139 :end-anchor)))140 141 (defun parse-mysql-uri (value)142 (multiple-value-bind (whole strings)143 (cl-ppcre:scan-to-strings *mysql-uri-scanner* value)144 (if whole145 (values (loop for i from 0 for property in '(:user :password :authority :port :database :table :parameters)146 for value = (aref strings i)147 when value148 append (list property (case property149 (:parameters (loop for assignment in (dsu:split-string value #\&)150 for (key value) = (dsu:split-string assignment #\=)151 collect (cons (dsu:cons-symbol :keyword key) value)))152 (t value))))153 whole)154 (error "Invalid mysql uri lexical form: ~s" value))))155 ;;; (parse-mysql-uri "mysql://production:X5lhSMNlJVlK4O1d@localhost/test" )156 ;;; (spocq::parse-mysql-uri "mysql://production:X5lhSMNlJVlK4O1d@localhost/test.events?encoding=utf-8&schema=test" )157 ;;; (parse-mysql-uri "mysql://production:X5lhSMNlJVlK4O1d@localhost/test?table=events&encoding=utf-8" )158 159 (defmethod ensure-iri-lexical-form ((uri mysql-uri))160 (let ((value (mysql-uri-lexical-form uri)))161 (if (plusp (length value))162 value163 (let ((user (mysql-uri-user uri))164 (password (mysql-uri-password uri))165 (authority (mysql-uri-authority uri))166 (port (mysql-uri-port uri))167 (database (mysql-uri-database uri))168 (table (mysql-uri-table uri))169 (parameters (mysql-uri-parameters uri)))170 (setf (spocq::mysql-uri-lexical-form uri)171 (format nil "mysql://~:[~5*~;~:[~2*~;~@[~a~]:~@[~a~]@~]~@[~a~]~@[:~a~]~]/~@[~a~]~@[.~a~]~@[?~{~a=~a~^&~}~]"172 (or user password authority port) (or user password)173 user password authority port174 database175 table176 (loop for (key . value) in parameters177 collect (string-downcase key)178 collect value)))))))179 180 (defgeneric spocq.i::mysql-uri (value)181 (:method ((lexical-form cl:string))182 (multiple-value-bind (initargs lexical-form) (spocq:parse-mysql-uri lexical-form)183 (apply #'spocq:make-mysql-uri :lexical-form lexical-form initargs)))184 (:method ((uri spocq:mysql-uri))185 (ensure-iri-lexical-form uri)))186 187 (defgeneric mysql-uri-schema (uri)188 (:method ((uri mysql-uri))189 (rest (assoc :schema (mysql-uri-parameters uri)))))190 191 ;;; odbc192 193 (defparameter *odbc-uri-scanner*194 (cl-ppcre:create-scanner `(:sequence :start-anchor195 (:sequence "odbc:"196 (:greedy-repetition 0 1197 (:register198 (:greedy-repetition 1 nil (:inverted-char-class #\/))))199 "//"200 (:greedy-repetition201 0 1202 (:sequence203 (:greedy-repetition204 0 1205 (:sequence206 (:greedy-repetition 0 1207 (:register208 (:greedy-repetition 1 nil (:inverted-char-class #\:))))209 ":"210 (:greedy-repetition 0 1211 (:register212 (:greedy-repetition 1 nil (:inverted-char-class #\@))))213 "@"))214 (:greedy-repetition 0 1215 (:register216 (:greedy-repetition 1 nil (:inverted-char-class #\: #\/))))217 (:greedy-repetition 0 1218 (:sequence ":"219 (:register220 (:greedy-repetition 1 nil (:inverted-char-class #\/)))))))221 "/"222 (:greedy-repetition 0 1223 (:register224 (:greedy-repetition 1 nil (:inverted-char-class #\/))))225 (:greedy-repetition226 0 1227 (:sequence228 "/"229 (:greedy-repetition 0 1230 (:register231 (:greedy-repetition 1 nil (:inverted-char-class #\?))))232 (:greedy-repetition233 0 1234 (:sequence235 "?"236 (:greedy-repetition 0 1237 (:register238 (:greedy-repetition 1 nil :EVERYTHING))))))))239 :end-anchor)))240 241 ;;; odbc:[driver]//[user]:[password]@[host]:[port]/[database]/[tables]?[query]242 ;;; components: all, driver, user, password, host, port, database, table, query243 244 (defun parse-odbc-uri (value)245 (multiple-value-bind (whole strings)246 (cl-ppcre:scan-to-strings *odbc-uri-scanner* value)247 (if whole248 (values (loop for i from 0 for property in '(:driver :user :password :authority :port :database :table :query)249 for value = (aref strings i)250 when value append (list property value))251 whole)252 (error "Invalid odbc uri lexical form: ~s" value))))253 254 (defmethod ensure-iri-lexical-form ((uri odbc-uri))255 (let ((value (odbc-uri-lexical-form uri)))256 (if (plusp (length value))257 value258 (let ((driver (odbc-uri-driver uri))259 (user (odbc-uri-user uri))260 (password (odbc-uri-password uri))261 (authority (odbc-uri-authority uri))262 (port (odbc-uri-port uri))263 (database (odbc-uri-database uri))264 (table (odbc-uri-table uri))265 (query (odbc-uri-query uri)))266 (setf (spocq::odbc-uri-lexical-form uri)267 (format nil "odbc:~@[~a~]//~:[~5*~;~:[~2*~;~@[~a~]:~@[~a~]@~]~@[~a~]~@[:~a~]~]/~@[~a~]/~@[~a~]~@[?~a~]"268 driver269 (or user password authority port) (or user password)270 user password authority port271 database table query))))))272 273 (defgeneric spocq.i::odbc-uri (value)274 (:method ((lexical-form cl:string))275 (multiple-value-bind (initargs lexical-form) (spocq:parse-odbc-uri lexical-form)276 (apply #'spocq:make-odbc-uri :lexical-form lexical-form initargs)))277 (:method ((uri spocq:odbc-uri))278 (ensure-iri-lexical-form uri)))279 280 ;;; postgres281 282 (defparameter *postgresql-uri-scanner*283 (cl-ppcre:create-scanner `(:sequence :start-anchor284 (:sequence "postgresql://"285 (:greedy-repetition286 0 1287 (:sequence288 (:greedy-repetition289 0 1290 (:sequence291 (:greedy-repetition 0 1292 (:register293 (:greedy-repetition 1 nil (:inverted-char-class #\:))))294 ":"295 (:greedy-repetition 0 1296 (:register297 (:greedy-repetition 1 nil (:inverted-char-class #\@))))298 "@"))299 (:greedy-repetition 0 1300 (:register301 (:greedy-repetition 1 nil (:inverted-char-class #\: #\/))))302 (:greedy-repetition 0 1303 (:sequence ":"304 (:register305 (:greedy-repetition 1 nil (:inverted-char-class #\/)))))))306 "/"307 (:greedy-repetition 0 1308 (:register309 (:greedy-repetition 1 nil (:inverted-char-class #\?))))310 (:greedy-repetition311 0 1312 (:sequence313 "?"314 (:greedy-repetition 0 1315 (:register316 (:greedy-repetition 1 nil :everything)))317 )))318 :end-anchor)))319 320 (defun parse-postgresql-uri (value)321 (multiple-value-bind (whole strings)322 (cl-ppcre:scan-to-strings *postgresql-uri-scanner* value)323 (if whole324 (values (loop for i from 0 for property in '(:user :password :authority :port :database :parameters)325 for value = (aref strings i)326 when value327 append (list property (case property328 (:parameters (loop for assignment in (dsu:split-string value #\&)329 for (key value) = (dsu:split-string assignment #\=)330 collect (cons (dsu:cons-symbol :keyword key) value)))331 (t value))))332 whole)333 (error "Invalid postgres uri lexical form: ~s" value))))334 335 ;;; (parse-postgresql-uri "postgresql://postgres:postgres@localhost/test" )336 ;;; (parse-postgresql-uri "postgresql://postgres:postgres@localhost/test?table=events&encoding=utf-8" )337 338 (defmethod ensure-iri-lexical-form ((uri postgresql-uri))339 (let ((value (postgresql-uri-lexical-form uri)))340 (if (plusp (length value))341 value342 (let ((user (postgresql-uri-user uri))343 (password (postgresql-uri-password uri))344 (authority (postgresql-uri-authority uri))345 (port (postgresql-uri-port uri))346 (database (postgresql-uri-database uri))347 (parameters (postgresql-uri-parameters uri)))348 (setf (spocq::postgresql-uri-lexical-form uri)349 (format nil "postgresql://~:[~5*~;~:[~2*~;~@[~a~]:~@[~a~]@~]~@[~a~]~@[:~a~]~]/~@[~a~]~@[?~{~a=~a~^&~}~]"350 (or user password authority port) (or user password)351 user password authority port352 database353 (loop for (key . value) in parameters354 collect (string-downcase key)355 collect value)))))))356 357 (defgeneric spocq.i::postgresql-uri (value)358 (:method ((lexical-form cl:string))359 (multiple-value-bind (initargs lexical-form) (spocq:parse-postgresql-uri lexical-form)360 (apply #'spocq:make-postgresql-uri :lexical-form lexical-form initargs)))361 (:method ((uri spocq:postgresql-uri))362 (ensure-iri-lexical-form uri)))363 364 (defgeneric postgresql-uri-schema (uri)365 (:method ((uri postgresql-uri))366 (rest (assoc :schema (postgresql-uri-parameters uri)))))367 368 369 (defmethod spocq.i::iri-lexical-form ((uri sql-uri))370 (ensure-iri-lexical-form uri))371 372 (defmethod spocq.i::parse-uri-by-scheme ((type (eql :mysql)) string)373 (spocq.i::mysql-uri string))374 (defmethod spocq.i::parse-uri-by-scheme ((type (eql :odbc)) string)375 (spocq.i::odbc-uri string))376 (defmethod spocq.i::parse-uri-by-scheme ((type (eql :postgresql)) string)377 (spocq.i::postgresql-uri string))378 379 (defmethod spocq.i::construct-uri-term ((scheme (eql :mysql)) lexical-form)380 (spocq.i::mysql-uri lexical-form))381 (defmethod spocq.i::construct-uri-term ((scheme (eql :odbc)) lexical-form)382 (spocq.i::odbc-uri lexical-form))383 (defmethod spocq.i::construct-uri-term ((scheme (eql :postgresql)) lexical-form)384 (spocq.i::postgresql-uri lexical-form))385 386 ;;; (parse-odbc-uri "odbc://:@:/postgresdb/aTable?")387 ;;; (parse-odbc-uri "odbc:Postgres64////aTable")388 ;;; (parse-odbc-uri "odbc://user:password@localhost:0000/postgresdb/aTable?")389 ;;; (parse-odbc-uri "odbc://localhost:0000/postgresdb/aTable?")390 ;;; (parse-odbc-uri "odbc://localhost/postgresdb/aTable?")391 392 ;;; (spocq.i::odbc-uri "odbc://localhost:0000/postgresdb/aTable?")393 394 (defgeneric spocq.i::merge-sql-uri (uri1 uri2)395 (:method ((uri1 cl:string) (uri2 t))396 (spocq.i::merge-sql-uri (spocq.i::sql-uri uri1) uri2))397 (:method ((uri1 t) (uri2 cl:string))398 (spocq.i::merge-sql-uri uri1 (spocq.i::sql-uri uri2)))399 400 (:method ((uri1 list) (uri2 mysql-uri))401 (spocq.i::merge-sql-uri (apply #'make-mysql-uri uri1) uri2))402 (:method ((uri1 mysql-uri) (uri2 list))403 (spocq.i::merge-sql-uri uri1 (apply #'make-mysql-uri uri2)))404 405 (:method ((uri1 list) (uri2 odbc-uri))406 (spocq.i::merge-sql-uri (apply #'make-odbc-uri uri1) uri2))407 (:method ((uri1 odbc-uri) (uri2 list))408 (spocq.i::merge-sql-uri uri1 (apply #'make-odbc-uri uri2)))409 410 (:method ((uri1 list) (uri2 postgresql-uri))411 (spocq.i::merge-sql-uri (apply #'make-postgresql-uri uri1) uri2))412 (:method ((uri1 postgresql-uri) (uri2 list))413 (spocq.i::merge-sql-uri uri1 (apply #'make-postgresql-uri uri2)))414 415 (:method ((uri1 odbc-uri) (uri2 odbc-uri))416 (let ((driver (or (odbc-uri-driver uri1) (odbc-uri-driver uri2)))417 (user (or (odbc-uri-user uri1) (odbc-uri-user uri2)))418 (password (or (odbc-uri-password uri1) (odbc-uri-password uri2)))419 (authority (or (odbc-uri-authority uri1) (odbc-uri-authority uri2)))420 (port (or (odbc-uri-port uri1) (odbc-uri-port uri2)))421 (database (or (odbc-uri-database uri1) (odbc-uri-database uri2)))422 (table (or (odbc-uri-table uri1) (odbc-uri-table uri2)))423 (query (or (odbc-uri-query uri1) (odbc-uri-query uri2))))424 (make-odbc-uri :lexical-form ""425 :driver driver426 :user user427 :password password428 :authority authority429 :port port430 :database database431 :table table432 :query query)))433 (:method ((uri1 postgresql-uri) (uri2 postgresql-uri))434 (let ((user (or (postgresql-uri-user uri1) (postgresql-uri-user uri2)))435 (password (or (postgresql-uri-password uri1) (postgresql-uri-password uri2)))436 (authority (or (postgresql-uri-authority uri1) (postgresql-uri-authority uri2)))437 (port (or (postgresql-uri-port uri1) (postgresql-uri-port uri2)))438 (database (or (postgresql-uri-database uri1) (postgresql-uri-database uri2)))439 (parameters (remove-duplicates (append (postgresql-uri-parameters uri1)440 (postgresql-uri-parameters uri2))441 :key #'first :from-end t)))442 (make-postgresql-uri :lexical-form ""443 :user user444 :password password445 :authority authority446 :port port447 :database database448 :parameters parameters))))449 450 ;;; (spocq.i::merge-sql-uri "odbc:Postgres64////aTable" "odbc://localhost:0000/postgresdb/?")451 ;;; (spocq.i::merge-sql-uri "odbc:Postgres64////aTable" '(:table "test"))452 ;;; (spocq.i::merge-sql-uri '(:table "test") "odbc:Postgres64///adatabase/aTable")453 ;;; (spocq.i::merge-sql-uri '(:table "test") "postgresql:///adatabase/")454 455