cl-sql-6.4.1/0000755000175000017500000000000012134026703011725 5ustar kevinkevincl-sql-6.4.1/clsql-sqlite.asd0000644000175000017500000000260511332141035015031 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; FILE IDENTIFICATION ;;;; ;;;; Name: clsql-sqlite.asd ;;;; Purpose: ASDF file for CLSQL SQLite backend ;;;; Programmer: Aurelio Bignoli ;;;; Date Started: Aug 2003 ;;;; ;;;; This file, part of CLSQL, is Copyright (c) 2003 by Aurelio Bignoli ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* (defpackage #:clsql-sqlite-system (:use #:asdf #:cl)) (in-package #:clsql-sqlite-system) (defsystem clsql-sqlite :name "cl-sql-sqlite" :author "Aurelio Bignoli " :maintainer "Aurelio Bignoli" :licence "Lessor Lisp General Public License" :description "Common Lisp SQLite Driver" :long-description "cl-sql-sqlite package provides a database driver to SQLite database library." :depends-on (clsql clsql-uffi) :components ((:module :db-sqlite :components ((:file "sqlite-package") (:file "sqlite-loader" :depends-on ("sqlite-package")) (:file "sqlite-api" :depends-on ("sqlite-loader")) (:file "sqlite-sql" :depends-on ("sqlite-api")))))) cl-sql-6.4.1/clsql-sqlite3.asd0000644000175000017500000000264011332141035015113 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; FILE IDENTIFICATION ;;;; ;;;; Name: clsql-sqlite3.asd ;;;; Purpose: ASDF file for CLSQL SQLite3 backend ;;;; Programmer: Aurelio Bignoli ;;;; Date Started: Oct 2004 ;;;; ;;;; This file, part of CLSQL, is Copyright (c) 2004 by Aurelio Bignoli ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* (defpackage #:clsql-sqlite3-system (:use #:asdf #:cl)) (in-package #:clsql-sqlite3-system) (defsystem clsql-sqlite3 :name "cl-sql-sqlite3" :author "Aurelio Bignoli " :maintainer "Aurelio Bignoli" :licence "Lessor Lisp General Public License" :description "Common Lisp Sqlite3 Driver" :long-description "cl-sql-sqlite3 package provides a database driver to SQLite Versione 3 database library." :depends-on (clsql clsql-uffi) :components ((:module :db-sqlite3 :components ((:file "sqlite3-package") (:file "sqlite3-loader" :depends-on ("sqlite3-package")) (:file "sqlite3-api" :depends-on ("sqlite3-loader")) (:file "sqlite3-sql" :depends-on ("sqlite3-api")))))) cl-sql-6.4.1/db-sqlite3/0000755000175000017500000000000012134026703013674 5ustar kevinkevincl-sql-6.4.1/db-sqlite3/sqlite3-api.lisp0000644000175000017500000003137112021503403016715 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; FILE IDENTIFICATION ;;;; ;;;; Name: sqlite3-api.lisp ;;;; Purpose: Low-level SQLite3 interface using UFFI ;;;; Authors: Aurelio Bignoli ;;;; Created: Oct 2004 ;;;; ;;;; This file, part of CLSQL, is Copyright (c) 2004 by Aurelio Bignoli ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* (in-package #:cl-user) (defpackage #:sqlite3 (:use #:common-lisp #:uffi) (:export ;;; Conditions #:sqlite3-error #:sqlite3-error-code #:sqlite3-error-message ;;; API functions. #:sqlite3-open #:sqlite3-close #:sqlite3-prepare #:sqlite3-step #:sqlite3-finalize #:sqlite3-column-count #:sqlite3-column-name #:sqlite3-column-type #:sqlite3-column-text #:sqlite3-column-bytes #:sqlite3-column-blob ;;; Types. #:sqlite3-db #:sqlite3-db-type #:sqlite3-stmt-type #:unsigned-char-ptr-type #:null-stmt ;;; Columnt types. #:SQLITE-INTEGER #:SQLITE-FLOAT #:SQLITE-TEXT #:SQLITE-BLOB #:SQLITE-NULL)) (in-package #:sqlite3) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;; ;;;; Return values for sqlite_exec() and sqlite_step() ;;;; (defconstant SQLITE-OK 0 "Successful result") (defconstant SQLITE-ERROR 1 "SQL error or missing database") (defconstant SQLITE-INTERNAL 2 "An internal logic error in SQLite") (defconstant SQLITE-PERM 3 "Access permission denied") (defconstant SQLITE-ABORT 4 "Callback routine requested an abort") (defconstant SQLITE-BUSY 5 "The database file is locked") (defconstant SQLITE-LOCKED 6 "A table in the database is locked") (defconstant SQLITE-NOMEM 7 "A malloc() failed") (defconstant SQLITE-READONLY 8 "Attempt to write a readonly database") (defconstant SQLITE-INTERRUPT 9 "Operation terminated by sqlite3_interrupt()") (defconstant SQLITE-IOERR 10 "Some kind of disk I/O error occurred") (defconstant SQLITE-CORRUPT 11 "The database disk image is malformed") (defconstant SQLITE-NOTFOUND 12 "(Internal Only) Table or record not found") (defconstant SQLITE-FULL 13 "Insertion failed because database is full") (defconstant SQLITE-CANTOPEN 14 "Unable to open the database file") (defconstant SQLITE-PROTOCOL 15 "Database lock protocol error") (defconstant SQLITE-EMPTY 16 "Database is empty") (defconstant SQLITE-SCHEMA 17 "The database schema changed") (defconstant SQLITE-TOOBIG 18 "Too much data for one row of a table") (defconstant SQLITE-CONSTRAINT 19 "Abort due to contraint violation") (defconstant SQLITE-MISMATCH 20 "Data type mismatch") (defconstant SQLITE-MISUSE 21 "Library used incorrectly") (defconstant SQLITE-NOLFS 22 "Uses OS features not supported on host") (defconstant SQLITE-AUTH 23 "Authorization denied") (defconstant SQLITE-FORMAT 24 "Auxiliary database format error") (defconstant SQLITE-RANGE 25 "2nd parameter to sqlite3_bind out of range") (defconstant SQLITE-NOTADB 26 "File opened that is not a database file") (defconstant SQLITE-ROW 100 "sqlite3_step() has another row ready") (defconstant SQLITE-DONE 101 "sqlite3_step() has finished executing") (defparameter error-codes (list (cons SQLITE-OK "not an error") (cons SQLITE-ERROR "SQL logic error or missing database") (cons SQLITE-INTERNAL "internal SQLite implementation flaw") (cons SQLITE-PERM "access permission denied") (cons SQLITE-ABORT "callback requested query abort") (cons SQLITE-BUSY "database is locked") (cons SQLITE-LOCKED "database table is locked") (cons SQLITE-NOMEM "out of memory") (cons SQLITE-READONLY "attempt to write a readonly database") (cons SQLITE-INTERRUPT "interrupted") (cons SQLITE-IOERR "disk I/O error") (cons SQLITE-CORRUPT "database disk image is malformed") (cons SQLITE-NOTFOUND "table or record not found") (cons SQLITE-FULL "database is full") (cons SQLITE-CANTOPEN "unable to open database file") (cons SQLITE-PROTOCOL "database locking protocol failure") (cons SQLITE-EMPTY "table contains no data") (cons SQLITE-SCHEMA "database schema has changed") (cons SQLITE-TOOBIG "too much data for one table row") (cons SQLITE-CONSTRAINT "constraint failed") (cons SQLITE-MISMATCH "datatype mismatch") (cons SQLITE-MISUSE "library routine called out of sequence") (cons SQLITE-NOLFS "kernel lacks large file support") (cons SQLITE-AUTH "authorization denied") (cons SQLITE-FORMAT "auxiliary database format error") (cons SQLITE-RANGE "bind index out of range") (cons SQLITE-NOTADB "file is encrypted or is not a database")) "Association list of error messages.") ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;; ;;;; Column types. ;;;; (defconstant SQLITE-INTEGER 1) (defconstant SQLITE-FLOAT 2) (defconstant SQLITE-TEXT 3) (defconstant SQLITE-BLOB 4) (defconstant SQLITE-NULL 5) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;; ;;;; Foreign types definitions. ;;;; (def-foreign-type sqlite3-db :pointer-void) (def-foreign-type sqlite3-stmt :pointer-void) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;; ;;;; Lisp types definitions. ;;;; (def-type sqlite3-db-type sqlite3-db) (def-type sqlite3-db-ptr-type (* sqlite3-db)) (def-type sqlite3-stmt-type sqlite3-stmt) (def-type sqlite3-stmt-ptr-type (* sqlite3-stmt)) (def-type unsigned-char-ptr-type (* :unsigned-char)) (defparameter null-stmt (make-null-pointer :void)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; ;;; Hash tables for db and statement pointers. ;;; (defvar *db-pointers* (make-hash-table)) (defvar *stmt-pointers* (make-hash-table)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;; ;;;; Conditions. ;;;; (define-condition sqlite3-error () ((message :initarg :message :reader sqlite3-error-message :initform "") (code :initarg :code :reader sqlite3-error-code)) (:report (lambda (condition stream) (format stream "Sqlite3 error [~A]: ~A" (sqlite3-error-code condition) (sqlite3-error-message condition))))) (defgeneric signal-sqlite3-error (db)) (defmethod signal-sqlite3-error (db) (let ((condition (make-condition 'sqlite3-error :code (sqlite3-errcode db) :message (convert-from-cstring (sqlite3-errmsg db))))) (unless (signal condition) (invoke-debugger condition)))) (defmethod signal-sqlite3-error ((code number)) (let ((condition (make-condition 'sqlite3-error :code code :message (let ((s (cdr (assoc code error-codes)))) (if s s "unknown error"))))) (unless (signal condition) (invoke-debugger condition)))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;; ;;;; Library functions. ;;;; (defmacro def-sqlite3-function (name args &key (returning :void)) `(def-function ,name ,args :module "sqlite3" :returning ,returning)) (declaim (inline %errcode)) (def-sqlite3-function "sqlite3_errcode" ((db sqlite3-db)) :returning :int) (declaim (inline %errmsg)) (def-sqlite3-function "sqlite3_errmsg" ((db sqlite3-db)) :returning :cstring) (declaim (inline %open)) (def-sqlite3-function ("sqlite3_open" %open) ((dbname :cstring) (db (* sqlite3-db))) :returning :int) (declaim (inline %close)) (def-sqlite3-function ("sqlite3_close" %close) ((db sqlite3-db)) :returning :int) (declaim (inline %prepare)) (def-sqlite3-function ("sqlite3_prepare" %prepare) ((db sqlite3-db) (sql :cstring) (len :int) (stmt (* sqlite3-stmt)) (sql-tail (* (* :unsigned-char)))) :returning :int) (declaim (inline %step)) (def-sqlite3-function ("sqlite3_step" %step) ((stmt sqlite3-stmt)) :returning :int) (declaim (inline %finalize)) (def-sqlite3-function ("sqlite3_finalize" %finalize) ((stmt sqlite3-stmt)) :returning :int) (declaim (inline sqlite3-column-count)) (def-sqlite3-function "sqlite3_column_count" ((stmt sqlite3-stmt)) :returning :int) (declaim (inline %column-name)) (def-sqlite3-function ("sqlite3_column_name" %column-name) ((stmt sqlite3-stmt) (n-col :int)) :returning :cstring) (declaim (inline sqlite3-column-type)) (def-sqlite3-function "sqlite3_column_type" ((stmt sqlite3-stmt) (n-col :int)) :returning :int) (declaim (inline sqlite3-column-text)) (def-sqlite3-function "sqlite3_column_text" ((stmt sqlite3-stmt) (n-col :int)) :returning (* :unsigned-char)) (declaim (inline sqlite3-column-bytes)) (def-sqlite3-function "sqlite3_column_bytes" ((stmt sqlite3-stmt) (n-col :int)) :returning :int) (declaim (inline sqlite3-column-blob)) (def-sqlite3-function "sqlite3_column_blob" ((stmt sqlite3-stmt) (n-col :int)) :returning :pointer-void) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;; ;;;; wrapper functions. ;;;; (defun sqlite3-open (db &optional (mode 0) &aux (db-name (etypecase db (pathname (namestring db)) (string db)))) (declare (ignore mode) (type string db-name)) (let ((dbp (allocate-foreign-object 'sqlite3-db))) (declare (type sqlite3-db-ptr-type dbp)) (with-cstring (db-name-native db-name) (let ((result (%open db-name-native dbp))) (if (/= result 0) (progn ;; According to docs, the db must be closed even in case ;; of error. (%close (deref-pointer dbp 'sqlite3-db)) (free-foreign-object dbp) (signal-sqlite3-error result)) (let ((db (deref-pointer dbp 'sqlite3-db))) (declare (type sqlite3-db-type db)) (setf (gethash db *db-pointers*) dbp) db)))))) (declaim (ftype (function (sqlite3-db-type) t) sqlite3-close)) (defun sqlite3-close (db) (declare (type sqlite3-db-type db)) (let ((result (%close db))) (if (/= result 0) (signal-sqlite3-error result) (progn (free-foreign-object (gethash db *db-pointers*)) (remhash db *db-pointers*) t)))) (declaim (ftype (function (sqlite3-db-type string) sqlite3-stmt-type) sqlite3-prepare)) (defun sqlite3-prepare (db sql) (declare (type sqlite3-db-type db)) (with-cstring (sql-native sql) (let ((stmtp (allocate-foreign-object 'sqlite3-stmt))) (declare (type sqlite3-stmt-ptr-type stmtp)) (with-foreign-object (sql-tail '(* :unsigned-char)) (let ((result (%prepare db sql-native -1 stmtp sql-tail))) (if (/= result SQLITE-OK) (progn (unless (null-pointer-p stmtp) ;; There is an error, but a statement has been allocated: ;; finalize it (better safe than sorry). (%finalize (deref-pointer stmtp 'sqlite3-stmt))) (free-foreign-object stmtp) (signal-sqlite3-error db)) (let ((stmt (deref-pointer stmtp 'sqlite3-stmt))) (declare (type sqlite3-stmt-type stmt)) (setf (gethash stmt *stmt-pointers*) stmtp) stmt))))))) (declaim (ftype (function (sqlite3-stmt-type) t) sqlite3-step)) (defun sqlite3-step (stmt) (declare (type sqlite3-stmt-type stmt)) (let ((result (%step stmt))) (cond ((= result SQLITE-ROW) t) ((= result SQLITE-DONE) nil) (t (signal-sqlite3-error result))))) (declaim (ftype (function (sqlite3-stmt-type) t) sqlite3-finalize)) (defun sqlite3-finalize (stmt) (declare (type sqlite3-stmt-type stmt)) (let ((result (%finalize stmt))) (if (/= result SQLITE-OK) (signal-sqlite3-error result) (progn (free-foreign-object (gethash stmt *stmt-pointers*)) (remhash stmt *stmt-pointers*) t)))) (declaim (inline sqlite3-column-name)) (defun sqlite3-column-name (stmt n) (declare (type sqlite3-stmt-type stmt) (type fixnum n)) (convert-from-cstring (%column-name stmt n))) cl-sql-6.4.1/db-sqlite3/sqlite3-loader.lisp0000644000175000017500000000315111335067642017426 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; FILE IDENTIFICATION ;;;; ;;;; Name: sqlite3-loader.lisp ;;;; Purpose: Sqlite3 library loader using UFFI ;;;; Programmer: Aurelio Bignoli ;;;; Date Started: Oct 2004 ;;;; ;;;; This file, part of CLSQL, is Copyright (c) 2004 by Aurelio Bignoli ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* (in-package #:clsql-sqlite3) (defvar *sqlite3-supporting-libraries* '("c") "Used only by CMU. List of library flags needed to be passed to ld to load the Sqlite3 library succesfully. If this differs at your site, set to the right path before compiling or loading the system.") (defvar *sqlite3-library-loaded* nil "T if foreign library was able to be loaded successfully") (defmethod database-type-library-loaded ((database-type (eql :sqlite3))) "T if foreign library was able to be loaded successfully. " *sqlite3-library-loaded*) (defmethod database-type-load-foreign ((database-type (eql :sqlite3))) (clsql-uffi:find-and-load-foreign-library '("libsqlite3" "sqlite3") :module "sqlite3" :supporting-libraries *sqlite3-supporting-libraries*) (setq *sqlite3-library-loaded* t)) (clsql-sys:database-type-load-foreign :sqlite3) cl-sql-6.4.1/db-sqlite3/sqlite3-package.lisp0000644000175000017500000000151511335067642017555 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; FILE IDENTIFICATION ;;;; ;;;; Name: sqlite-package.lisp ;;;; Purpose: Package definition for low-level SQLite3 interface ;;;; Programmer: Aurelio Bignoli ;;;; Date Started: Oct 2004 ;;;; ;;;; This file, part of CLSQL, is Copyright (c) 2004 by Aurelio Bignoli ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* (in-package #:cl-user) (defpackage #:clsql-sqlite3 (:use #:common-lisp #:clsql-sys) (:export #:sqlite3-database)) cl-sql-6.4.1/db-sqlite3/sqlite3-sql.lisp0000644000175000017500000003440212021503403016741 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; FILE IDENTIFICATION ;;;; ;;;; Name: sqlite-sql.lisp ;;;; Purpose: High-level SQLite3 interface ;;;; Authors: Aurelio Bignoli & Kevin Rosenberg ;;;; Created: Oct 2004 ;;;; ;;;; This file, part of CLSQL, is Copyright (c) 2004-2010 by Aurelio Bignoli & Kevin Rosenberg ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* (in-package #:clsql-sqlite3) (defclass sqlite3-database (database) ((sqlite3-db :initarg :sqlite3-db :accessor sqlite3-db))) (defmethod database-type ((database sqlite3-database)) :sqlite3) (defmethod database-initialize-database-type ((database-type (eql :sqlite3))) t) (defun check-sqlite3-connection-spec (connection-spec) (check-connection-spec connection-spec :sqlite3 (name &optional init-foreign-func))) (defmethod database-name-from-spec (connection-spec (database-type (eql :sqlite3))) (check-sqlite3-connection-spec connection-spec) (princ-to-string (first connection-spec))) (defmethod database-connect (connection-spec (database-type (eql :sqlite3))) (check-sqlite3-connection-spec connection-spec) (handler-case (let ((db (sqlite3:sqlite3-open (first connection-spec))) (init-foreign-func (second connection-spec))) (declare (type sqlite3:sqlite3-db-type db)) (when init-foreign-func (handler-case (funcall init-foreign-func db) (condition (c) (progn (sqlite3:sqlite3-close db) (error c))))) (make-instance 'sqlite3-database :name (database-name-from-spec connection-spec :sqlite3) :database-type :sqlite3 :connection-spec connection-spec :sqlite3-db db)) (sqlite3:sqlite3-error (err) (error 'sql-connection-error :database-type database-type :connection-spec connection-spec :error-id (sqlite3:sqlite3-error-code err) :message (sqlite3:sqlite3-error-message err))))) (defmethod database-disconnect ((database sqlite3-database)) (sqlite3:sqlite3-close (sqlite3-db database)) (setf (sqlite3-db database) nil) t) (defmethod database-execute-command (sql-expression (database sqlite3-database)) (handler-case (let ((stmt (sqlite3:sqlite3-prepare (sqlite3-db database) sql-expression))) (declare (type sqlite3:sqlite3-stmt-type stmt)) (when stmt (unwind-protect (sqlite3:sqlite3-step stmt) (sqlite3:sqlite3-finalize stmt)))) (sqlite3:sqlite3-error (err) (error 'sql-database-data-error :database database :expression sql-expression :error-id (sqlite3:sqlite3-error-code err) :message (sqlite3:sqlite3-error-message err)))) t) (defstruct sqlite3-result-set (stmt sqlite3:null-stmt :type sqlite3:sqlite3-stmt-type) (n-col 0 :type fixnum) (col-names '()) (result-types '())) (declaim (ftype (function (sqlite3:sqlite3-stmt-type fixnum t) list) get-result-types)) (defun get-result-types (stmt n-col result-types) (declare (type sqlite3:sqlite3-stmt-type stmt) (type fixnum n-col)) (if (eq :auto result-types) (loop for n from 0 below n-col collect (let ((column-type (sqlite3:sqlite3-column-type stmt n))) (cond ((= column-type sqlite3:SQLITE-INTEGER) :int64) ((= column-type sqlite3:SQLITE-FLOAT) :double) ((= column-type sqlite3:SQLITE-TEXT) :string) ((= column-type sqlite3:SQLITE-BLOB) :blob) ((= column-type sqlite3:SQLITE-NULL) :string) (t :string)))) (loop for type in result-types collect (case type ((:int :integer :tinyint) :int32) (:long #+(or x86-64 64bit) :int64 #-(or x86-64 64bit) :int32) (:bigint :int64) ((:float :double) :double) ((:numeric) :number) (otherwise :string))))) (defmethod database-query-result-set ((query-expression string) (database sqlite3-database) &key result-types full-set) (let ((stmt sqlite3:null-stmt)) (declare (type sqlite3:sqlite3-stmt-type stmt)) (handler-case (progn (setf stmt (sqlite3:sqlite3-prepare (sqlite3-db database) query-expression)) (let* ((n-col (if (sqlite3:sqlite3-step stmt) ;; Non empty result set. (sqlite3:sqlite3-column-count stmt) ;; Empty result set. 0)) (result-set (make-sqlite3-result-set :stmt stmt :n-col n-col :col-names (loop for n from 0 below n-col collect (sqlite3:sqlite3-column-name stmt n)) :result-types (when (> n-col 0) (get-result-types stmt n-col result-types))))) (if full-set (values result-set n-col nil) (values result-set n-col)))) (sqlite3:sqlite3-error (err) (progn (unless (eq stmt sqlite3:null-stmt) (ignore-errors (sqlite3:sqlite3-finalize stmt))) (error 'sql-database-data-error :database database :expression query-expression :error-id (sqlite3:sqlite3-error-code err) :message (sqlite3:sqlite3-error-message err))))))) (defmethod database-dump-result-set (result-set (database sqlite3-database)) (handler-case (sqlite3:sqlite3-finalize (sqlite3-result-set-stmt result-set)) (sqlite3:sqlite3-error (err) (error 'sql-database-error :message (format nil "Error finalizing SQLite3 statement: ~A" (sqlite3:sqlite3-error-message err)))))) (defmethod database-store-next-row (result-set (database sqlite3-database) list) (let ((n-col (sqlite3-result-set-n-col result-set))) (if (= n-col 0) ;; empty result set. nil ;; Non-empty set. (let ((stmt (sqlite3-result-set-stmt result-set))) (declare (type sqlite3:sqlite3-stmt-type stmt)) ;; Store row in list. (loop for i = 0 then (1+ i) for rest on list for types = (sqlite3-result-set-result-types result-set) then (rest types) do (setf (car rest) (if (eq (first types) :blob) (clsql-uffi:convert-raw-field (sqlite3:sqlite3-column-blob stmt i) (car types) :length (sqlite3:sqlite3-column-bytes stmt i) :encoding (encoding database)) (clsql-uffi:convert-raw-field (sqlite3:sqlite3-column-text stmt i) (car types) :encoding (encoding database))))) ;; Advance result set cursor. (handler-case (unless (sqlite3:sqlite3-step stmt) (setf (sqlite3-result-set-n-col result-set) 0)) (sqlite3:sqlite3-error (err) (error 'sql-database-error :message (format nil "Error in sqlite3-step: ~A" (sqlite3:sqlite3-error-message err))))) t)))) (defmethod database-query (query-expression (database sqlite3-database) result-types field-names) (declare (optimize (speed 3) (safety 0) (debug 0) (space 0))) (handler-case (let ((stmt (sqlite3:sqlite3-prepare (sqlite3-db database) query-expression)) (rows '()) (col-names '())) (declare (type sqlite3:sqlite3-stmt-type stmt)) (unwind-protect (when (sqlite3:sqlite3-step stmt) (let ((n-col (sqlite3:sqlite3-column-count stmt))) (flet ((extract-row-data () (loop for i from 0 below n-col for types = (get-result-types stmt n-col result-types) then (rest types) collect (if (eq (first types) :blob) (clsql-uffi:convert-raw-field (sqlite3:sqlite3-column-blob stmt i) (car types) :length (sqlite3:sqlite3-column-bytes stmt i) :encoding (encoding database)) (clsql-uffi:convert-raw-field (sqlite3:sqlite3-column-text stmt i) (car types) :encoding (encoding database)))))) (when field-names (setf col-names (loop for n from 0 below n-col collect (sqlite3:sqlite3-column-name stmt n)))) (push (extract-row-data) rows) (do* () (nil) (if (sqlite3:sqlite3-step stmt) (push (extract-row-data) rows) (return)))))) (sqlite3:sqlite3-finalize stmt)) (values (nreverse rows) col-names)) (sqlite3:sqlite3-error (err) (error 'sql-database-data-error :database database :expression query-expression :error-id (sqlite3:sqlite3-error-code err) :message (sqlite3:sqlite3-error-message err))))) ;;; Object listing (defmethod database-list-tables-and-sequences ((database sqlite3-database) &key owner) (declare (ignore owner)) ;; Query is copied from .table command of sqlite3 command line utility. (mapcar #'car (database-query "SELECT name FROM sqlite_master WHERE type='table' UNION ALL SELECT name FROM sqlite_temp_master WHERE type='table' ORDER BY name" database nil nil))) (defmethod database-list-tables ((database sqlite3-database) &key owner) (remove-if #'(lambda (s) (and (>= (length s) 11) (string-equal (subseq s 0 11) "_CLSQL_SEQ_"))) (database-list-tables-and-sequences database :owner owner))) (defmethod database-list-views ((database sqlite3-database) &key (owner nil)) (declare (ignore owner)) (mapcar #'car (database-query "SELECT name FROM sqlite_master WHERE type='view' UNION ALL SELECT name FROM sqlite_temp_master WHERE type='view' ORDER BY name" database nil nil))) (defmethod database-list-indexes ((database sqlite3-database) &key (owner nil)) (declare (ignore owner)) (mapcar #'car (database-query "SELECT name FROM sqlite_master WHERE type='index' UNION ALL SELECT name FROM sqlite_temp_master WHERE type='index' ORDER BY name" database nil nil))) (defmethod database-list-table-indexes (table (database sqlite3-database) &key (owner nil)) (declare (ignore owner)) (let ((*print-circle* nil)) (mapcar #'car (database-query (format nil "SELECT name FROM sqlite_master WHERE type='index' AND tbl_name='~A' UNION ALL SELECT name FROM sqlite_temp_master WHERE type='index' AND tbl_name='~A' ORDER BY name" table table) database nil nil)))) (declaim (inline sqlite3-table-info)) (defun sqlite3-table-info (table database) (database-query (format nil "PRAGMA table_info('~A')" table) database nil nil)) (defmethod database-list-attributes (table (database sqlite3-database) &key (owner nil)) (declare (ignore owner)) (mapcar #'(lambda (table-info) (second table-info)) (sqlite3-table-info table database))) (defmethod database-attribute-type (attribute table (database sqlite3-database) &key (owner nil)) (declare (ignore owner)) (loop for field-info in (sqlite3-table-info table database) when (string= attribute (second field-info)) return (let* ((raw-type (third field-info)) (start-length (position #\( raw-type)) (type (string-trim clsql-sys::+whitespace-chars+ (if start-length (subseq raw-type 0 start-length) raw-type))) (length (if start-length (parse-integer (subseq raw-type (1+ start-length)) :junk-allowed t) nil))) (values (when type (ensure-keyword type)) length nil (if (string-equal (fourth field-info) "0") 1 0))))) (defmethod database-create (connection-spec (type (eql :sqlite3))) (declare (ignore connection-spec)) ;; databases are created automatically by Sqlite3 t) (defmethod database-destroy (connection-spec (type (eql :sqlite3))) (destructuring-bind (name) connection-spec (if (probe-file name) (delete-file name) nil))) (defmethod database-probe (connection-spec (type (eql :sqlite3))) (destructuring-bind (name) connection-spec ;; TODO: Add a test that this file is a real sqlite3 database (or (string-equal ":memory:" name) (and (probe-file name) t)))) ;;; Database capabilities (defmethod db-type-has-boolean-where? ((db-type (eql :sqlite3))) nil) cl-sql-6.4.1/db-odbc/0000755000175000017500000000000012134026703013217 5ustar kevinkevincl-sql-6.4.1/db-odbc/odbc-dbi.lisp0000644000175000017500000007372111725170505015572 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; FILE IDENTIFICATION ;;;; ;;;; Name: odbc-dbi.cl ;;;; Purpose: Mid-level (DBI) interface for CLSQL ODBC backend ;;;; Author: Kevin M. Rosenberg ;;;; Create: April 2004 ;;;; ;;;; This file, part of CLSQL, is Copyright (c) 2002 by Kevin M. Rosenberg ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* (in-package #:cl-user) (defpackage #:odbc-dbi (:use #:cl #:odbc) (:export #:bind-parameter #:close-query #:connect #:db-external-format #:db-hstmt #:db-width #:disconnect #:end-transaction #:fetch-row #:list-all-data-sources #:list-all-database-tables #:list-all-table-columns #:list-table-indexes #:loop-over-results #:prepare-sql #:rr-sql #:run-prepared-sql #:set-autocommit #:sql #:*auto-trim-strings* #:*default-database* #:*default-odbc-external-format* #:*null-value* ) (:documentation "This is the mid-level interface ODBC.")) (in-package #:odbc-dbi) (defgeneric terminate (src)) (defgeneric db-open-query (src query-expression &key arglen col-positions result-types width &allow-other-keys)) (defgeneric db-fetch-query-results (src &optional count)) (defgeneric %db-execute (src sql-expression &key &allow-other-keys)) (defgeneric db-execute-command (src sql-string)) (defgeneric %initialize-query (src arglen col-positions &key result-types width)) (defgeneric %read-query-data (src ignore-columns)) (defgeneric db-map-query (src type function query-exp &key result-types)) (defgeneric db-prepare-statement (src sql &key parameter-table parameter-columns)) (defgeneric get-odbc-info (src info-type)) (defvar *reuse-query-objects* t) ;;; SQL Interface (defclass odbc-db () (;; any reason to have more than one henv? (width :initform +max-precision+ :accessor db-width) (hstmt :initform nil :accessor db-hstmt) (henv :initform nil :allocation :class :initarg :henv :accessor henv) (hdbc :initform nil :initarg :hdbc :accessor hdbc) ;; info returned from SQLGetInfo (info :initform (make-hash-table) :reader db-info) (type :initform nil :initarg :db-type :reader db-type) (connected-p :initform nil :accessor db-connected-p) ;; not used yet (count :initform 0 :initarg :count :accessor db-count) ;; not used yet (total-count :initform 0 :allocation :class :accessor db-total-count) ;; the use of this slot is deprecated; it will be removed when dtf works without it. (query :initform nil :accessor db-query-object) ;; resource of (active and inactive) query objects (queries :initform () :accessor db-queries))) (defclass odbc-query () ((hstmt :initform nil :initarg :hstmt :accessor hstmt) ; = cursor?? (width :initform +max-precision+ :accessor query-width) (computed-result-types :initform nil :initarg :computed-result-types :accessor computed-result-types) (column-count :initform nil :accessor column-count) (column-names :initform (make-array 0 :element-type 'string :adjustable t :fill-pointer t) :accessor column-names) (column-c-types :initform (make-array 0 :element-type 'fixnum :adjustable t :fill-pointer t) :accessor column-c-types) (column-sql-types :initform (make-array 0 :element-type 'fixnum :adjustable t :fill-pointer t) :accessor column-sql-types) (column-data-ptrs :initform (make-array 0 :adjustable t :fill-pointer t) :accessor data-ptrs) (column-out-len-ptrs :initform (make-array 0 :adjustable t :fill-pointer t) :accessor column-out-len-ptrs) (column-precisions :initform (make-array 0 :element-type 'integer :adjustable t :fill-pointer t) :accessor column-precisions) (column-scales :initform (make-array 0 :element-type 'fixnum :adjustable t :fill-pointer t) :accessor column-scales) (column-nullables-p :initform (make-array 0 :element-type 'fixnum :adjustable t :fill-pointer t) :accessor column-nullables-p) ;;(parameter-count :initform 0 :accessor parameter-count) (parameter-data-ptrs :initform (make-array 0 :adjustable t :fill-pointer t) :accessor parameter-ptrs) ;; a query string or a query expression object (sql-expression :initform nil :initarg :sql-expression :accessor sql-expression) ;; database object the query is to be run against (database :initarg :database :reader query-database) (active-p :initform nil :initarg :active-p :accessor query-active-p)) (:documentation "Stores query information, like SQL query string/expression and database to run the query against." )) ;;; AODBC Compatible interface (defun connect (&key data-source-name user password connection-string completion window-handle (autocommit t)) (let ((db (make-instance 'odbc-db))) (unless (henv db) ;; has class allocation! (setf (henv db) (%new-environment-handle))) (setf (hdbc db) (%new-db-connection-handle (henv db))) (if connection-string (%sql-driver-connect (hdbc db) connection-string (ecase completion (:no-prompt odbc::$SQL_DRIVER_NOPROMPT) (:complete odbc::$SQL_DRIVER_COMPLETE) (:prompt odbc::$SQL_DRIVER_PROMPT) (:complete-required odbc::$SQL_DRIVER_COMPLETE_REQUIRED)) window-handle) (%sql-connect (hdbc db) data-source-name user password)) #+ignore (setf (db-hstmt db) (%new-statement-handle (hdbc db))) (when (/= (get-odbc-info db odbc::$SQL_TXN_CAPABLE) odbc::$SQL_TC_NONE) (if autocommit (enable-autocommit (hdbc db)) (disable-autocommit (hdbc db)))) db)) (defun disconnect (database) "This is set in the generic-odbc-database disconnect-fn slot so xref fails but this does get called on generic ODBC connections " (with-slots (hdbc queries) database (dolist (query queries) (db-close-query query :drop-p T)) (when (db-hstmt database) (%free-statement (db-hstmt database) :drop)) (%disconnect hdbc))) (defun sql (expr &key db result-types row-count (column-names t) query hstmt width) (declare (ignore hstmt)) (cond (query (let ((q (db-open-query db expr :result-types result-types :width width))) (if column-names (values q (column-names q)) q))) (t (multiple-value-bind (data col-names) (db-query db expr :result-types result-types :width width) (cond (row-count (if (consp data) (length data) data)) (column-names (values data col-names)) (t data)))))) (defun fetch-row (query &optional (eof-errorp t) eof-value) (multiple-value-bind (row query count) (db-fetch-query-results query 1) (cond ((zerop count) (close-query query) (when eof-errorp (error 'clsql:sql-database-data-error :message "ODBC: Ran out of data in fetch-row")) eof-value) (t (car row))))) (defun close-query (query) (db-close-query query)) (defun list-all-database-tables (&key db hstmt) (declare (ignore hstmt)) (let ((query (get-free-query db))) (unwind-protect (progn (with-slots (hstmt) query (unless hstmt (setf hstmt (%new-statement-handle (hdbc db)))) (%list-tables hstmt) (%initialize-query query nil nil) (values (db-fetch-query-results query) (coerce (column-names query) 'list)))) (db-close-query query)))) (defun list-table-indexes (table &key db unique hstmt &aux (table (princ-to-string (clsql-sys::unescaped-database-identifier table)))) (declare (ignore hstmt)) (let ((query (get-free-query db))) (unwind-protect (progn (with-slots (hstmt) query (unless hstmt (setf hstmt (%new-statement-handle (hdbc db)))) (%table-statistics table hstmt :unique unique) (%initialize-query query nil nil) (values (db-fetch-query-results query) (coerce (column-names query) 'list)))) (db-close-query query)))) (defun list-all-table-columns (table &key db hstmt &aux (table (princ-to-string (clsql-sys::unescaped-database-identifier table)))) (declare (ignore hstmt)) (db-describe-columns db nil nil table nil)) ;; use nil rather than "" for unspecified values (defun list-all-data-sources () (let ((db (make-instance 'odbc-db))) (unless (henv db) ;; has class allocation! (setf (henv db) (%new-environment-handle))) (%list-data-sources (henv db)))) (defun rr-sql (hstmt sql-statement &key db) (declare (ignore hstmt sql-statement db)) (warn "rr-sql not implemented.")) ;;; Mid-level interface (defun db-commit (database) (%commit (henv database) (hdbc database))) (defun db-rollback (database) (%rollback (henv database) (hdbc database))) (defun db-cancel-query (query) (with-slots (hstmt) query (%sql-cancel hstmt) (setf (query-active-p query) nil))) #+simple-version (defmacro with-transaction (&body body) `(%with-transaction (:henv (henv ,*default-database*) :hdbc (hdbc ,*default-database*)) ,@body)) (defmethod initialize-instance :after ((query odbc-query) &key sql henv hdbc &allow-other-keys) (when sql (let ((hstmt (%new-statement-handle hdbc))) (%sql-exec-direct sql hstmt henv hdbc) (with-slots (column-count column-names column-c-types column-sql-types column-data-ptrs column-out-len-ptrs column-precisions column-scales column-nullables-p active-p) query (setf (hstmt query) hstmt) (%initialize-query query nil nil) (setf active-p t))))) ;; one for odbc-db is missing ;; TODO: Seems to be uncalled (defmethod terminate ((query odbc-query)) ;;(format tb::*local-output* "~%*** terminated: ~s" query) (db-close-query query)) (defun %dispose-column-ptrs (query) "frees memory allocated for query object column-data and column-data-length" (with-slots (column-data-ptrs column-out-len-ptrs hstmt) query (loop for data-ptr across column-data-ptrs for out-len-ptr across column-out-len-ptrs when data-ptr do (uffi:free-foreign-object data-ptr) when out-len-ptr do (uffi:free-foreign-object out-len-ptr)) (setf (fill-pointer column-data-ptrs) 0 (fill-pointer column-out-len-ptrs) 0))) (defmethod db-open-query ((database odbc-db) query-expression &key arglen col-positions result-types width &allow-other-keys) (db-open-query (get-free-query database) query-expression :arglen arglen :col-positions col-positions :result-types result-types :width (if width width (db-width database)))) (defmethod db-open-query ((query odbc-query) query-expression &key arglen col-positions result-types width &allow-other-keys) (%db-execute query query-expression) (%initialize-query query arglen col-positions :result-types result-types :width width)) (defmethod db-fetch-query-results ((database odbc-db) &optional count) (db-fetch-query-results (db-query-object database) count)) (defmethod db-fetch-query-results ((query odbc-query) &optional count) (when (query-active-p query) (with-slots (column-count column-data-ptrs column-c-types column-sql-types column-out-len-ptrs column-precisions hstmt computed-result-types) query (let* ((rows-fetched 0) (rows (loop for i from 0 until (or (and count (= i count)) (= (%sql-fetch hstmt) odbc::$SQL_NO_DATA_FOUND)) collect (loop for result-type across computed-result-types for data-ptr across column-data-ptrs for c-type across column-c-types for sql-type across column-sql-types for out-len-ptr across column-out-len-ptrs for precision across column-precisions for j from 0 ; column count is zero based in lisp collect (progn (incf rows-fetched) (cond ((< 0 precision (query-width query)) (read-data data-ptr c-type sql-type out-len-ptr result-type)) ((zerop (get-cast-long out-len-ptr)) nil) (t (read-data-in-chunks hstmt j data-ptr c-type sql-type out-len-ptr result-type)))))))) (values rows query rows-fetched))))) (defun db-query (database query-expression &key result-types width) (let ((free-query (get-free-query database))) (setf (sql-expression free-query) query-expression) (unwind-protect (progn (%db-execute free-query query-expression) (%initialize-query free-query nil nil :result-types result-types :width width) (if (plusp (column-count free-query)) ;; KMR: Added check for commands that don't return columns (values (db-fetch-query-results free-query nil) (map 'list #'identity (column-names free-query))) (values (result-rows-count (hstmt free-query)) nil))) (db-close-query free-query) ))) (defmethod %db-execute ((database odbc-db) sql-expression &key &allow-other-keys) (%db-execute (get-free-query database) sql-expression)) (defmethod %db-execute ((query odbc-query) sql-expression &key &allow-other-keys) (with-slots (henv hdbc) (odbc::query-database query) (with-slots (hstmt) query (unless hstmt (setf hstmt (%new-statement-handle hdbc))) (setf (sql-expression query) sql-expression) (%sql-exec-direct sql-expression hstmt henv hdbc) query))) ;; reuse inactive queries (defun get-free-query (database) "get-free-query finds or makes a nonactive query object, and then sets it to active. This makes the functions db-execute-command and db-query thread safe." (with-slots (queries hdbc) database (or (and *reuse-query-objects* (clsql-sys:without-interrupts (let ((inactive-query (find-if (lambda (query) (not (query-active-p query))) queries))) (when inactive-query (with-slots (column-count column-names column-c-types width hstmt column-sql-types column-data-ptrs column-out-len-ptrs column-precisions column-scales column-nullables-p) inactive-query (setf column-count 0 width +max-precision+ ;; KMR hstmt (%new-statement-handle hdbc) (fill-pointer column-names) 0 (fill-pointer column-c-types) 0 (fill-pointer column-sql-types) 0 (fill-pointer column-data-ptrs) 0 (fill-pointer column-out-len-ptrs) 0 (fill-pointer column-precisions) 0 (fill-pointer column-scales) 0 (fill-pointer column-nullables-p) 0)) (setf (query-active-p inactive-query) t)) inactive-query))) (let ((new-query (make-instance 'odbc-query :database database ;;(clone-database database) :active-p t))) (push new-query queries) new-query)))) (defmethod db-execute-command ((database odbc-db) sql-string) (db-execute-command (get-free-query database) sql-string)) (defmethod db-execute-command ((query odbc-query) sql-string) (with-slots (hstmt database) query (with-slots (henv hdbc) database (unless hstmt (setf hstmt (%new-statement-handle hdbc))) (unwind-protect (%sql-exec-direct sql-string hstmt henv hdbc) (db-close-query query))))) (defmethod %initialize-query ((database odbc-db) arglen col-positions &key result-types width) (%initialize-query (db-query-object database) arglen col-positions :result-types result-types :width (if width width (db-width database)))) (defmethod %initialize-query ((query odbc-query) arglen col-positions &key result-types width) (with-slots (hstmt computed-result-types column-count column-names column-c-types column-sql-types column-data-ptrs column-out-len-ptrs column-precisions column-scales column-nullables-p) query (setf column-count (if arglen (min arglen (result-columns-count hstmt)) (result-columns-count hstmt))) (when width (setf (query-width query) width)) ;;(format tb::*local-output* "~%column-count: ~d, col-positions: ~d" column-count col-positions) (labels ((initialize-column (col-nr) (multiple-value-bind (name sql-type precision scale nullable-p) (%describe-column hstmt (1+ col-nr)) ;; allocate space to bind result rows to (multiple-value-bind (c-type data-ptr out-len-ptr size long-p) (%allocate-bindings sql-type precision) (if long-p ;; if long-p we fetch in chunks with %sql-get-data but must ensure that out_len_ptr is non zero (setf (uffi:deref-pointer out-len-ptr #.odbc::$ODBC-LONG-TYPE) #.odbc::$SQL_NO_TOTAL) (%bind-column hstmt col-nr c-type data-ptr (1+ size) out-len-ptr)) (vector-push-extend name column-names) (vector-push-extend sql-type column-sql-types) (vector-push-extend (sql-to-c-type sql-type) column-c-types) (vector-push-extend precision column-precisions) (vector-push-extend scale column-scales) (vector-push-extend nullable-p column-nullables-p) (vector-push-extend data-ptr column-data-ptrs) (vector-push-extend out-len-ptr column-out-len-ptrs))))) (if col-positions (dolist (col-nr col-positions) (initialize-column col-nr)) (dotimes (col-nr column-count) ;; get column information (initialize-column col-nr)))) ;; TODO: move this into the above loop (setf computed-result-types (make-array column-count)) (dotimes (i column-count) (setf (aref computed-result-types i) (cond ((consp result-types) (nth i result-types)) ((eq result-types :auto) (case (aref column-c-types i) (#.odbc::$SQL_C_SLONG :int) (#.odbc::$SQL_C_DOUBLE :double) (#.odbc::$SQL_C_FLOAT :float) (#.odbc::$SQL_C_SSHORT :short) (#.odbc::$SQL_C_STINYINT :short) (#.odbc::$SQL_C_SBIGINT #.odbc::$ODBC-BIG-TYPE) (#.odbc::$SQL_C_TYPE_TIMESTAMP :time) (#.odbc::$SQL_C_CHAR ;; TODO: Read this as rational instead of double (or (case (aref column-sql-types i) ((#.odbc::$SQL_NUMERIC #.odbc::$SQL_DECIMAL) :double)) T)) (t t))) (t t))))) query) (defun db-close-query (query &key (drop-p (not *reuse-query-objects*))) (with-slots (hstmt column-count column-names column-c-types column-sql-types column-data-ptrs column-out-len-ptrs column-precisions column-scales column-nullables-p database) query (%dispose-column-ptrs query) (cond ((null hstmt) nil) (drop-p (%free-statement hstmt :drop) ;; dont free with uffi/ this is a double free and crashes everything ;; (uffi:free-foreign-object hstmt) (setf hstmt nil)) (t (%free-statement hstmt :unbind) (%free-statement hstmt :reset) (%free-statement hstmt :close))) (setf (query-active-p query) nil) (when drop-p (clsql-sys:without-interrupts (with-slots (queries) database (setf queries (remove query queries)))))) query) (defmethod %read-query-data ((database odbc-db) ignore-columns) (%read-query-data (db-query-object database) ignore-columns)) (defmethod %read-query-data ((query odbc-query) ignore-columns) (with-slots (hstmt column-count column-c-types column-sql-types column-data-ptrs column-out-len-ptrs column-precisions computed-result-types) query (unless (= (odbc::SQLFetch hstmt) odbc::$SQL_NO_DATA_FOUND) (values (loop for col-nr from 0 to (- column-count (if (eq ignore-columns :last) 2 1)) for result-type across computed-result-types collect (let ((precision (aref column-precisions col-nr)) (sql-type (aref column-sql-types col-nr))) (cond ((or (< 0 precision (query-width query)) (and (zerop precision) (not (find sql-type '($SQL_C_CHAR))))) (read-data (aref column-data-ptrs col-nr) (aref column-c-types col-nr) sql-type (aref column-out-len-ptrs col-nr) result-type)) ((zerop (get-cast-long (aref column-out-len-ptrs col-nr))) *null*) (t (read-data-in-chunks hstmt col-nr (aref column-data-ptrs col-nr) (aref column-c-types col-nr) (aref column-sql-types col-nr) (aref column-out-len-ptrs col-nr) result-type))))) t)))) (defmethod db-map-query ((database odbc-db) type function query-exp &key result-types) (db-map-query (get-free-query database) type function query-exp :result-types result-types)) (defmethod db-map-query ((query odbc-query) type function query-exp &key result-types) (declare (ignore type)) ; preliminary. Do a type coersion here (%db-execute query (sql-expression query-exp)) (unwind-protect (progn (%initialize-query query nil nil :result-types result-types) ;; the main loop (loop for data = (%read-query-data query nil) while data do (apply function data))) ;; dispose of memory and set query inactive or get rid of it (db-close-query query))) (defun db-map-bind-query (query type function &rest parameters) (declare (ignore type)) ; preliminary. Do a type coersion here (unwind-protect (progn (apply #'%db-bind-execute query parameters) ;; the main loop (loop with data while (setf data (%read-query-data query nil)) do (apply function data))) ;; dispose of memory and set query inactive or get rid of it (%db-reset-query query))) ;; does not always return exactly a lisp type... (defun sql-to-lisp-type (sql-type) (ecase sql-type ((#.odbc::$SQL_CHAR #.odbc::$SQL_VARCHAR #.odbc::$SQL_LONGVARCHAR) :string) ((#.odbc::$SQL_NUMERIC #.odbc::$SQL_DECIMAL) :string) ; ?? (#.odbc::$SQL_BIGINT #.odbc::$ODBC-BIG-TYPE) (#.odbc::$SQL_INTEGER #.odbc::$ODBC-LONG-TYPE) (#.odbc::$SQL_SMALLINT :short) ((#.odbc::$SQL_FLOAT #.odbc::$SQL_DOUBLE) #.odbc::$ODBC-LONG-TYPE) (#.odbc::$SQL_REAL #.odbc::$ODBC-LONG-TYPE) ((#.odbc::$SQL_DATE #.odbc::$SQL_TYPE_DATE) 'sql-c-date) ((#.odbc::$SQL_TIME #.odbc::$SQL_TYPE_TIME) 'sql-c-time) ((#.odbc::$SQL_TIMESTAMP #.odbc::$SQL_TYPE_TIMESTAMP) 'sql-c-timestamp) ;;((#.odbc::$SQL_BINARY #.odbc::$SQL_VARBINARY #.odbc::$SQL_LONGVARBINARY) odbc::$SQL_C_BINARY) ; ?? (#.odbc::$SQL_TINYINT :short) ;;(#.odbc::$SQL_BIT odbc::$SQL_C_BIT) ; ?? (#.odbc::$SQL_BIT :short) ((#.odbc::$SQL_VARBINARY #.odbc::$SQL_LONGVARBINARY) :binary) )) ;; prepared queries (defmethod db-prepare-statement ((database odbc-db) sql &key parameter-table parameter-columns) (with-slots (hdbc) database (let ((query (get-free-query database))) (with-slots (hstmt) query (unless hstmt (setf hstmt (%new-statement-handle hdbc)))) (db-prepare-statement query sql :parameter-table parameter-table :parameter-columns parameter-columns)))) (defmethod db-prepare-statement ((query odbc-query) (sql string) &key parameter-table parameter-columns) ;; this is a workaround to get hold of the column types when the driver does not ;; support SQLDescribeParam. To do: put code in here for drivers that do ;; support it. (unless (string-equal sql "insert" :end1 6) (error 'clsql:sql-database-error (format nil "Only insert expressions are supported in literal ODBC: '~a'." sql))) (%db-execute query (format nil "select ~{~a~^,~} from ~a where 0 = 1" (or parameter-columns '("*")) parameter-table)) (%initialize-query query nil nil) (with-slots (hstmt) query (%free-statement hstmt :unbind) (%free-statement hstmt :reset) (setf (sql-expression query) sql) (%sql-prepare hstmt sql)) query) (defun %db-bind-execute (query &rest parameters) "Only used from db-map-bind-query parameters are released in %reset-query " (with-slots (hstmt parameter-data-ptrs) query (loop for parameter in parameters with data-ptr and size and parameter-string do (setf parameter-string (if (stringp parameter) parameter (write-to-string parameter)) size (length parameter-string) data-ptr (uffi:allocate-foreign-string (1+ size))) (vector-push-extend data-ptr parameter-data-ptrs) (%sql-bind-parameter hstmt (1- (fill-pointer parameter-data-ptrs)) odbc::$SQL_PARAM_INPUT odbc::$SQL_C_CHAR ; (aref column-c-types parameter-count) odbc::$SQL_CHAR ; sql-type (query-width query) ;precision ; this should be the actual precision! ;; scale 0 ;; should be calculated for odbc::$SQL_DECIMAL, ;;$SQL_NUMERIC and odbc::$SQL_TIMESTAMP data-ptr ;; = rgbValue 0 ;; *pcbValue; ;; change this for output and binary input! (see 3-32) +null-ptr+) (%put-str data-ptr parameter-string size)) (%sql-execute hstmt))) (defun %db-reset-query (query) "Only used from db-map-bind-query parameters are allocated in %db-bind-execute " (with-slots (hstmt parameter-data-ptrs) query (prog1 (db-fetch-query-results query nil) (%free-statement hstmt :reset) ;; but _not_ :unbind ! (%free-statement hstmt :close) (dotimes (param-nr (fill-pointer parameter-data-ptrs)) (let ((data-ptr (aref parameter-data-ptrs param-nr))) (when data-ptr (uffi:free-foreign-object data-ptr)))) (setf (fill-pointer parameter-data-ptrs) 0)))) (defun data-parameter-ptr (hstmt) (uffi:with-foreign-object (param-ptr :pointer-void) (let ((return-code (%sql-param-data hstmt param-ptr))) ;;(format t "~%return-code from %sql-param-data: ~a~%" return-code) (when (= return-code odbc::$SQL_NEED_DATA) ;;(ffc::%pointer-to-address (%get-ptr param-ptr)) (uffi:deref-pointer param-ptr :pointer-void))))) ;; database inquiery functions (defun db-describe-columns (database table-qualifier table-owner table-name column-name) (with-slots (hdbc) database (%describe-columns hdbc table-qualifier table-owner table-name column-name))) ;; should translate info-type integers to keywords in order to make this ;; more readable? (defmethod get-odbc-info ((database odbc-db) info-type) (with-slots (hdbc info) database (or (gethash info-type info) (setf (gethash info-type info) (%sql-get-info hdbc info-type))))) (defmethod get-odbc-info ((query odbc-query) info-type) (get-odbc-info (odbc::query-database query) info-type)) ;; driver inquiry ;; How does this differ from list-data-sources? (defgeneric db-data-sources (db-type)) (defmethod db-data-sources ((db-type (eql :odbc))) "Returns a list of (data-source description) - pairs" (let ((henv (%new-environment-handle))) (unwind-protect (loop with direction = :first for data-source+description = (multiple-value-list (%sql-data-sources henv :direction direction)) while (car data-source+description) collect data-source+description do (setf direction :next)) (%sql-free-environment henv)))) cl-sql-6.4.1/db-odbc/odbc-api.lisp0000644000175000017500000012124611725170505015601 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Package: odbc -*- ;;;; ************************************************************************* ;;;; FILE IDENTIFICATION ;;;; ;;;; Name: odbc-api.lisp ;;;; Purpose: Low-level ODBC API using UFFI ;;;; Authors: Kevin M. Rosenberg and Paul Meurer ;;;; ;;;; This file, part of CLSQL, is Copyright (c) 2004 by Kevin M. Rosenberg ;;;; and Copyright (C) Paul Meurer 1999 - 2001. All rights reserved. ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* (in-package #:odbc) (defvar *null* nil "Lisp representation of SQL Null value, default = nil. May be locally bound to something else if a certain type is necessary.") (defvar *binary-format* :unsigned-byte-vector) (defvar *time-format* (lambda (time) (clsql-sys:format-time nil time :format :iso)) "Bound to a function that converts from a clsql:wall-time to the desired representation of date/time/timestamp. By default, returns an iso-timestring.") (defvar +null-ptr+ (make-null-pointer :byte)) (defparameter +null-handle-ptr+ (make-null-pointer :void)) (defvar *info-output* nil "Stream to send SUCCESS_WITH_INFO messages.") (defmacro %put-str (ptr string &optional max-length) (let ((size (gensym))) `(let ((,size (length ,string))) (when (and ,max-length (> ,size ,max-length)) (error 'clsql:sql-database-data-error :message (format nil "string \"~a\" of length ~d is longer than max-length: ~d" ,string ,size ,max-length))) (with-cast-pointer (char-ptr ,ptr :byte) (dotimes (i ,size) (setf (deref-array char-ptr '(:array :byte) i) (char-code (char ,string i)))) (setf (deref-array char-ptr '(:array :byte) ,size) 0))))) (defmacro with-allocate-foreign-string ((var len) &body body) "Safely does uffi:allocate-foreign-string-- making sure we do the uffi:free-foreign-object" `(let ((,var)) (unwind-protect (progn (setf ,var (uffi:allocate-foreign-string ,len)) ,@body) (when ,var (uffi:free-foreign-object ,var))))) (defmacro with-allocate-foreign-strings (bindings &rest body) (if bindings `(with-allocate-foreign-string ,(car bindings) (with-allocate-foreign-strings ,(cdr bindings) ,@body)) `(progn ,@body))) (defun handle-error (henv hdbc hstmt) (with-allocate-foreign-strings ((sql-state 256) (error-message #.$SQL_MAX_MESSAGE_LENGTH)) (with-foreign-objects ((error-code #.$ODBC-LONG-TYPE) (msg-length :short)) (SQLError henv hdbc hstmt sql-state error-code error-message #.$SQL_MAX_MESSAGE_LENGTH msg-length) (values (convert-from-foreign-string error-message) (convert-from-foreign-string sql-state) (deref-pointer msg-length :short) (deref-pointer error-code #.$ODBC-LONG-TYPE))))) (defun sql-state (henv hdbc hstmt) (with-allocate-foreign-strings ((sql-state 256) (error-message #.$SQL_MAX_MESSAGE_LENGTH)) (with-foreign-objects ((error-code #.$ODBC-LONG-TYPE) (msg-length :short)) (SQLError henv hdbc hstmt sql-state error-code error-message #.$SQL_MAX_MESSAGE_LENGTH msg-length) (convert-from-foreign-string sql-state) ;; test this: return a keyword for efficiency ;;(%cstring-to-keyword state) ))) (defmacro with-error-handling ((&key henv hdbc hstmt (print-info t)) odbc-call &body body) (let ((result-code (gensym "RC-"))) `(let ((,result-code ,odbc-call)) ;; Check for allegro v7 & v8 bug with ODBC calls returning ;; 32-bit unsigned ints, not 16-bit signed ints #+(and allegro mswindows) (when (> ,result-code #xFFFF) (warn (format nil "16-bit return bug: result-code #x~X for expression ~S" ,result-code (quote ,odbc-call))) (setq ,result-code (logand ,result-code #xFFFF)) (when (> ,result-code #x7FFF) (setq ,result-code (- ,result-code #x10000)))) (case ,result-code (#.$SQL_SUCCESS (progn ,result-code ,@body)) (#.$SQL_SUCCESS_WITH_INFO (when ,print-info (multiple-value-bind (error-message sql-state) (handle-error (or ,henv +null-handle-ptr+) (or ,hdbc +null-handle-ptr+) (or ,hstmt +null-handle-ptr+)) (when *info-output* (format *info-output* "[ODBC info ~A] ~A state: ~A" ,result-code error-message sql-state)))) (progn ,result-code ,@body)) (#.$SQL_INVALID_HANDLE (error 'clsql-sys:sql-database-error :message "ODBC: Invalid handle")) (#.$SQL_STILL_EXECUTING (error 'clsql-sys:sql-temporary-error :message "ODBC: Still executing")) (#.$SQL_ERROR (multiple-value-bind (error-message sql-state) (handle-error (or ,henv +null-handle-ptr+) (or ,hdbc +null-handle-ptr+) (or ,hstmt +null-handle-ptr+)) (error 'clsql-sys:sql-database-error :message error-message :secondary-error-id sql-state))) (#.$SQL_NO_DATA_FOUND (progn ,result-code ,@body)) ;; work-around for Allegro 7.0beta AMD64 which returns negative numbers (otherwise (multiple-value-bind (error-message sql-state) (handle-error (or ,henv +null-handle-ptr+) (or ,hdbc +null-handle-ptr+) (or ,hstmt +null-handle-ptr+)) (error 'clsql-sys:sql-database-error :message error-message :secondary-error-id sql-state)) #+ignore (progn ,result-code ,@body)))))) (defun %new-environment-handle () (let ((henv (with-foreign-object (phenv 'sql-handle) (with-error-handling () (SQLAllocHandle $SQL_HANDLE_ENV +null-handle-ptr+ phenv) (deref-pointer phenv 'sql-handle))))) (%set-attr-odbc-version henv $SQL_OV_ODBC3) henv)) (defun %sql-free-environment (henv) (with-error-handling (:henv henv) (SQLFreeEnv henv))) (defun %new-db-connection-handle (henv) (with-foreign-object (phdbc 'sql-handle) (setf (deref-pointer phdbc 'sql-handle) +null-handle-ptr+) (with-error-handling (:henv henv) (SQLAllocHandle $SQL_HANDLE_DBC henv phdbc) (deref-pointer phdbc 'sql-handle)))) (defun %free-statement (hstmt option) (with-error-handling (:hstmt hstmt) (SQLFreeStmt hstmt (ecase option (:drop $SQL_DROP) (:close $SQL_CLOSE) (:unbind $SQL_UNBIND) (:reset $SQL_RESET_PARAMS))))) (defmacro with-statement-handle ((hstmt hdbc) &body body) `(let ((,hstmt (%new-statement-handle ,hdbc))) (unwind-protect (progn ,@body) (%free-statement ,hstmt :drop)))) ;; functional interface (defun %sql-connect (hdbc server uid pwd) (with-cstrings ((server-ptr server) (uid-ptr uid) (pwd-ptr pwd)) (with-error-handling (:hdbc hdbc) (SQLConnect hdbc server-ptr $SQL_NTS uid-ptr $SQL_NTS pwd-ptr $SQL_NTS)))) (defun %sql-driver-connect (hdbc connection-string completion window-handle) (with-cstring (connection-ptr connection-string) (with-allocate-foreign-string (completed-connection-string-ptr $SQL_MAX_CONN_OUT) (with-foreign-object (completed-connection-length :short) (with-error-handling (:hdbc hdbc) (SQLDriverConnect hdbc (or window-handle +null-handle-ptr+) connection-ptr $SQL_NTS completed-connection-string-ptr $SQL_MAX_CONN_OUT completed-connection-length completion)))))) (defun %disconnect (hdbc) (with-error-handling (:hdbc hdbc) (SQLDisconnect hdbc) (with-error-handling (:hdbc hdbc) (SQLFreeHandle $SQL_HANDLE_DBC hdbc)))) (defun %commit (henv hdbc) (with-error-handling (:henv henv :hdbc hdbc) (SQLTransact henv hdbc $SQL_COMMIT))) (defun %rollback (henv hdbc) (with-error-handling (:henv henv :hdbc hdbc) (SQLTransact henv hdbc $SQL_ROLLBACK))) ; col-nr is zero-based in Lisp but 1 based in sql ; col-nr = :bookmark retrieves a bookmark. (defun %bind-column (hstmt column-nr c-type data-ptr precision out-len-ptr) (with-error-handling (:hstmt hstmt) (SQLBindCol hstmt (if (eq column-nr :bookmark) 0 (1+ column-nr)) c-type data-ptr precision out-len-ptr))) ; parameter-nr is zero-based in Lisp (defun %sql-bind-parameter (hstmt parameter-nr parameter-type c-type sql-type precision scale data-ptr max-value out-len-ptr) (with-error-handling (:hstmt hstmt) (SQLBindParameter hstmt (1+ parameter-nr) parameter-type ;$SQL_PARAM_INPUT c-type ;$SQL_C_CHAR sql-type ;$SQL_VARCHAR precision ;(1- (length str)) scale ;0 data-ptr max-value out-len-ptr ;#.+null-ptr+ ))) (defun %sql-fetch (hstmt) (with-error-handling (:hstmt hstmt) (SQLFetch hstmt))) (defun %new-statement-handle (hdbc) (let ((statement-handle (with-foreign-object (phstmt 'sql-handle) (with-error-handling (:hdbc hdbc) (SQLAllocHandle $SQL_HANDLE_STMT hdbc phstmt) (deref-pointer phstmt 'sql-handle))))) (if (uffi:null-pointer-p statement-handle) (error 'clsql:sql-database-error :message "Received null statement handle.") statement-handle))) (defun %sql-get-info (hdbc info-type) (ecase info-type ;; those return string ((#.$SQL_ACCESSIBLE_PROCEDURES #.$SQL_ACCESSIBLE_TABLES #.$SQL_COLUMN_ALIAS #.$SQL_DATA_SOURCE_NAME #.$SQL_DATA_SOURCE_READ_ONLY #.$SQL_DBMS_NAME #.$SQL_DBMS_VER #.$SQL_DRIVER_NAME #.$SQL_DRIVER_ODBC_VER #.$SQL_DRIVER_VER #.$SQL_EXPRESSIONS_IN_ORDERBY #.$SQL_IDENTIFIER_QUOTE_CHAR #.$SQL_KEYWORDS #.$SQL_LIKE_ESCAPE_CLAUSE #.$SQL_MAX_ROW_SIZE_INCLUDES_LONG #.$SQL_MULT_RESULT_SETS #.$SQL_MULTIPLE_ACTIVE_TXN #.$SQL_NEED_LONG_DATA_LEN #.$SQL_ODBC_SQL_OPT_IEF #.$SQL_ODBC_VER #.$SQL_ORDER_BY_COLUMNS_IN_SELECT #.$SQL_OUTER_JOINS #.$SQL_OWNER_TERM #.$SQL_PROCEDURE_TERM #.$SQL_PROCEDURES #.$SQL_QUALIFIER_NAME_SEPARATOR #.$SQL_QUALIFIER_TERM #.$SQL_ROW_UPDATES #.$SQL_SEARCH_PATTERN_ESCAPE #.$SQL_SERVER_NAME #.$SQL_SPECIAL_CHARACTERS #.$SQL_TABLE_TERM #.$SQL_USER_NAME) (with-allocate-foreign-string (info-ptr 1024) (with-foreign-object (info-length-ptr :short) (with-error-handling (:hdbc hdbc) (SQLGetInfo hdbc info-type info-ptr 1023 info-length-ptr) (convert-from-foreign-string info-ptr))))) ;; those returning a word ((#.$SQL_ACTIVE_CONNECTIONS #.$SQL_ACTIVE_STATEMENTS #.$SQL_CONCAT_NULL_BEHAVIOR #.$SQL_CORRELATION_NAME #.$SQL_CURSOR_COMMIT_BEHAVIOR #.$SQL_CURSOR_ROLLBACK_BEHAVIOR #.$SQL_MAX_COLUMN_NAME_LEN #.$SQL_MAX_COLUMNS_IN_GROUP_BY #.$SQL_MAX_COLUMNS_IN_INDEX #.$SQL_MAX_COLUMNS_IN_ORDER_BY #.$SQL_MAX_COLUMNS_IN_SELECT #.$SQL_MAX_COLUMNS_IN_TABLE #.$SQL_MAX_CURSOR_NAME_LEN #.$SQL_MAX_OWNER_NAME_LEN #.$SQL_MAX_PROCEDURE_NAME_LEN #.$SQL_MAX_QUALIFIER_NAME_LEN #.$SQL_MAX_TABLE_NAME_LEN #.$SQL_MAX_TABLES_IN_SELECT #.$SQL_MAX_USER_NAME_LEN #.$SQL_NON_NULLABLE_COLUMNS #.$SQL_NULL_COLLATION #.$SQL_ODBC_API_CONFORMANCE #.$SQL_ODBC_SAG_CLI_CONFORMANCE #.$SQL_ODBC_SQL_CONFORMANCE #.$SQL_QUALIFIER_LOCATION #.$SQL_QUOTED_IDENTIFIER_CASE #.$SQL_TXN_CAPABLE) (with-foreign-objects ((info-ptr :short) (info-length-ptr :short)) (with-error-handling (:hdbc hdbc) (SQLGetInfo hdbc info-type info-ptr 255 info-length-ptr) (deref-pointer info-ptr :short))) ) ;; those returning a long bitmask ((#.$SQL_ALTER_TABLE #.$SQL_BOOKMARK_PERSISTENCE #.$SQL_CONVERT_BIGINT #.$SQL_CONVERT_BINARY #.$SQL_CONVERT_BIT #.$SQL_CONVERT_CHAR #.$SQL_CONVERT_DATE #.$SQL_CONVERT_DECIMAL #.$SQL_CONVERT_DOUBLE #.$SQL_CONVERT_FLOAT #.$SQL_CONVERT_INTEGER #.$SQL_CONVERT_LONGVARCHAR #.$SQL_CONVERT_NUMERIC #.$SQL_CONVERT_REAL #.$SQL_CONVERT_SMALLINT #.$SQL_CONVERT_TIME #.$SQL_CONVERT_TIMESTAMP #.$SQL_CONVERT_TINYINT #.$SQL_CONVERT_VARBINARY #.$SQL_CONVERT_VARCHAR #.$SQL_CONVERT_LONGVARBINARY #.$SQL_CONVERT_FUNCTIONS #.$SQL_FETCH_DIRECTION #.$SQL_FILE_USAGE #.$SQL_GETDATA_EXTENSIONS #.$SQL_LOCK_TYPES #.$SQL_MAX_INDEX_SIZE #.$SQL_MAX_ROW_SIZE #.$SQL_MAX_STATEMENT_LEN #.$SQL_NUMERIC_FUNCTIONS #.$SQL_OWNER_USAGE #.$SQL_POS_OPERATIONS #.$SQL_POSITIONED_STATEMENTS #.$SQL_QUALIFIER_USAGE #.$SQL_SCROLL_CONCURRENCY #.$SQL_SCROLL_OPTIONS #.$SQL_STATIC_SENSITIVITY #.$SQL_STRING_FUNCTIONS #.$SQL_SUBQUERIES #.$SQL_SYSTEM_FUNCTIONS #.$SQL_TIMEDATE_ADD_INTERVALS #.$SQL_TIMEDATE_DIFF_INTERVALS #.$SQL_TIMEDATE_FUNCTIONS #.$SQL_TXN_ISOLATION_OPTION #.$SQL_UNION) (with-foreign-objects ((info-ptr #.$ODBC-LONG-TYPE) (info-length-ptr :short)) (with-error-handling (:hdbc hdbc) (SQLGetInfo hdbc info-type info-ptr 255 info-length-ptr) (deref-pointer info-ptr #.$ODBC-LONG-TYPE))) ) ;; those returning a long integer ((#.$SQL_DEFAULT_TXN_ISOLATION #.$SQL_DRIVER_HDBC #.$SQL_DRIVER_HENV #.$SQL_DRIVER_HLIB #.$SQL_DRIVER_HSTMT #.$SQL_GROUP_BY #.$SQL_IDENTIFIER_CASE #.$SQL_MAX_BINARY_LITERAL_LEN #.$SQL_MAX_CHAR_LITERAL_LEN #.$SQL_ACTIVE_ENVIRONMENTS ) (with-foreign-objects ((info-ptr #.$ODBC-LONG-TYPE) (info-length-ptr :short)) (with-error-handling (:hdbc hdbc) (SQLGetInfo hdbc info-type info-ptr 255 info-length-ptr) (deref-pointer info-ptr #.$ODBC-LONG-TYPE)))))) (defun %sql-exec-direct (sql hstmt henv hdbc) (with-cstring (sql-ptr sql) (with-error-handling (:hstmt hstmt :henv henv :hdbc hdbc) (SQLExecDirect hstmt sql-ptr $SQL_NTS)))) (defun %sql-cancel (hstmt) (with-error-handling (:hstmt hstmt) (SQLCancel hstmt))) (defun %sql-execute (hstmt) (with-error-handling (:hstmt hstmt) (SQLExecute hstmt))) (defun result-columns-count (hstmt) (with-foreign-objects ((columns-nr-ptr :short)) (with-error-handling (:hstmt hstmt) (SQLNumResultCols hstmt columns-nr-ptr) (deref-pointer columns-nr-ptr :short)))) (defun result-rows-count (hstmt) (with-foreign-objects ((row-count-ptr #.$ODBC-LONG-TYPE)) (with-error-handling (:hstmt hstmt) (SQLRowCount hstmt row-count-ptr) (deref-pointer row-count-ptr #.$ODBC-LONG-TYPE)))) ;; column counting is 1-based (defun %describe-column (hstmt column-nr) (with-allocate-foreign-string (column-name-ptr 256) (with-foreign-objects ((column-name-length-ptr :short) (column-sql-type-ptr :short) (column-precision-ptr #.$ODBC-ULONG-TYPE) (column-scale-ptr :short) (column-nullable-p-ptr :short)) (with-error-handling (:hstmt hstmt) (SQLDescribeCol hstmt column-nr column-name-ptr 256 column-name-length-ptr column-sql-type-ptr column-precision-ptr column-scale-ptr column-nullable-p-ptr) (values (convert-from-foreign-string column-name-ptr) (deref-pointer column-sql-type-ptr :short) (deref-pointer column-precision-ptr #.$ODBC-ULONG-TYPE) (deref-pointer column-scale-ptr :short) (deref-pointer column-nullable-p-ptr :short)))))) ;; parameter counting is 1-based ;; this function isn't used, which is good because FreeTDS dosn't support it. (defun %describe-parameter (hstmt parameter-nr) (with-foreign-objects ((column-sql-type-ptr :short) (column-precision-ptr #.$ODBC-ULONG-TYPE) (column-scale-ptr :short) (column-nullable-p-ptr :short)) (with-error-handling (:hstmt hstmt) (SQLDescribeParam hstmt parameter-nr column-sql-type-ptr column-precision-ptr column-scale-ptr column-nullable-p-ptr) (values (deref-pointer column-sql-type-ptr :short) (deref-pointer column-precision-ptr #.$ODBC-ULONG-TYPE) (deref-pointer column-scale-ptr :short) (deref-pointer column-nullable-p-ptr :short))))) (defun %column-attributes (hstmt column-nr descriptor-type) (with-allocate-foreign-string (descriptor-info-ptr 256) (with-foreign-objects ((descriptor-length-ptr :short) (numeric-descriptor-ptr #.$ODBC-LONG-TYPE)) (with-error-handling (:hstmt hstmt) (SQLColAttributes hstmt column-nr descriptor-type descriptor-info-ptr 256 descriptor-length-ptr numeric-descriptor-ptr) (values (convert-from-foreign-string descriptor-info-ptr) (deref-pointer numeric-descriptor-ptr #.$ODBC-LONG-TYPE)))))) (defun %prepare-describe-columns (hstmt table-qualifier table-owner table-name column-name) (with-cstrings ((table-qualifier-ptr table-qualifier) (table-owner-ptr table-owner) (table-name-ptr table-name) (column-name-ptr column-name)) (with-error-handling (:hstmt hstmt) (SQLColumns hstmt table-qualifier-ptr (length table-qualifier) table-owner-ptr (length table-owner) table-name-ptr (length table-name) column-name-ptr (length column-name))))) (defun %describe-columns (hdbc table-qualifier table-owner table-name column-name) (with-statement-handle (hstmt hdbc) (%prepare-describe-columns hstmt table-qualifier table-owner table-name column-name) (fetch-all-rows hstmt))) (defun %sql-data-sources (henv &key (direction :first)) (with-allocate-foreign-strings ((name-ptr (1+ $SQL_MAX_DSN_LENGTH)) (description-ptr 1024)) (with-foreign-objects ((name-length-ptr :short) (description-length-ptr :short)) (let ((res (with-error-handling (:henv henv) (SQLDataSources henv (ecase direction (:first $SQL_FETCH_FIRST) (:next $SQL_FETCH_NEXT)) name-ptr (1+ $SQL_MAX_DSN_LENGTH) name-length-ptr description-ptr 1024 description-length-ptr)))) (when (= res $SQL_NO_DATA_FOUND) (values (convert-from-foreign-string name-ptr) (convert-from-foreign-string description-ptr))))))) (defun sql-to-c-type (sql-type) (ecase sql-type ;; Added -10 for MSSQL ntext type and -11 for nvarchar ((#.$SQL_CHAR #.$SQL_VARCHAR #.$SQL_LONGVARCHAR #.$SQL_NUMERIC #.$sql_decimal -8 -9 -10 -11) $SQL_C_CHAR) (#.$SQL_INTEGER $SQL_C_SLONG) (#.$SQL_BIGINT $SQL_C_SBIGINT) (#.$SQL_SMALLINT $SQL_C_SSHORT) (#.$SQL_DOUBLE $SQL_C_DOUBLE) (#.$SQL_FLOAT $SQL_C_DOUBLE) (#.$SQL_REAL $SQL_C_FLOAT) (#.$SQL_DATE $SQL_C_DATE) (#.$SQL_TIME $SQL_C_TIME) (#.$SQL_TIMESTAMP $SQL_C_TIMESTAMP) (#.$SQL_TYPE_DATE $SQL_C_TYPE_DATE) (#.$SQL_TYPE_TIME $SQL_C_TYPE_TIME) (#.$SQL_TYPE_TIMESTAMP $SQL_C_TYPE_TIMESTAMP) ((#.$SQL_BINARY #.$SQL_VARBINARY #.$SQL_LONGVARBINARY) $SQL_C_BINARY) (#.$SQL_TINYINT $SQL_C_STINYINT) (#.$SQL_BIT $SQL_C_BIT))) (def-type byte-pointer-type (* :byte)) (def-type short-pointer-type (* :short)) (def-type int-pointer-type (* :int)) (def-type long-pointer-type (* #.$ODBC-LONG-TYPE)) (def-type big-pointer-type (* #.$ODBC-BIG-TYPE)) (def-type float-pointer-type (* :float)) (def-type double-pointer-type (* :double)) (def-type string-pointer-type (* :unsigned-char)) (defun get-cast-byte (ptr) (locally (declare (type byte-pointer-type ptr)) (deref-pointer ptr :byte))) (defun get-cast-short (ptr) (locally (declare (type short-pointer-type ptr)) (deref-pointer ptr :short))) (defun get-cast-int (ptr) (locally (declare (type int-pointer-type ptr)) (deref-pointer ptr :int))) (defun get-cast-long (ptr) (locally (declare (type long-pointer-type ptr)) (deref-pointer ptr #.$ODBC-LONG-TYPE))) (defun get-cast-big (ptr) (locally (declare (type big-pointer-type ptr)) (deref-pointer ptr #.$ODBC-BIG-TYPE))) (defun get-cast-single-float (ptr) (locally (declare (type float-pointer-type ptr)) (deref-pointer ptr :float))) (defun get-cast-double-float (ptr) (locally (declare (type double-pointer-type ptr)) (deref-pointer ptr :double))) (defun get-cast-foreign-string (ptr) (locally (declare (type string-pointer-type ptr)) (convert-from-foreign-string ptr))) (defun get-cast-binary (ptr len format) "FORMAT is one of :unsigned-byte-vector, :bit-vector (:string, :hex-string)" (with-cast-pointer (casted ptr :unsigned-byte) (ecase format (:unsigned-byte-vector (let ((vector (make-array len :element-type '(unsigned-byte 8)))) (dotimes (i len) (setf (aref vector i) (deref-array casted '(:array :unsigned-byte) i))) vector)) (:bit-vector (let ((vector (make-array (ash len 3) :element-type 'bit))) (dotimes (i len) (let ((byte (deref-array casted '(:array :byte) i))) (dotimes (j 8) (setf (bit vector (+ (ash i 3) j)) (logand (ash byte (- j 7)) 1))))) vector))))) (defun read-data (data-ptr c-type sql-type out-len-ptr result-type) (declare (type long-ptr-type out-len-ptr)) (let* ((out-len (get-cast-long out-len-ptr)) (value (cond ((= out-len $SQL_NULL_DATA) *null*) (t (case sql-type ;; SQL extended datatypes (#.$SQL_TINYINT (get-cast-byte data-ptr)) (#.$SQL_C_STINYINT (get-cast-byte data-ptr)) ;; ? (#.$SQL_C_SSHORT (get-cast-short data-ptr)) ;; ? (#.$SQL_SMALLINT (get-cast-short data-ptr)) ;; ?? (#.$SQL_INTEGER (get-cast-int data-ptr)) (#.$SQL_BIGINT (get-cast-big data-ptr)) ;; TODO: Change this to read in rationals instead of doubles ((#.$SQL_DECIMAL #.$SQL_NUMERIC) (let* ((*read-base* 10) (*read-default-float-format* 'double-float) (str (get-cast-foreign-string data-ptr))) (read-from-string str))) (#.$SQL_BIT (get-cast-byte data-ptr)) (t (case c-type ((#.$SQL_C_DATE #.$SQL_C_TYPE_DATE) (funcall *time-format* (date-to-clsql-time data-ptr))) ((#.$SQL_C_TIME #.$SQL_C_TYPE_TIME) (funcall *time-format* (time-to-clsql-time data-ptr))) ((#.$SQL_C_TIMESTAMP #.$SQL_C_TYPE_TIMESTAMP) (funcall *time-format* (timestamp-to-clsql-time data-ptr))) (#.$SQL_INTEGER (get-cast-int data-ptr)) (#.$SQL_C_FLOAT (get-cast-single-float data-ptr)) (#.$SQL_C_DOUBLE (get-cast-double-float data-ptr)) (#.$SQL_C_SLONG (get-cast-long data-ptr)) #+lispworks (#.$SQL_C_BIT ; encountered only in Access (get-cast-byte data-ptr)) (#.$SQL_C_BINARY (get-cast-binary data-ptr out-len *binary-format*)) ((#.$SQL_C_SSHORT #.$SQL_C_STINYINT) ; LMH short ints (get-cast-short data-ptr)) ; LMH (#.$SQL_C_SBIGINT (get-cast-big data-ptr)) #+ignore (#.$SQL_C_CHAR (code-char (get-cast-short data-ptr))) (t (get-cast-foreign-string data-ptr))))))))) ;; FIXME: this could be better optimized for types which use READ-FROM-STRING above (if (and (or (eq result-type t) (eq result-type :string)) value (not (stringp value))) (write-to-string value) value))) ;; which value is appropriate? (defparameter +max-precision+ 4001) (defvar *break-on-unknown-data-type* t) ;; C. Stacy's idea to factor this out ;; "Make it easy to add new datatypes by making new subroutine %ALLOCATE-BINDINGS, ;; so that I don't have to remember to make changes in more than one place. ;; Just keep it in synch with READ-DATA." (defun %allocate-bindings (sql-type precision) (let* ((c-type (sql-to-c-type sql-type)) (size (if (zerop precision) +max-precision+ ;; if the precision cannot be determined (min precision +max-precision+))) (long-p (= size +max-precision+)) (data-ptr (case c-type ;; add more? (#.$SQL_C_SLONG (uffi:allocate-foreign-object #.$ODBC-LONG-TYPE)) ((#.$SQL_C_DATE #.$SQL_C_TYPE_DATE) (allocate-foreign-object 'sql-c-date)) ((#.$SQL_C_TIME #.$SQL_C_TYPE_TIME) (allocate-foreign-object 'sql-c-time)) ((#.$SQL_C_TIMESTAMP #.$SQL_C_TYPE_TIMESTAMP) (allocate-foreign-object 'sql-c-timestamp)) (#.$SQL_C_FLOAT (uffi:allocate-foreign-object :float)) (#.$SQL_C_DOUBLE (uffi:allocate-foreign-object :double)) (#.$SQL_C_BIT (uffi:allocate-foreign-object :byte)) (#.$SQL_C_STINYINT (uffi:allocate-foreign-object :byte)) (#.$SQL_C_SBIGINT (uffi:allocate-foreign-object #.$ODBC-BIG-TYPE)) (#.$SQL_C_SSHORT (uffi:allocate-foreign-object :short)) (#.$SQL_C_CHAR (uffi:allocate-foreign-string (1+ size))) (#.$SQL_C_BINARY (uffi:allocate-foreign-string (1+ (* 2 size)))) (t ;; Maybe should signal a restartable condition for this? (when *break-on-unknown-data-type* (break "SQL type is ~A, precision ~D, size ~D, C type is ~A" sql-type precision size c-type)) (uffi:allocate-foreign-object :byte (1+ size))))) (out-len-ptr (uffi:allocate-foreign-object #.$ODBC-LONG-TYPE))) (values c-type data-ptr out-len-ptr size long-p))) (defun fetch-all-rows (hstmt &key free-option flatp) (let ((column-count (result-columns-count hstmt))) (unless (zerop column-count) (let ((names (make-array column-count)) (sql-types (make-array column-count :element-type 'fixnum)) (c-types (make-array column-count :element-type 'fixnum)) (precisions (make-array column-count :element-type 'fixnum)) (data-ptrs (make-array column-count :initial-element nil)) (out-len-ptrs (make-array column-count :initial-element nil)) (scales (make-array column-count :element-type 'fixnum)) (nullables-p (make-array column-count :element-type 'fixnum))) (unwind-protect (values (progn (dotimes (col-nr column-count) ;; get column information (multiple-value-bind (name sql-type precision scale nullable-p) (%describe-column hstmt (1+ col-nr)) ;; allocate space to bind result rows to (multiple-value-bind (c-type data-ptr out-len-ptr) (%allocate-bindings sql-type precision) (%bind-column hstmt col-nr c-type data-ptr (1+ precision) out-len-ptr) (setf (svref names col-nr) name (aref sql-types col-nr) sql-type (aref c-types col-nr) (sql-to-c-type sql-type) (aref precisions col-nr) (if (zerop precision) 0 precision) (aref scales col-nr) scale (aref nullables-p col-nr) nullable-p (aref data-ptrs col-nr) data-ptr (aref out-len-ptrs col-nr) out-len-ptr)))) ;; the main loop (prog1 (cond (flatp (when (> column-count 1) (error 'clsql:sql-database-error :message "If more than one column is to be fetched, flatp has to be nil.")) (loop until (= (%sql-fetch hstmt) $SQL_NO_DATA_FOUND) collect (read-data (aref data-ptrs 0) (aref c-types 0) (aref sql-types 0) (aref out-len-ptrs 0) t))) (t (loop until (= (%sql-fetch hstmt) $SQL_NO_DATA_FOUND) collect (loop for col-nr from 0 to (1- column-count) collect (read-data (aref data-ptrs col-nr) (aref c-types col-nr) (aref sql-types col-nr) (aref out-len-ptrs col-nr) t))))))) names) ;; dispose of memory etc (when free-option (%free-statement hstmt free-option)) (dotimes (col-nr column-count) (let ((data-ptr (aref data-ptrs col-nr)) (out-len-ptr (aref out-len-ptrs col-nr))) (when data-ptr (free-foreign-object data-ptr)) ; we *did* allocate them (when out-len-ptr (free-foreign-object out-len-ptr))))))))) ;; to do: factor out common parts, put the sceleton (the obligatory macro part) ;; of %do-fetch into sql package (has been done) (defun %sql-prepare (hstmt sql) (with-cstring (sql-ptr sql) (with-error-handling (:hstmt hstmt) (SQLPrepare hstmt sql-ptr $SQL_NTS)))) ;; depending on option, we return a long int or a string; string not implemented (defun get-connection-option (hdbc option) (with-foreign-object (param-ptr #.$ODBC-LONG-TYPE) (with-error-handling (:hdbc hdbc) (SQLGetConnectOption hdbc option param-ptr) (deref-pointer param-ptr #.$ODBC-LONG-TYPE)))) (defun set-connection-option (hdbc option param) (with-error-handling (:hdbc hdbc) (SQLSetConnectOption hdbc option param))) (defun disable-autocommit (hdbc) (set-connection-option hdbc $SQL_AUTOCOMMIT $SQL_AUTOCOMMIT_OFF)) (defun enable-autocommit (hdbc) (set-connection-option hdbc $SQL_AUTOCOMMIT $SQL_AUTOCOMMIT_ON)) (defun %sql-set-pos (hstmt row option lock) (with-error-handling (:hstmt hstmt) (SQLSetPos hstmt row option lock))) (defun %sql-extended-fetch (hstmt fetch-type row) (with-foreign-objects ((row-count-ptr #.$ODBC-ULONG-TYPE) (row-status-ptr :short)) (with-error-handling (:hstmt hstmt) (SQLExtendedFetch hstmt fetch-type row row-count-ptr row-status-ptr) (values (deref-pointer row-count-ptr #.$ODBC-ULONG-TYPE) (deref-pointer row-status-ptr :short))))) ; column-nr is zero-based (defun %sql-get-data (hstmt column-nr c-type data-ptr precision out-len-ptr) (with-error-handling (:hstmt hstmt :print-info nil) (SQLGetData hstmt (if (eq column-nr :bookmark) 0 (1+ column-nr)) c-type data-ptr precision out-len-ptr))) (defun %sql-param-data (hstmt param-ptr) (with-error-handling (:hstmt hstmt :print-info t) ;; nil (SQLParamData hstmt param-ptr))) (defun %sql-put-data (hstmt data-ptr size) (with-error-handling (:hstmt hstmt :print-info t) ;; nil (SQLPutData hstmt data-ptr size))) (defconstant $sql-data-truncated (intern "01004" :keyword)) (defun read-data-in-chunks (hstmt column-nr data-ptr c-type sql-type out-len-ptr result-type) (declare (type long-ptr-type out-len-ptr) (ignore result-type)) (let* ((res (%sql-get-data hstmt column-nr c-type data-ptr +max-precision+ out-len-ptr)) (out-len (get-cast-long out-len-ptr)) (result (if (equal out-len #.$SQL_NULL_DATA) (return-from read-data-in-chunks *null*) ;;this isn't the most efficient way of doing it: ;;the foreign string gets copied to lisp, then ;;that is copied into the final string. However, ;;the previous impl that tried to copy one ;;character over at a time failed miserably on ;;multibyte characters. ;; ;;In the face of multibyte characters, the out-len ;;tells us the length in bytes but that doesn't ;;particularly help us here in allocating a lisp ;;array. So our best strategy is to just let the ;;foreign library that's already dealing with ;;encodings do its thing. (with-output-to-string (str) (loop do (if (= c-type #.$SQL_CHAR) (write-sequence (get-cast-foreign-string data-ptr) str) (error 'clsql:sql-database-error :message "wrong type. preliminary.")) while (and (= res $SQL_SUCCESS_WITH_INFO) (equal (sql-state +null-handle-ptr+ +null-handle-ptr+ hstmt) "01004")) do (setf res (%sql-get-data hstmt column-nr c-type data-ptr +max-precision+ out-len-ptr))))))) ;; reset the out length for the next row (setf (deref-pointer out-len-ptr #.$ODBC-LONG-TYPE) #.$SQL_NO_TOTAL) (if (= sql-type $SQL_DECIMAL) (let ((*read-base* 10)) (read-from-string result)) result))) (def-type c-timestamp-ptr-type (* (:struct sql-c-timestamp))) (def-type c-time-ptr-type (* (:struct sql-c-time))) (def-type c-date-ptr-type (* (:struct sql-c-date))) (defun timestamp-to-clsql-time (ptr) (declare (type c-timestamp-ptr-type ptr)) (clsql-sys:make-time :second (get-slot-value ptr 'sql-c-timestamp 'second) :minute (get-slot-value ptr 'sql-c-timestamp 'minute) :hour (get-slot-value ptr 'sql-c-timestamp 'hour) :day (get-slot-value ptr 'sql-c-timestamp 'day) :month (get-slot-value ptr 'sql-c-timestamp 'month) :year (get-slot-value ptr 'sql-c-timestamp 'year) :usec (let ((frac (get-slot-value ptr 'sql-c-timestamp 'fraction))) (if frac (/ frac 1000) 0)))) (defun universal-time-to-timestamp (time &optional (fraction 0)) "TODO: Dead function?" (multiple-value-bind (sec min hour day month year) (decode-universal-time time) (let ((ptr (allocate-foreign-object 'sql-c-timestamp))) (setf (get-slot-value ptr 'sql-c-timestamp 'second) sec (get-slot-value ptr 'sql-c-timestamp 'minute) min (get-slot-value ptr 'sql-c-timestamp 'hour) hour (get-slot-value ptr 'sql-c-timestamp 'day) day (get-slot-value ptr 'sql-c-timestamp 'month) month (get-slot-value ptr 'sql-c-timestamp 'year) year (get-slot-value ptr 'sql-c-timestamp 'fraction) fraction) ptr))) (defun %put-timestamp (ptr time &optional (fraction 0)) "TODO: Dead function?" (declare (type c-timestamp-ptr-type ptr)) (multiple-value-bind (sec min hour day month year) (decode-universal-time time) (setf (get-slot-value ptr 'sql-c-timestamp 'second) sec (get-slot-value ptr 'sql-c-timestamp 'minute) min (get-slot-value ptr 'sql-c-timestamp 'hour) hour (get-slot-value ptr 'sql-c-timestamp 'day) day (get-slot-value ptr 'sql-c-timestamp 'month) month (get-slot-value ptr 'sql-c-timestamp 'year) year (get-slot-value ptr 'sql-c-timestamp 'fraction) fraction) ptr)) (defun date-to-clsql-time (ptr) (declare (type c-date-ptr-type ptr)) (clsql-sys:make-time :second 0 :minute 0 :hour 0 :day (get-slot-value ptr 'sql-c-timestamp 'day) :month (get-slot-value ptr 'sql-c-timestamp 'month) :year (get-slot-value ptr 'sql-c-timestamp 'year))) (defun time-to-clsql-time (ptr) (declare (type c-time-ptr-type ptr)) (clsql-sys:make-time :second (get-slot-value ptr 'sql-c-timestamp 'second) :minute (get-slot-value ptr 'sql-c-timestamp 'minute) :hour (get-slot-value ptr 'sql-c-timestamp 'hour))) ;;; Added by KMR (defun %set-attr-odbc-version (henv version) (with-error-handling (:henv henv) ;;note that we are passing version as an integer that happens to be ;;stuffed into a pointer. ;;http://msdn.microsoft.com/en-us/library/ms709285%28v=VS.85%29.aspx (SQLSetEnvAttr henv $SQL_ATTR_ODBC_VERSION (make-pointer version :void) 0))) (defun %list-tables (hstmt) (with-error-handling (:hstmt hstmt) (SQLTables hstmt +null-ptr+ 0 +null-ptr+ 0 +null-ptr+ 0 +null-ptr+ 0))) (defun %table-statistics (table hstmt &key unique (ensure t) &aux (table (princ-to-string (clsql-sys::unescaped-database-identifier table)))) (with-cstrings ((table-cs table)) (with-error-handling (:hstmt hstmt) (SQLStatistics hstmt +null-ptr+ 0 +null-ptr+ 0 table-cs $SQL_NTS (if unique $SQL_INDEX_UNIQUE $SQL_INDEX_ALL) (if ensure $SQL_ENSURE $SQL_QUICK))))) (defun %list-data-sources (henv) (let ((results nil)) (with-foreign-strings ((dsn-ptr (1+ $SQL_MAX_DSN_LENGTH)) (desc-ptr 256)) (with-foreign-objects ((dsn-len :short) (desc-len :short)) (let ((res (with-error-handling (:henv henv) (SQLDataSources henv $SQL_FETCH_FIRST dsn-ptr (1+ $SQL_MAX_DSN_LENGTH) dsn-len desc-ptr 256 desc-len)))) (when (or (eql res $SQL_SUCCESS) (eql res $SQL_SUCCESS_WITH_INFO)) (push (convert-from-foreign-string dsn-ptr) results)) (do ((res (with-error-handling (:henv henv) (SQLDataSources henv $SQL_FETCH_NEXT dsn-ptr (1+ $SQL_MAX_DSN_LENGTH) dsn-len desc-ptr 256 desc-len)) (with-error-handling (:henv henv) (SQLDataSources henv $SQL_FETCH_NEXT dsn-ptr (1+ $SQL_MAX_DSN_LENGTH) dsn-len desc-ptr 256 desc-len)))) ((not (or (eql res $SQL_SUCCESS) (eql res $SQL_SUCCESS_WITH_INFO)))) (push (convert-from-foreign-string dsn-ptr) results))))) (nreverse results))) cl-sql-6.4.1/db-odbc/odbc-ff-interface.lisp0000644000175000017500000003362511610324732017360 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Package: odbc -*- ;;;; ************************************************************************* ;;;; FILE IDENTIFICATION ;;;; ;;;; Name: odbc-ff-interface.lisp ;;;; Purpose: Function definitions for UFFI interface to ODBC ;;;; Author: Kevin M. Rosenberg ;;;; ;;;; This file, part of CLSQL, is Copyright (c) 2004 by Kevin M. Rosenberg ;;;; and Copyright (C) Paul Meurer 1999 - 2001. All rights reserved. ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* (in-package #:odbc) (def-foreign-type sql-handle :pointer-void) (def-foreign-type sql-handle-ptr (* sql-handle)) (def-foreign-type string-ptr (* :unsigned-char)) (def-type long-ptr-type (* #.$ODBC-LONG-TYPE)) ;; ODBC3 (def-function "SQLAllocHandle" ((handle-type :short) (input-handle sql-handle) (*phenv sql-handle-ptr)) :module "odbc" :returning :short) ;; ODBC3 version of SQLFreeStmt, SQLFreeConnect, and SSQLFreeStmt (def-function "SQLFreeHandle" ((handle-type :short) ; HandleType (input-handle sql-handle)) ; Handle :module "odbc" :returning :short) ; RETCODE_SQL_API ;; deprecated (def-function "SQLAllocEnv" ((*phenv sql-handle-ptr) ; HENV FAR *phenv ) :module "odbc" :returning :short) ; RETCODE_SQL_API ;; deprecated (def-function "SQLAllocConnect" ((henv sql-handle) ; HENV henv (*phdbc sql-handle-ptr) ; HDBC FAR *phdbc ) :module "odbc" :returning :short) ; RETCODE_SQL_API (def-function "SQLConnect" ((hdbc sql-handle) ; HDBC hdbc (*szDSN :cstring) ; UCHAR FAR *szDSN (cbDSN :short) ; SWORD cbDSN (*szUID :cstring) ; UCHAR FAR *szUID (cbUID :short) ; SWORD cbUID (*szAuthStr :cstring) ; UCHAR FAR *szAuthStr (cbAuthStr :short) ; SWORD cbAuthStr ) :module "odbc" :returning :short) ; RETCODE_SQL_API (def-function "SQLDriverConnect" ((hdbc sql-handle) ; HDBC hdbc (hwnd sql-handle) ; SQLHWND hwnd (*szConnStrIn :cstring) ; UCHAR FAR *szConnStrIn (cbConnStrIn :short) ; SWORD cbConnStrIn (*szConnStrOut string-ptr) ; UCHAR FAR *szConnStrOut (cbConnStrOutMax :short) ; SWORD cbConnStrOutMax (*pcbConnStrOut :pointer-void) ; SWORD FAR *pcbConnStrOut (fDriverCompletion :short) ; UWORD fDriverCompletion ) :module "odbc" :returning :short) ; RETCODE_SQL_API (def-function "SQLDisconnect" ((hdbc sql-handle)) ; HDBC hdbc :module "odbc" :returning :short) ; RETCODE_SQL_API ;;deprecated (def-function "SQLFreeConnect" ((hdbc sql-handle)) ; HDBC hdbc :module "odbc" :returning :short) ; RETCODE_SQL_API ;; deprecated (def-function "SQLAllocStmt" ((hdbc sql-handle) ; HDBC hdbc (*phstmt sql-handle-ptr) ; HSTMT FAR *phstmt ) :module "odbc" :returning :short) ; RETCODE_SQL_API (def-function "SQLGetInfo" ((hdbc sql-handle) ; HDBC hdbc (fInfoType :short) ; UWORD fInfoType (rgbInfoValue :pointer-void) ; PTR rgbInfoValue (cbInfoValueMax :short) ; SWORD cbInfoValueMax (*pcbInfoValue :pointer-void) ; SWORD FAR *pcbInfoValue ) :module "odbc" :returning :short) ; RETCODE_SQL_API (def-function "SQLPrepare" ((hstmt sql-handle) ; HSTMT hstmt (*szSqlStr :cstring) ; UCHAR FAR *szSqlStr (cbSqlStr :int) ; SDWORD cbSqlStr ) :module "odbc" :returning :short) ; RETCODE_SQL_API (def-function "SQLExecute" ((hstmt sql-handle) ; HSTMT hstmt ) :module "odbc" :returning :short) ; RETCODE_SQL_API (def-function "SQLExecDirect" ((hstmt sql-handle) ; HSTMT hstmt (*szSqlStr :cstring) ; UCHAR FAR *szSqlStr (cbSqlStr :int) ; SDWORD cbSqlStr ) :module "odbc" :returning :short) ; RETCODE_SQL_API (def-function "SQLFreeStmt" ((hstmt sql-handle) ; HSTMT hstmt (fOption :short)) ; UWORD fOption :module "odbc" :returning :short) ; RETCODE_SQL_API (def-function "SQLCancel" ((hstmt sql-handle) ; HSTMT hstmt ) :module "odbc" :returning :short) ; RETCODE_SQL_API (def-function "SQLError" ((henv sql-handle) ; HENV henv (hdbc sql-handle) ; HDBC hdbc (hstmt sql-handle) ; HSTMT hstmt (*szSqlState string-ptr) ; UCHAR FAR *szSqlState (*pfNativeError (* :int)) ; SDWORD FAR *pfNativeError (*szErrorMsg string-ptr) ; UCHAR FAR *szErrorMsg (cbErrorMsgMax :short) ; SWORD cbErrorMsgMax (*pcbErrorMsg (* :short)) ; SWORD FAR *pcbErrorMsg ) :module "odbc" :returning :short) ; RETCODE_SQL_API (def-function "SQLNumResultCols" ((hstmt sql-handle) ; HSTMT hstmt (*pccol (* :short)) ; SWORD FAR *pccol ) :module "odbc" :returning :short) ; RETCODE_SQL_API (def-function "SQLRowCount" ((hstmt sql-handle) ; HSTMT hstmt (*pcrow (* :int)) ; SDWORD FAR *pcrow ) :module "odbc" :returning :short) ; RETCODE_SQL_API (def-function "SQLDescribeCol" ((hstmt sql-handle) ; HSTMT hstmt (icol :short) ; UWORD icol (*szColName string-ptr) ; UCHAR FAR *szColName (cbColNameMax :short) ; SWORD cbColNameMax (*pcbColName (* :short)) ; SWORD FAR *pcbColName (*pfSqlType (* :short)) ; SWORD FAR *pfSqlType (*pcbColDef (* #.$ODBC-ULONG-TYPE)) ; UDWORD FAR *pcbColDef (*pibScale (* :short)) ; SWORD FAR *pibScale (*pfNullable (* :short)) ; SWORD FAR *pfNullable ) :module "odbc" :returning :short) ; RETCODE_SQL_API (def-function "SQLColAttributes" ((hstmt sql-handle) ; HSTMT hstmt (icol :short) ; UWORD icol (fDescType :short) ; UWORD fDescType (rgbDesc string-ptr) ; PTR rgbDesc (cbDescMax :short) ; SWORD cbDescMax (*pcbDesc (* :short)) ; SWORD FAR *pcbDesc (*pfDesc (* :int)) ; SDWORD FAR *pfDesc ) :module "odbc" :returning :short) ; RETCODE_SQL_API (def-function "SQLColumns" ((hstmt sql-handle) ; HSTMT hstmt (*szTableQualifier :cstring) ; UCHAR FAR *szTableQualifier (cbTableQualifier :short) ; SWORD cbTableQualifier (*szTableOwner :cstring) ; UCHAR FAR *szTableOwner (cbTableOwner :short) ; SWORD cbTableOwner (*szTableName :cstring) ; UCHAR FAR *szTableName (cbTableName :short) ; SWORD cbTableName (*szColumnName :cstring) ; UCHAR FAR *szColumnName (cbColumnName :short) ; SWORD cbColumnName ) :module "odbc" :returning :short) ; RETCODE_SQL_API (def-function "SQLBindCol" ((hstmt sql-handle) ; HSTMT hstmt (icol :short) ; UWORD icol (fCType :short) ; SWORD fCType (rgbValue :pointer-void) ; PTR rgbValue (cbValueMax :int) ; SDWORD cbValueMax (*pcbValue (* :int)) ; SDWORD FAR *pcbValue ) :module "odbc" :returning :short) ; RETCODE_SQL_API (def-function "SQLFetch" ((hstmt sql-handle) ; HSTMT hstmt ) :module "odbc" :returning :short) ; RETCODE_SQL_API (def-function "SQLTransact" ((henv sql-handle) ; HENV henv (hdbc sql-handle) ; HDBC hdbc (fType :short) ; UWORD fType ($SQL_COMMIT or $SQL_ROLLBACK) ) :module "odbc" :returning :short) ; RETCODE_SQL_API ;; ODBC 2.0 (def-function "SQLDescribeParam" ((hstmt sql-handle) ; HSTMT hstmt (ipar :short) ; UWORD ipar (*pfSqlType (* :short)) ; SWORD FAR *pfSqlType (*pcbColDef (* :unsigned-int)) ; UDWORD FAR *pcbColDef (*pibScale (* :short)) ; SWORD FAR *pibScale (*pfNullable (* :short)) ; SWORD FAR *pfNullable ) :module "odbc" :returning :short) ; RETCODE_SQL_API ;; ODBC 2.0 (def-function "SQLBindParameter" ((hstmt sql-handle) ; HSTMT hstmt (ipar :short) ; UWORD ipar (fParamType :short) ; SWORD fParamType (fCType :short) ; SWORD fCType (fSqlType :short) ; SWORD fSqlType (cbColDef :int) ; UDWORD cbColDef (ibScale :short) ; SWORD ibScale (rgbValue :pointer-void) ; PTR rgbValue (cbValueMax :int) ; SDWORD cbValueMax (*pcbValue :pointer-void) ; SDWORD FAR *pcbValue ) :module "odbc" :returning :short) ; RETCODE_SQL_API ;; level 1 (def-function "SQLGetData" ((hstmt sql-handle) ; HSTMT hstmt (icol :short) ; UWORD icol (fCType :short) ; SWORD fCType (rgbValue :pointer-void) ; PTR rgbValue (cbValueMax :int) ; SDWORD cbValueMax (*pcbValue :pointer-void) ; SDWORD FAR *pcbValue ) :module "odbc" :returning :short) ; RETCODE_SQL_API (def-function "SQLParamData" ((hstmt sql-handle) ; HSTMT hstmt (*prgbValue :pointer-void) ; PTR FAR *prgbValue ) :module "odbc" :returning :short) ; RETCODE_SQL_API (def-function "SQLPutData" ((hstmt sql-handle) ; HSTMT hstmt (rgbValue :pointer-void) ; PTR rgbValue (cbValue :int) ; SDWORD cbValue ) :module "odbc" :returning :short) ; RETCODE_SQL_API (def-function "SQLGetConnectOption" ((hdbc sql-handle) ; HDBC hdbc (fOption :short) ; UWORD fOption (pvParam :pointer-void) ; PTR pvParam ) :module "odbc" :returning :short) ; RETCODE_SQL_API (def-function "SQLSetConnectOption" ((hdbc sql-handle) ; HDBC hdbc (fOption :short) ; UWORD fOption (vParam :int) ; UDWORD vParam ) :module "odbc" :returning :short) ; RETCODE_SQL_API (def-function "SQLSetPos" ((hstmt sql-handle) ; HSTMT hstmt (irow :short) ; UWORD irow (fOption :short) ; UWORD fOption (fLock :short) ; UWORD fLock ) :module "odbc" :returning :short) ; RETCODE_SQL_API ; level 2 (def-function "SQLExtendedFetch" ((hstmt sql-handle) ; HSTMT hstmt (fFetchType :short) ; UWORD fFetchType (irow :int) ; SDWORD irow (*pcrow :pointer-void) ; UDWORD FAR *pcrow (*rgfRowStatus :pointer-void) ; UWORD FAR *rgfRowStatus ) :module "odbc" :returning :short) ; RETCODE_SQL_API (def-function "SQLDataSources" ((henv sql-handle) ; HENV henv (fDirection :short) (*szDSN string-ptr) ; UCHAR FAR *szDSN (cbDSNMax :short) ; SWORD cbDSNMax (*pcbDSN (* :short)) ; SWORD *pcbDSN (*szDescription string-ptr) ; UCHAR *szDescription (cbDescriptionMax :short) ; SWORD cbDescriptionMax (*pcbDescription (* :short)) ; SWORD *pcbDescription ) :module "odbc" :returning :short) ; RETCODE_SQL_API (def-function "SQLFreeEnv" ((henv sql-handle) ; HSTMT hstmt ) :module "odbc" :returning :short) ; RETCODE_SQL_API ;;; foreign type definitions ;;(defmacro %sql-len-data-at-exec (length) ;; `(- $SQL_LEN_DATA_AT_EXEC_OFFSET ,length)) (def-struct sql-c-time (hour :short) (minute :short) (second :short)) (def-struct sql-c-date (year :short) (month :short) (day :short)) (def-struct sql-c-timestamp (year :short) (month :short) (day :short) (hour :short) (minute :short) (second :short) (fraction :int)) ;;; Added by KMR (def-function "SQLSetEnvAttr" ((henv sql-handle) ; HENV henv (attr :int) (*value :pointer-void) (szLength :int)) :module "odbc" :returning :short) (def-function "SQLGetEnvAttr" ((henv sql-handle) ; HENV henv (attr :int) (*value :pointer-void) (szLength :int) (string-length-ptr (* :int))) :module "odbc" :returning :short) (def-function "SQLTables" ((hstmt :pointer-void) (catalog-name :pointer-void) (catalog-name-length :short) (schema-name :pointer-void) (schema-name-length :short) (table-name :pointer-void) (table-name-length :short) (table-type-name :pointer-void) (table-type-name-length :short)) :module "odbc" :returning :short) (def-function "SQLStatistics" ((hstmt :pointer-void) (catalog-name :pointer-void) (catalog-name-length :short) (schema-name :pointer-void) (schema-name-length :short) (table-name :cstring) (table-name-length :short) (unique :short) (reserved :short)) :module "odbc" :returning :short) cl-sql-6.4.1/db-odbc/odbc-sql.lisp0000644000175000017500000001467612134025332015627 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; FILE IDENTIFICATION ;;;; ;;;; Name: odbc-sql.cl ;;;; Purpose: Medium-level interface for CLSQL ODBC backend ;;;; Programmer: Kevin M. Rosenberg ;;;; Date Started: Feb 2002 ;;;; ;;;; This file, part of CLSQL, is Copyright (c) 2002 by Kevin M. Rosenberg ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* (defpackage #:clsql-odbc (:use #:common-lisp #:clsql-sys) (:export #:odbc-database) (:documentation "This is the CLSQL interface to ODBC.")) (in-package #:clsql-odbc) ;; ODBC interface (defclass odbc-database (generic-odbc-database) ((odbc-db-type :accessor database-odbc-db-type))) (defmethod database-name-from-spec (connection-spec (database-type (eql :odbc))) (check-connection-spec connection-spec database-type (dsn user password &key connection-string completion window-handle)) (destructuring-bind (dsn user password &key connection-string completion window-handle) connection-spec (declare (ignore password connection-string completion window-handle)) (concatenate 'string dsn "/" user))) (defmethod database-connect (connection-spec (database-type (eql :odbc))) (check-connection-spec connection-spec database-type (dsn user password &key connection-string completion window-handle)) (destructuring-bind (dsn user password &key connection-string (completion :no-prompt) window-handle) connection-spec (handler-case (let ((db (make-instance 'odbc-database :name (database-name-from-spec connection-spec :odbc) :database-type :odbc :connection-spec connection-spec :dbi-package (find-package '#:odbc-dbi) :odbc-conn (odbc-dbi:connect :user user :password password :data-source-name dsn :connection-string connection-string :completion completion :window-handle window-handle)))) (store-type-of-connected-database db) ;; Ensure this database type is initialized so can check capabilities of ;; underlying database (initialize-database-type :database-type database-type) db) #+ignore (error () ;; Init or Connect failed (error 'sql-connection-error :database-type database-type :connection-spec connection-spec :message "Connection failed"))))) (defmethod database-underlying-type ((database odbc-database)) (database-odbc-db-type database)) (defun store-type-of-connected-database (db) (let* ((odbc-conn (clsql-sys::odbc-conn db)) (server-name (odbc-dbi::get-odbc-info odbc-conn odbc::$SQL_SERVER_NAME)) (dbms-name (odbc-dbi::get-odbc-info odbc-conn odbc::$SQL_DBMS_NAME)) (type ;; need SERVER-NAME and DBMS-NAME because many drivers mix this up (cond ((or (search "postgresql" server-name :test #'char-equal) (search "postgresql" dbms-name :test #'char-equal)) (unless (find-package 'clsql-postgresql) (ignore-errors (asdf:operate 'asdf:load-op 'clsql-postgresql-socket))) :postgresql) ((or (search "Microsoft SQL Server" server-name :test #'char-equal) (search "Microsoft SQL Server" dbms-name :test #'char-equal)) :mssql) ((or (search "mysql" server-name :test #'char-equal) (search "mysql" dbms-name :test #'char-equal)) (unless (find-package 'clsql-mysql) ;; ignore errors on platforms where the shared libraries are not available (ignore-errors (asdf:operate 'asdf:load-op 'clsql-mysql))) :mysql) ((or (search "oracle" server-name :test #'char-equal) (search "oracle" dbms-name :test #'char-equal)) :oracle)))) (setf (database-odbc-db-type db) type))) (defmethod database-create (connection-spec (type (eql :odbc))) (declare (ignore connection-spec)) (warn "Not implemented.")) (defmethod database-destroy (connection-spec (type (eql :odbc))) (declare (ignore connection-spec)) (warn "Not implemented.")) (defmethod database-probe (connection-spec (type (eql :odbc))) (when (find (car connection-spec) (database-list connection-spec type) :test #'string-equal) t)) (defmethod database-list (connection-spec (type (eql :odbc))) (declare (ignore connection-spec)) (odbc-dbi:list-all-data-sources)) (defmethod database-list-indexes ((database odbc-database) &key (owner nil)) (let ((result '())) (dolist (table (database-list-tables database :owner owner) result) (setq result (append (database-list-table-indexes table database :owner owner) result))))) (defmethod database-list-table-indexes (table (database odbc-database) &key (owner nil)) (declare (ignore owner)) (multiple-value-bind (rows col-names) (odbc-dbi:list-table-indexes table :db (clsql-sys::odbc-conn database)) (declare (ignore col-names)) ;; INDEX_NAME is hard-coded in sixth position by ODBC driver ;; FIXME: ??? is hard-coded in the fourth position (do ((results nil) (loop-rows rows (cdr loop-rows))) ((null loop-rows) (nreverse results)) (let* ((row (car loop-rows)) (col (nth 5 row))) (unless (or (null col) (find col results :test #'string-equal)) (push col results)))))) ;;; Database capabilities (defmethod db-backend-has-create/destroy-db? ((db-type (eql :odbc))) nil) (defmethod database-initialize-database-type ((database-type (eql :odbc))) ;; nothing to do t) (when (clsql-sys:database-type-library-loaded :odbc) (clsql-sys:initialize-database-type :database-type :odbc)) cl-sql-6.4.1/db-odbc/odbc-package.lisp0000644000175000017500000000347111673670205016426 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; FILE IDENTIFICATION ;;;; ;;;; Name: odbc-package.lisp ;;;; Purpose: Package definition for low-level ODBC interface ;;;; Author: Kevin M. Rosenberg ;;;; Created: April 2004 ;;;; ;;;; This file, part of CLSQL, is Copyright (c) 2004 by Kevin M. Rosenberg ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* (in-package #:cl-user) (defpackage #:odbc (:use #:cl #:uffi) (:export #:database-library-loaded #:*null* #:+null-ptr+ #:+max-precision+ #:*info-output* #:*time-format* #:get-cast-long #:%free-statement #:%disconnect #:%commit #:%rollback #:%sql-fetch #:%sql-cancel #:db-connect #:%new-db-connection-handle #:%new-environment-handle #:%sql-connect #:%sql-driver-connect #:disable-autocommit #:enable-autocommit #:%sql-free-environment #:%sql-data-sources #:%sql-get-info #:%sql-param-data #:%sql-execute #:%put-str #:%sql-bind-parameter #:%sql-prepare #:sqlfetch #:%bind-column #:%allocate-bindings #:%describe-column #:%describe-columns #:read-data #:read-data-in-chunks #:query-database #:%new-statement-handle #:%sql-exec-direct #:result-columns-count #:result-rows-count #:sql-to-c-type #:%list-tables #:%table-statistics #:%list-data-sources ) (:documentation "This is the low-level interface ODBC.")) cl-sql-6.4.1/db-odbc/Makefile0000644000175000017500000000126211335067642014671 0ustar kevinkevin#!/usr/bin/make ########################################################################## # FILE IDENTIFICATION # # Name: Makefile # Purpose: Makefile for CLSQL SQL interface # Programer: Kevin M. Rosenberg # Date Started: Mar 2002 # # This file, part of CLSQL, is Copyright (c) 2002 by Kevin M. Rosenberg # # CLSQL users are granted the rights to distribute and use this software # as governed by the terms of the Lisp Lesser GNU Public License # (http://opensource.franz.com/preamble.html), also known as the LLGPL. ########################################################################## SUBDIRS= include ../Makefile.common .PHONY: distclean distclean: clean cl-sql-6.4.1/db-odbc/odbc-constants.lisp0000644000175000017500000011621411610324732017037 0ustar kevinkevin ;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Package: odbc -*- ;;;; ************************************************************************* ;;;; FILE IDENTIFICATION ;;;; ;;;; Name: odbc-constants.lisp ;;;; Purpose: Constants for UFFI interface to ODBC ;;;; Authors: Kevin M. Rosenberg and Paul Meurer ;;;; ;;;; This file, part of CLSQL, is Copyright (c) 2004 by Kevin M. Rosenberg ;;;; and Copyright (C) Paul Meurer 1999 - 2001. All rights reserved. ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* (in-package #:odbc) ;; on SuSE AMD64 9.0, unixODBC is compiled with with SQLLEN being 4 bytes long (defconstant $ODBC-LONG-TYPE :int) (defconstant $ODBC-ULONG-TYPE :unsigned-int) (defconstant $ODBC-BIG-TYPE :long-long) ;; (defconstant $ODBCVER #x0210) ;; for new SQLAllocHandle functiion (defconstant $SQL_HANDLE_ENV 1) (defconstant $SQL_HANDLE_DBC 2) (defconstant $SQL_HANDLE_STMT 3) (defconstant $SQL_HANDLE_DESC 4) ;; generally useful constants (defconstant $SQL_SPEC_MAJOR 2) ;; Major version of specification (defconstant $SQL_SPEC_MINOR 10) ;; Minor version of specification (defvar $SQL_SPEC_STRING "02.10") ;; String constant for version (defconstant $SQL_SQLSTATE_SIZE 5) ;; size of SQLSTATE (defconstant $SQL_MAX_MESSAGE_LENGTH 512) ;; message buffer size (defconstant $SQL_MAX_DSN_LENGTH 32) ;; maximum data source name size ;; RETCODEs (defconstant $SQL_INVALID_HANDLE -2) (defconstant $SQL_ERROR -1) (defconstant $SQL_SUCCESS 0) (defconstant $SQL_SUCCESS_WITH_INFO 1) (defconstant $SQL_NO_DATA_FOUND 100) ;; Standard SQL datatypes, using ANSI type numbering (defconstant $SQL_CHAR 1) (defconstant $SQL_NUMERIC 2) (defconstant $SQL_DECIMAL 3) (defconstant $SQL_INTEGER 4) (defconstant $SQL_SMALLINT 5) (defconstant $SQL_FLOAT 6) (defconstant $SQL_REAL 7) (defconstant $SQL_DOUBLE 8) (defconstant $SQL_VARCHAR 12) (defconstant $SQL_TYPE_MIN $SQL_CHAR) (defconstant $SQL_TYPE_NULL 0) (defconstant $SQL_TYPE_MAX $SQL_VARCHAR) ;; C datatype to SQL datatype mapping SQL types (defconstant $SQL_C_CHAR $SQL_CHAR) ;; CHAR, VARCHAR, DECIMAL, NUMERIC (defconstant $SQL_C_LONG $SQL_INTEGER) ;; INTEGER (defconstant $SQL_C_SHORT $SQL_SMALLINT) ;; SMALLINT (defconstant $SQL_C_FLOAT $SQL_REAL) ;; REAL (defconstant $SQL_C_DOUBLE $SQL_DOUBLE) ;; FLOAT, DOUBLE (defconstant $SQL_C_DEFAULT 99) ;; NULL status constants. These are used in SQLColumns, SQLColAttributes, ;;SQLDescribeCol, SQLDescribeParam, and SQLSpecialColumns to describe the ;;nullablity of a column in a table. (defconstant $SQL_NO_NULLS 0) (defconstant $SQL_NULLABLE 1) (defconstant $SQL_NULLABLE_UNKNOWN 2) ;; Special length values (defconstant $SQL_NULL_DATA -1) (defconstant $SQL_DATA_AT_EXEC -2) (defconstant $SQL_NTS -3) ;; SQLFreeStmt defines (defconstant $SQL_CLOSE 0) (defconstant $SQL_DROP 1) (defconstant $SQL_UNBIND 2) (defconstant $SQL_RESET_PARAMS 3) ;; SQLTransact defines (defconstant $SQL_COMMIT 0) (defconstant $SQL_ROLLBACK 1) ;; SQLColAttributes defines (defconstant $SQL_COLUMN_COUNT 0) (defconstant $SQL_COLUMN_NAME 1) (defconstant $SQL_COLUMN_TYPE 2) (defconstant $SQL_COLUMN_LENGTH 3) (defconstant $SQL_COLUMN_PRECISION 4) (defconstant $SQL_COLUMN_SCALE 5) (defconstant $SQL_COLUMN_DISPLAY_SIZE 6) (defconstant $SQL_COLUMN_NULLABLE 7) (defconstant $SQL_COLUMN_UNSIGNED 8) (defconstant $SQL_COLUMN_MONEY 9) (defconstant $SQL_COLUMN_UPDATABLE 10) (defconstant $SQL_COLUMN_AUTO_INCREMENT 11) (defconstant $SQL_COLUMN_CASE_SENSITIVE 12) (defconstant $SQL_COLUMN_SEARCHABLE 13) (defconstant $SQL_COLUMN_TYPE_NAME 14) (defconstant $SQL_COLUMN_TABLE_NAME 15) (defconstant $SQL_COLUMN_OWNER_NAME 16) (defconstant $SQL_COLUMN_QUALIFIER_NAME 17) (defconstant $SQL_COLUMN_LABEL 18) (defconstant $SQL_COLATT_OPT_MAX $SQL_COLUMN_LABEL) (defconstant $SQL_COLUMN_DRIVER_START 1000) (defconstant $SQL_COLATT_OPT_MIN $SQL_COLUMN_COUNT) ;; SQLColAttributes subdefines for SQL_COLUMN_UPDATABLE (defconstant $SQL_ATTR_READONLY 0) (defconstant $SQL_ATTR_WRITE 1) (defconstant $SQL_ATTR_READWRITE_UNKNOWN 2) ;; SQLColAttributes subdefines for SQL_COLUMN_SEARCHABLE ;; These are also used by SQLGetInfo (defconstant $SQL_UNSEARCHABLE 0) (defconstant $SQL_LIKE_ONLY 1) (defconstant $SQL_ALL_EXCEPT_LIKE 2) (defconstant $SQL_SEARCHABLE 3) ;; SQLError defines (defconstant $SQL_NULL_HENV 0) (defconstant $SQL_NULL_HDBC 0) (defconstant $SQL_NULL_HSTMT 0) ;; Defines for SQLGetFunctions ;; Core Functions ;; (defconstant $SQL_API_SQLALLOCCONNECT 1) (defconstant $SQL_API_SQLALLOCENV 2) (defconstant $SQL_API_SQLALLOCSTMT 3) (defconstant $SQL_API_SQLBINDCOL 4) (defconstant $SQL_API_SQLCANCEL 5) (defconstant $SQL_API_SQLCOLATTRIBUTES 6) (defconstant $SQL_API_SQLCONNECT 7) (defconstant $SQL_API_SQLDESCRIBECOL 8) (defconstant $SQL_API_SQLDISCONNECT 9) (defconstant $SQL_API_SQLERROR 10) (defconstant $SQL_API_SQLEXECDIRECT 11) (defconstant $SQL_API_SQLEXECUTE 12) (defconstant $SQL_API_SQLFETCH 13) (defconstant $SQL_API_SQLFREECONNECT 14) (defconstant $SQL_API_SQLFREEENV 15) (defconstant $SQL_API_SQLFREESTMT 16) (defconstant $SQL_API_SQLGETCURSORNAME 17) (defconstant $SQL_API_SQLNUMRESULTCOLS 18) (defconstant $SQL_API_SQLPREPARE 19) (defconstant $SQL_API_SQLROWCOUNT 20) (defconstant $SQL_API_SQLSETCURSORNAME 21) (defconstant $SQL_API_SQLSETPARAM 22) (defconstant $SQL_API_SQLTRANSACT 23) (defconstant $SQL_NUM_FUNCTIONS 23) (defconstant $SQL_EXT_API_START 40) ;; Level 1 Functions (defconstant $SQL_API_SQLCOLUMNS 40) (defconstant $SQL_API_SQLDRIVERCONNECT 41) (defconstant $SQL_API_SQLGETCONNECTOPTION 42) (defconstant $SQL_API_SQLGETDATA 43) (defconstant $SQL_API_SQLGETFUNCTIONS 44) (defconstant $SQL_API_SQLGETINFO 45) (defconstant $SQL_API_SQLGETSTMTOPTION 46) (defconstant $SQL_API_SQLGETTYPEINFO 47) (defconstant $SQL_API_SQLPARAMDATA 48) (defconstant $SQL_API_SQLPUTDATA 49) (defconstant $SQL_API_SQLSETCONNECTOPTION 50) (defconstant $SQL_API_SQLSETSTMTOPTION 51) (defconstant $SQL_API_SQLSPECIALCOLUMNS 52) (defconstant $SQL_API_SQLSTATISTICS 53) (defconstant $SQL_API_SQLTABLES 54) ;; Level 2 Functions (defconstant $SQL_API_SQLBROWSECONNECT 55) (defconstant $SQL_API_SQLCOLUMNPRIVILEGES 56) (defconstant $SQL_API_SQLDATASOURCES 57) (defconstant $SQL_API_SQLDESCRIBEPARAM 58) (defconstant $SQL_API_SQLEXTENDEDFETCH 59) (defconstant $SQL_API_SQLFOREIGNKEYS 60) (defconstant $SQL_API_SQLMORERESULTS 61) (defconstant $SQL_API_SQLNATIVESQL 62) (defconstant $SQL_API_SQLNUMPARAMS 63) (defconstant $SQL_API_SQLPARAMOPTIONS 64) (defconstant $SQL_API_SQLPRIMARYKEYS 65) (defconstant $SQL_API_SQLPROCEDURECOLUMNS 66) (defconstant $SQL_API_SQLPROCEDURES 67) (defconstant $SQL_API_SQLSETPOS 68) (defconstant $SQL_API_SQLSETSCROLLOPTIONS 69) (defconstant $SQL_API_SQLTABLEPRIVILEGES 70) ;/* SDK 2.0 Additions */ (defconstant $SQL_API_SQLDRIVERS 71) (defconstant $SQL_API_SQLBINDPARAMETER 72) (defconstant $SQL_EXT_API_LAST $SQL_API_SQLBINDPARAMETER) (defconstant $SQL_API_ALL_FUNCTIONS 0) (defconstant $SQL_NUM_EXTENSIONS (- $SQL_EXT_API_LAST $SQL_EXT_API_START -1)) (defconstant $SQL_API_LOADBYORDINAL 199) ;;; Defines for SQLGetInfo (defconstant $SQL_INFO_FIRST 0) (defconstant $SQL_ACTIVE_CONNECTIONS 0) (defconstant $SQL_ACTIVE_STATEMENTS 1) (defconstant $SQL_DATA_SOURCE_NAME 2) (defconstant $SQL_DRIVER_HDBC 3) (defconstant $SQL_DRIVER_HENV 4) (defconstant $SQL_DRIVER_HSTMT 5) (defconstant $SQL_DRIVER_NAME 6) (defconstant $SQL_DRIVER_VER 7) (defconstant $SQL_FETCH_DIRECTION 8) (defconstant $SQL_ODBC_API_CONFORMANCE 9) (defconstant $SQL_ODBC_VER 10) (defconstant $SQL_ROW_UPDATES 11) (defconstant $SQL_ODBC_SAG_CLI_CONFORMANCE 12) (defconstant $SQL_SERVER_NAME 13) (defconstant $SQL_SEARCH_PATTERN_ESCAPE 14) (defconstant $SQL_ODBC_SQL_CONFORMANCE 15) (defconstant $SQL_DBMS_NAME 17) (defconstant $SQL_DBMS_VER 18) (defconstant $SQL_ACCESSIBLE_TABLES 19) (defconstant $SQL_ACCESSIBLE_PROCEDURES 20) (defconstant $SQL_PROCEDURES 21) (defconstant $SQL_CONCAT_NULL_BEHAVIOR 22) (defconstant $SQL_CURSOR_COMMIT_BEHAVIOR 23) (defconstant $SQL_CURSOR_ROLLBACK_BEHAVIOR 24) (defconstant $SQL_DATA_SOURCE_READ_ONLY 25) (defconstant $SQL_DEFAULT_TXN_ISOLATION 26) (defconstant $SQL_EXPRESSIONS_IN_ORDERBY 27) (defconstant $SQL_IDENTIFIER_CASE 28) (defconstant $SQL_IDENTIFIER_QUOTE_CHAR 29) (defconstant $SQL_MAX_COLUMN_NAME_LEN 30) (defconstant $SQL_MAX_CURSOR_NAME_LEN 31) (defconstant $SQL_MAX_OWNER_NAME_LEN 32) (defconstant $SQL_MAX_PROCEDURE_NAME_LEN 33) (defconstant $SQL_MAX_QUALIFIER_NAME_LEN 34) (defconstant $SQL_MAX_TABLE_NAME_LEN 35) (defconstant $SQL_MULT_RESULT_SETS 36) (defconstant $SQL_MULTIPLE_ACTIVE_TXN 37) (defconstant $SQL_OUTER_JOINS 38) (defconstant $SQL_OWNER_TERM 39) (defconstant $SQL_PROCEDURE_TERM 40) (defconstant $SQL_QUALIFIER_NAME_SEPARATOR 41) (defconstant $SQL_QUALIFIER_TERM 42) (defconstant $SQL_SCROLL_CONCURRENCY 43) (defconstant $SQL_SCROLL_OPTIONS 44) (defconstant $SQL_TABLE_TERM 45) (defconstant $SQL_TXN_CAPABLE 46) (defconstant $SQL_USER_NAME 47) (defconstant $SQL_CONVERT_FUNCTIONS 48) (defconstant $SQL_NUMERIC_FUNCTIONS 49) (defconstant $SQL_STRING_FUNCTIONS 50) (defconstant $SQL_SYSTEM_FUNCTIONS 51) (defconstant $SQL_TIMEDATE_FUNCTIONS 52) (defconstant $SQL_CONVERT_BIGINT 53) (defconstant $SQL_CONVERT_BINARY 54) (defconstant $SQL_CONVERT_BIT 55) (defconstant $SQL_CONVERT_CHAR 56) (defconstant $SQL_CONVERT_DATE 57) (defconstant $SQL_CONVERT_DECIMAL 58) (defconstant $SQL_CONVERT_DOUBLE 59) (defconstant $SQL_CONVERT_FLOAT 60) (defconstant $SQL_CONVERT_INTEGER 61) (defconstant $SQL_CONVERT_LONGVARCHAR 62) (defconstant $SQL_CONVERT_NUMERIC 63) (defconstant $SQL_CONVERT_REAL 64) (defconstant $SQL_CONVERT_SMALLINT 65) (defconstant $SQL_CONVERT_TIME 66) (defconstant $SQL_CONVERT_TIMESTAMP 67) (defconstant $SQL_CONVERT_TINYINT 68) (defconstant $SQL_CONVERT_VARBINARY 69) (defconstant $SQL_CONVERT_VARCHAR 70) (defconstant $SQL_CONVERT_LONGVARBINARY 71) (defconstant $SQL_TXN_ISOLATION_OPTION 72) (defconstant $SQL_ODBC_SQL_OPT_IEF 73) ;;; ODBC SDK 1.0 Additions (defconstant $SQL_CORRELATION_NAME 74) (defconstant $SQL_NON_NULLABLE_COLUMNS 75) ;;; ODBC SDK 2.0 Additions (defconstant $SQL_DRIVER_HLIB 76) (defconstant $SQL_DRIVER_ODBC_VER 77) (defconstant $SQL_LOCK_TYPES 78) (defconstant $SQL_POS_OPERATIONS 79) (defconstant $SQL_POSITIONED_STATEMENTS 80) (defconstant $SQL_GETDATA_EXTENSIONS 81) (defconstant $SQL_BOOKMARK_PERSISTENCE 82) (defconstant $SQL_STATIC_SENSITIVITY 83) (defconstant $SQL_FILE_USAGE 84) (defconstant $SQL_NULL_COLLATION 85) (defconstant $SQL_ALTER_TABLE 86) (defconstant $SQL_COLUMN_ALIAS 87) (defconstant $SQL_GROUP_BY 88) (defconstant $SQL_KEYWORDS 89) (defconstant $SQL_ORDER_BY_COLUMNS_IN_SELECT 90) (defconstant $SQL_OWNER_USAGE 91) (defconstant $SQL_QUALIFIER_USAGE 92) (defconstant $SQL_QUOTED_IDENTIFIER_CASE 93) (defconstant $SQL_SPECIAL_CHARACTERS 94) (defconstant $SQL_SUBQUERIES 95) (defconstant $SQL_UNION 96) (defconstant $SQL_MAX_COLUMNS_IN_GROUP_BY 97) (defconstant $SQL_MAX_COLUMNS_IN_INDEX 98) (defconstant $SQL_MAX_COLUMNS_IN_ORDER_BY 99) (defconstant $SQL_MAX_COLUMNS_IN_SELECT 100) (defconstant $SQL_MAX_COLUMNS_IN_TABLE 101) (defconstant $SQL_MAX_INDEX_SIZE 102) (defconstant $SQL_MAX_ROW_SIZE_INCLUDES_LONG 103) (defconstant $SQL_MAX_ROW_SIZE 104) (defconstant $SQL_MAX_STATEMENT_LEN 105) (defconstant $SQL_MAX_TABLES_IN_SELECT 106) (defconstant $SQL_MAX_USER_NAME_LEN 107) (defconstant $SQL_MAX_CHAR_LITERAL_LEN 108) (defconstant $SQL_TIMEDATE_ADD_INTERVALS 109) (defconstant $SQL_TIMEDATE_DIFF_INTERVALS 110) (defconstant $SQL_NEED_LONG_DATA_LEN 111) (defconstant $SQL_MAX_BINARY_LITERAL_LEN 112) (defconstant $SQL_LIKE_ESCAPE_CLAUSE 113) (defconstant $SQL_QUALIFIER_LOCATION 114) (defconstant $SQL_ACTIVE_ENVIRONMENTS 116) #| /*** ODBC SDK 2.01 Additions ***/) (defconstant $SQL_OJ_CAPABILITIES 65003 ;; Temp value until ODBC 3.0 (defconstant $SQL_INFO_LAST SQL_QUALIFIER_LOCATION ) (defconstant $SQL_INFO_DRIVER_START 1000 ;; SQL_CONVERT_* return value bitmasks ) (defconstant $SQL_CVT_CHAR #x00000001L) (defconstant $SQL_CVT_NUMERIC #x00000002L) (defconstant $SQL_CVT_DECIMAL #x00000004L) (defconstant $SQL_CVT_INTEGER #x00000008L) (defconstant $SQL_CVT_SMALLINT #x00000010L) (defconstant $SQL_CVT_FLOAT #x00000020L) (defconstant $SQL_CVT_REAL #x00000040L) (defconstant $SQL_CVT_DOUBLE #x00000080L) (defconstant $SQL_CVT_VARCHAR #x00000100L) (defconstant $SQL_CVT_LONGVARCHAR #x00000200L) (defconstant $SQL_CVT_BINARY #x00000400L) (defconstant $SQL_CVT_VARBINARY #x00000800L) (defconstant $SQL_CVT_BIT #x00001000L) (defconstant $SQL_CVT_TINYINT #x00002000L) (defconstant $SQL_CVT_BIGINT #x00004000L) (defconstant $SQL_CVT_DATE #x00008000L) (defconstant $SQL_CVT_TIME #x00010000L) (defconstant $SQL_CVT_TIMESTAMP #x00020000L) (defconstant $SQL_CVT_LONGVARBINARY #x00040000L) ;; SQL_CONVERT_FUNCTIONS functions) (defconstant $SQL_FN_CVT_CONVERT #x00000001L) ;; SQL_STRING_FUNCTIONS functions (defconstant $SQL_FN_STR_CONCAT #x00000001L) (defconstant $SQL_FN_STR_INSERT #x00000002L) (defconstant $SQL_FN_STR_LEFT #x00000004L) (defconstant $SQL_FN_STR_LTRIM #x00000008L) (defconstant $SQL_FN_STR_LENGTH #x00000010L) (defconstant $SQL_FN_STR_LOCATE #x00000020L) (defconstant $SQL_FN_STR_LCASE #x00000040L) (defconstant $SQL_FN_STR_REPEAT #x00000080L) (defconstant $SQL_FN_STR_REPLACE #x00000100L) (defconstant $SQL_FN_STR_RIGHT #x00000200L) (defconstant $SQL_FN_STR_RTRIM #x00000400L) (defconstant $SQL_FN_STR_SUBSTRING #x00000800L) (defconstant $SQL_FN_STR_UCASE #x00001000L) (defconstant $SQL_FN_STR_ASCII #x00002000L) (defconstant $SQL_FN_STR_CHAR #x00004000L (defconstant $SQL_FN_STR_DIFFERENCE #x00008000L) (defconstant $SQL_FN_STR_LOCATE_2 #x00010000L) (defconstant $SQL_FN_STR_SOUNDEX #x00020000L) (defconstant $SQL_FN_STR_SPACE #x00040000L ;; SQL_NUMERIC_FUNCTIONS functions ) (defconstant $SQL_FN_NUM_ABS #x00000001L) (defconstant $SQL_FN_NUM_ACOS #x00000002L) (defconstant $SQL_FN_NUM_ASIN #x00000004L) (defconstant $SQL_FN_NUM_ATAN #x00000008L) (defconstant $SQL_FN_NUM_ATAN2 #x00000010L) (defconstant $SQL_FN_NUM_CEILING #x00000020L) (defconstant $SQL_FN_NUM_COS #x00000040L) (defconstant $SQL_FN_NUM_COT #x00000080L) (defconstant $SQL_FN_NUM_EXP #x00000100L) (defconstant $SQL_FN_NUM_FLOOR #x00000200L) (defconstant $SQL_FN_NUM_LOG #x00000400L) (defconstant $SQL_FN_NUM_MOD #x00000800L) (defconstant $SQL_FN_NUM_SIGN #x00001000L) (defconstant $SQL_FN_NUM_SIN #x00002000L) (defconstant $SQL_FN_NUM_SQRT #x00004000L) (defconstant $SQL_FN_NUM_TAN #x00008000L) (defconstant $SQL_FN_NUM_PI #x00010000L) (defconstant $SQL_FN_NUM_RAND #x00020000L (defconstant $SQL_FN_NUM_DEGREES #x00040000L) (defconstant $SQL_FN_NUM_LOG10 #x00080000L) (defconstant $SQL_FN_NUM_POWER #x00100000L) (defconstant $SQL_FN_NUM_RADIANS #x00200000L) (defconstant $SQL_FN_NUM_ROUND #x00400000L) (defconstant $SQL_FN_NUM_TRUNCATE #x00800000L ;; SQL_TIMEDATE_FUNCTIONS functions ) (defconstant $SQL_FN_TD_NOW #x00000001L) (defconstant $SQL_FN_TD_CURDATE #x00000002L) (defconstant $SQL_FN_TD_DAYOFMONTH #x00000004L) (defconstant $SQL_FN_TD_DAYOFWEEK #x00000008L) (defconstant $SQL_FN_TD_DAYOFYEAR #x00000010L) (defconstant $SQL_FN_TD_MONTH #x00000020L) (defconstant $SQL_FN_TD_QUARTER #x00000040L) (defconstant $SQL_FN_TD_WEEK #x00000080L) (defconstant $SQL_FN_TD_YEAR #x00000100L) (defconstant $SQL_FN_TD_CURTIME #x00000200L) (defconstant $SQL_FN_TD_HOUR #x00000400L) (defconstant $SQL_FN_TD_MINUTE #x00000800L) (defconstant $SQL_FN_TD_SECOND #x00001000L (defconstant $SQL_FN_TD_TIMESTAMPADD #x00002000L) (defconstant $SQL_FN_TD_TIMESTAMPDIFF #x00004000L) (defconstant $SQL_FN_TD_DAYNAME #x00008000L) (defconstant $SQL_FN_TD_MONTHNAME #x00010000L ;; SQL_SYSTEM_FUNCTIONS functions ) (defconstant $SQL_FN_SYS_USERNAME #x00000001L) (defconstant $SQL_FN_SYS_DBNAME #x00000002L) (defconstant $SQL_FN_SYS_IFNULL #x00000004L ;; SQL_TIMEDATE_ADD_INTERVALS and SQL_TIMEDATE_DIFF_INTERVALS functions (defconstant $SQL_FN_TSI_FRAC_SECOND #x00000001L) (defconstant $SQL_FN_TSI_SECOND #x00000002L) (defconstant $SQL_FN_TSI_MINUTE #x00000004L) (defconstant $SQL_FN_TSI_HOUR #x00000008L) (defconstant $SQL_FN_TSI_DAY #x00000010L) (defconstant $SQL_FN_TSI_WEEK #x00000020L) (defconstant $SQL_FN_TSI_MONTH #x00000040L) (defconstant $SQL_FN_TSI_QUARTER #x00000080L) (defconstant $SQL_FN_TSI_YEAR #x00000100L ;; SQL_ODBC_API_CONFORMANCE values ) (defconstant $SQL_OAC_NONE #x0000) (defconstant $SQL_OAC_LEVEL1 #x0001) (defconstant $SQL_OAC_LEVEL2 #x0002 ;; SQL_ODBC_SAG_CLI_CONFORMANCE values ) (defconstant $SQL_OSCC_NOT_COMPLIANT #x0000) (defconstant $SQL_OSCC_COMPLIANT #x0001 ;; SQL_ODBC_SQL_CONFORMANCE values ) (defconstant $SQL_OSC_MINIMUM #x0000) (defconstant $SQL_OSC_CORE #x0001) (defconstant $SQL_OSC_EXTENDED #x0002 ;; SQL_CONCAT_NULL_BEHAVIOR values ) (defconstant $SQL_CB_NULL #x0000) (defconstant $SQL_CB_NON_NULL #x0001 ;; SQL_CURSOR_COMMIT_BEHAVIOR and SQL_CURSOR_ROLLBACK_BEHAVIOR values ) (defconstant $SQL_CB_DELETE #x0000) (defconstant $SQL_CB_CLOSE #x0001) (defconstant $SQL_CB_PRESERVE #x0002 ;; SQL_IDENTIFIER_CASE values ) (defconstant $SQL_IC_UPPER #x0001) (defconstant $SQL_IC_LOWER #x0002) (defconstant $SQL_IC_SENSITIVE #x0003) (defconstant $SQL_IC_MIXED #x0004 ;; SQL_TXN_CAPABLE values |# (defconstant $SQL_TC_NONE 0) (defconstant $SQL_TC_DML 1) (defconstant $SQL_TC_ALL 2) (defconstant $SQL_TC_DDL_COMMIT 3) (defconstant $SQL_TC_DDL_IGNORE 4) ;; SQL_SCROLL_OPTIONS masks (defconstant $SQL_SO_FORWARD_ONLY #x00000001) (defconstant $SQL_SO_KEYSET_DRIVEN #x00000002) (defconstant $SQL_SO_DYNAMIC #x00000004) (defconstant $SQL_SO_MIXED #x00000008) (defconstant $SQL_SO_STATIC #x00000010) ;; SQL_SCROLL_CONCURRENCY masks (defconstant $SQL_SCCO_READ_ONLY #x00000001) (defconstant $SQL_SCCO_LOCK #x00000002) (defconstant $SQL_SCCO_OPT_ROWVER #x00000004) (defconstant $SQL_SCCO_OPT_VALUES #x00000008) ;; SQL_FETCH_DIRECTION masks (defconstant $SQL_FD_FETCH_NEXT #x00000001) (defconstant $SQL_FD_FETCH_FIRST #x00000002) (defconstant $SQL_FD_FETCH_LAST #x00000004) (defconstant $SQL_FD_FETCH_PRIOR #x00000008) (defconstant $SQL_FD_FETCH_ABSOLUTE #x00000010) (defconstant $SQL_FD_FETCH_RELATIVE #x00000020) (defconstant $SQL_FD_FETCH_RESUME #x00000040) (defconstant $SQL_FD_FETCH_BOOKMARK #x00000080) #| ;; SQL_TXN_ISOLATION_OPTION masks ) (defconstant $SQL_TXN_READ_UNCOMMITTED #x00000001L) (defconstant $SQL_TXN_READ_COMMITTED #x00000002L) (defconstant $SQL_TXN_REPEATABLE_READ #x00000004L) (defconstant $SQL_TXN_SERIALIZABLE #x00000008L) (defconstant $SQL_TXN_VERSIONING #x00000010L ;; SQL_CORRELATION_NAME values ) (defconstant $SQL_CN_NONE #x0000) (defconstant $SQL_CN_DIFFERENT #x0001) (defconstant $SQL_CN_ANY #x0002 ;; SQL_NON_NULLABLE_COLUMNS values ) (defconstant $SQL_NNC_NULL #x0000) (defconstant $SQL_NNC_NON_NULL #x0001 ;; SQL_NULL_COLLATION values ) (defconstant $SQL_NC_HIGH #x0000) (defconstant $SQL_NC_LOW #x0001) (defconstant $SQL_NC_START #x0002) (defconstant $SQL_NC_END #x0004 ;; SQL_FILE_USAGE values ) (defconstant $SQL_FILE_NOT_SUPPORTED #x0000) (defconstant $SQL_FILE_TABLE #x0001) (defconstant $SQL_FILE_QUALIFIER #x0002 ;; SQL_GETDATA_EXTENSIONS values ) (defconstant $SQL_GD_ANY_COLUMN #x00000001L) (defconstant $SQL_GD_ANY_ORDER #x00000002L) (defconstant $SQL_GD_BLOCK #x00000004L) (defconstant $SQL_GD_BOUND #x00000008L ;; SQL_ALTER_TABLE values ) (defconstant $SQL_AT_ADD_COLUMN #x00000001L) (defconstant $SQL_AT_DROP_COLUMN #x00000002L ;; SQL_POSITIONED_STATEMENTS masks ) (defconstant $SQL_PS_POSITIONED_DELETE #x00000001L) (defconstant $SQL_PS_POSITIONED_UPDATE #x00000002L) (defconstant $SQL_PS_SELECT_FOR_UPDATE #x00000004L ;; SQL_GROUP_BY values ) (defconstant $SQL_GB_NOT_SUPPORTED #x0000) (defconstant $SQL_GB_GROUP_BY_EQUALS_SELECT #x0001) (defconstant $SQL_GB_GROUP_BY_CONTAINS_SELECT #x0002) (defconstant $SQL_GB_NO_RELATION #x0003 ;; SQL_OWNER_USAGE masks ) (defconstant $SQL_OU_DML_STATEMENTS #x00000001L) (defconstant $SQL_OU_PROCEDURE_INVOCATION #x00000002L) (defconstant $SQL_OU_TABLE_DEFINITION #x00000004L) (defconstant $SQL_OU_INDEX_DEFINITION #x00000008L) (defconstant $SQL_OU_PRIVILEGE_DEFINITION #x00000010L ;; SQL_QUALIFIER_USAGE masks ) (defconstant $SQL_QU_DML_STATEMENTS #x00000001L) (defconstant $SQL_QU_PROCEDURE_INVOCATION #x00000002L) (defconstant $SQL_QU_TABLE_DEFINITION #x00000004L) (defconstant $SQL_QU_INDEX_DEFINITION #x00000008L) (defconstant $SQL_QU_PRIVILEGE_DEFINITION #x00000010L ;; SQL_SUBQUERIES masks ) (defconstant $SQL_SQ_COMPARISON #x00000001L) (defconstant $SQL_SQ_EXISTS #x00000002L) (defconstant $SQL_SQ_IN #x00000004L) (defconstant $SQL_SQ_QUANTIFIED #x00000008L) (defconstant $SQL_SQ_CORRELATED_SUBQUERIES #x00000010L ;; SQL_UNION masks ) (defconstant $SQL_U_UNION #x00000001L) (defconstant $SQL_U_UNION_ALL #x00000002L ;; SQL_BOOKMARK_PERSISTENCE values ) (defconstant $SQL_BP_CLOSE #x00000001L) (defconstant $SQL_BP_DELETE #x00000002L) (defconstant $SQL_BP_DROP #x00000004L) (defconstant $SQL_BP_TRANSACTION #x00000008L) (defconstant $SQL_BP_UPDATE #x00000010L) (defconstant $SQL_BP_OTHER_HSTMT #x00000020L) (defconstant $SQL_BP_SCROLL #x00000040L ;; SQL_STATIC_SENSITIVITY values ) (defconstant $SQL_SS_ADDITIONS #x00000001L) (defconstant $SQL_SS_DELETIONS #x00000002L) (defconstant $SQL_SS_UPDATES #x00000004L ;; SQL_LOCK_TYPESL masks ) (defconstant $SQL_LCK_NO_CHANGE #x00000001L) (defconstant $SQL_LCK_EXCLUSIVE #x00000002L) (defconstant $SQL_LCK_UNLOCK #x00000004L ;; SQL_POS_OPERATIONS masks |# (defconstant $SQL_POS_POSITION 1) ;; #x00000001L (defconstant $SQL_POS_REFRESH 2) ;; #x00000002L (defconstant $SQL_POS_UPDATE 4) ;; #x00000004L (defconstant $SQL_POS_DELETE 8) ;; #x00000008L (defconstant $SQL_POS_ADD 16) ;; #x00000010L #| ;; SQL_QUALIFIER_LOCATION values ) (defconstant $SQL_QL_START #x0001L) (defconstant $SQL_QL_END #x0002L ;; SQL_OJ_CAPABILITIES values (defconstant $SQL_OJ_LEFT #x00000001L) (defconstant $SQL_OJ_RIGHT #x00000002L) (defconstant $SQL_OJ_FULL #x00000004L) (defconstant $SQL_OJ_NESTED #x00000008L) (defconstant $SQL_OJ_NOT_ORDERED #x00000010L) (defconstant $SQL_OJ_INNER #x00000020L) (defconstant $SQL_OJ_ALL_COMPARISON_OPS #x00000040L ;; options for SQLGetStmtOption/SQLSetStmtOption) (defconstant $SQL_QUERY_TIMEOUT 0) (defconstant $SQL_MAX_ROWS 1) (defconstant $SQL_NOSCAN 2) (defconstant $SQL_MAX_LENGTH 3) (defconstant $SQL_ASYNC_ENABLE 4) (defconstant $SQL_BIND_TYPE 5 (defconstant $SQL_CURSOR_TYPE 6) (defconstant $SQL_CONCURRENCY 7) (defconstant $SQL_KEYSET_SIZE 8) (defconstant $SQL_ROWSET_SIZE 9) (defconstant $SQL_SIMULATE_CURSOR 10) (defconstant $SQL_RETRIEVE_DATA 11) (defconstant $SQL_USE_BOOKMARKS 12) (defconstant $SQL_GET_BOOKMARK 13 /* GetStmtOption Only) (defconstant $SQL_ROW_NUMBER 14 /* GetStmtOption Only) (defconstant $SQL_STMT_OPT_MAX SQL_ROW_NUMBER ) (defconstant $SQL_STMT_OPT_MIN SQL_QUERY_TIMEOUT ;; SQL_QUERY_TIMEOUT options) (defconstant $SQL_QUERY_TIMEOUT_DEFAULT 0UL ;; SQL_MAX_ROWS options) (defconstant $SQL_MAX_ROWS_DEFAULT 0UL ;; SQL_NOSCAN options) (defconstant $SQL_NOSCAN_OFF 0UL /* 1.0 FALSE) (defconstant $SQL_NOSCAN_ON 1UL /* 1.0 TRUE) (defconstant $SQL_NOSCAN_DEFAULT SQL_NOSCAN_OFF ;; SQL_MAX_LENGTH options) (defconstant $SQL_MAX_LENGTH_DEFAULT 0UL ;; SQL_ASYNC_ENABLE options) (defconstant $SQL_ASYNC_ENABLE_OFF 0UL) (defconstant $SQL_ASYNC_ENABLE_ON 1UL) (defconstant $SQL_ASYNC_ENABLE_DEFAULT SQL_ASYNC_ENABLE_OFF ;; SQL_BIND_TYPE options) (defconstant $SQL_BIND_BY_COLUMN 0UL) (defconstant $SQL_BIND_TYPE_DEFAULT SQL_BIND_BY_COLUMN ;; Default value ;; SQL_CONCURRENCY options) (defconstant $SQL_CONCUR_READ_ONLY 1) (defconstant $SQL_CONCUR_LOCK 2) (defconstant $SQL_CONCUR_ROWVER 3) (defconstant $SQL_CONCUR_VALUES 4) (defconstant $SQL_CONCUR_DEFAULT SQL_CONCUR_READ_ONLY ;; Default value ;; SQL_CURSOR_TYPE options) (defconstant $SQL_CURSOR_FORWARD_ONLY 0UL) (defconstant $SQL_CURSOR_KEYSET_DRIVEN 1UL) (defconstant $SQL_CURSOR_DYNAMIC 2UL) (defconstant $SQL_CURSOR_STATIC 3UL) (defconstant $SQL_CURSOR_TYPE_DEFAULT SQL_CURSOR_FORWARD_ONLY ;; Default value ;; SQL_ROWSET_SIZE options) (defconstant $SQL_ROWSET_SIZE_DEFAULT 1UL ;; SQL_KEYSET_SIZE options) (defconstant $SQL_KEYSET_SIZE_DEFAULT 0UL ;; SQL_SIMULATE_CURSOR options) (defconstant $SQL_SC_NON_UNIQUE 0UL) (defconstant $SQL_SC_TRY_UNIQUE 1UL) (defconstant $SQL_SC_UNIQUE 2UL ;; SQL_RETRIEVE_DATA options) (defconstant $SQL_RD_OFF 0UL) (defconstant $SQL_RD_ON 1UL) (defconstant $SQL_RD_DEFAULT SQL_RD_ON ;; SQL_USE_BOOKMARKS options) (defconstant $SQL_UB_OFF 0UL) (defconstant $SQL_UB_ON 1UL) (defconstant $SQL_UB_DEFAULT SQL_UB_OFF |# ;; options for SQLSetConnectOption/SQLGetConnectOption) (defconstant $SQL_ACCESS_MODE 101) (defconstant $SQL_AUTOCOMMIT 102) (defconstant $SQL_LOGIN_TIMEOUT 103) (defconstant $SQL_OPT_TRACE 104) (defconstant $SQL_OPT_TRACEFILE 105) (defconstant $SQL_TRANSLATE_DLL 106) (defconstant $SQL_TRANSLATE_OPTION 107) (defconstant $SQL_TXN_ISOLATION 108) (defconstant $SQL_CURRENT_QUALIFIER 109) (defconstant $SQL_ODBC_CURSORS 110) (defconstant $SQL_QUIET_MODE 111) (defconstant $SQL_PACKET_SIZE 112) (defconstant $SQL_CONN_OPT_MAX $SQL_PACKET_SIZE) (defconstant $SQL_CONNECT_OPT_DRVR_START 1000) ;;#define SQL_CONN_OPT_MIN SQL_ACCESS_MODE ;; SQL_ACCESS_MODE options (defconstant $SQL_MODE_READ_WRITE 0) ; 0UL (defconstant $SQL_MODE_READ_ONLY 1) ; 1UL (defconstant $SQL_MODE_DEFAULT $SQL_MODE_READ_WRITE) ;; SQL_AUTOCOMMIT options) (defconstant $SQL_AUTOCOMMIT_OFF 0) ;0UL (defconstant $SQL_AUTOCOMMIT_ON 1) ;1UL (defconstant $SQL_AUTOCOMMIT_DEFAULT $SQL_AUTOCOMMIT_ON) ;; SQL_LOGIN_TIMEOUT options) (defconstant $SQL_LOGIN_TIMEOUT_DEFAULT 15) ; 15UL ;; SQL_OPT_TRACE options) (defconstant $SQL_OPT_TRACE_OFF 0) ; 0UL (defconstant $SQL_OPT_TRACE_ON 1) ; 1UL (defconstant $SQL_OPT_TRACE_DEFAULT $SQL_OPT_TRACE_OFF) ; #ifndef SQL_OPT_TRACE_FILE_DEFAULT ; (defconstant $SQL_OPT_TRACE_FILE_DEFAULT "\\SQL.LOG" ;; #endif (defconstant $SQL_CUR_USE_IF_NEEDED 0) ; 0UL (defconstant $SQL_CUR_USE_ODBC 1) ; 1UL (defconstant $SQL_CUR_USE_DRIVER 2) ; 2UL (defconstant $SQL_CUR_DEFAULT $SQL_CUR_USE_DRIVER) #| ;; Column types and scopes in SQLSpecialColumns. ) (defconstant $SQL_BEST_ROWID 1) (defconstant $SQL_ROWVER 2) ) (defconstant $SQL_SCOPE_CURROW 0) (defconstant $SQL_SCOPE_TRANSACTION 1) (defconstant $SQL_SCOPE_SESSION 2 ;; Defines for SQLSetPos) (defconstant $SQL_ENTIRE_ROWSET 0 |# ;; Operations in SQLSetPos (defconstant $SQL_POSITION 0) ;; 1.0 FALSE (defconstant $SQL_REFRESH 1) ;; 1.0 TRUE (defconstant $SQL_UPDATE 2) (defconstant $SQL_DELETE 3) (defconstant $SQL_ADD 4) ;; Lock options in SQLSetPos) (defconstant $SQL_LOCK_NO_CHANGE 0) ;; 1.0 FALSE (defconstant $SQL_LOCK_EXCLUSIVE 1) ;; 1.0 TRUE (defconstant $SQL_LOCK_UNLOCK 2) ;; SQLBindParameter extensions (defconstant $SQL_DEFAULT_PARAM -5) (defconstant $SQL_IGNORE -6) (defconstant $SQL_LEN_DATA_AT_EXEC_OFFSET -100) ;(defconstant $SQL_LEN_DATA_AT_EXEC(length) (-length+SQL_LEN_DATA_AT_EXEC_OFFSET) ;; Special return values for SQLGetData (defconstant $SQL_NO_TOTAL -4) #| ;; Macros for SQLSetPos) (defconstant $SQL_POSITION_TO(hstmt,irow) SQLSetPos(hstmt,irow,SQL_POSITION,SQL_LOCK_NO_CHANGE)) (defconstant $SQL_LOCK_RECORD(hstmt,irow,fLock) SQLSetPos(hstmt,irow,SQL_POSITION,fLock)) (defconstant $SQL_REFRESH_RECORD(hstmt,irow,fLock) SQLSetPos(hstmt,irow,SQL_REFRESH,fLock)) (defconstant $SQL_UPDATE_RECORD(hstmt,irow) SQLSetPos(hstmt,irow,SQL_UPDATE,SQL_LOCK_NO_CHANGE)) (defconstant $SQL_DELETE_RECORD(hstmt,irow) SQLSetPos(hstmt,irow,SQL_DELETE,SQL_LOCK_NO_CHANGE)) (defconstant $SQL_ADD_RECORD(hstmt,irow) SQLSetPos(hstmt,irow,SQL_ADD,SQL_LOCK_NO_CHANGE) ; #ifndef RC_INVOKED /* This define is too large for RC) (defconstant $SQL_ODBC_KEYWORDS \ "ABSOLUTE,ACTION,ADA,ADD,ALL,ALLOCATE,ALTER,AND,ANY,ARE,AS,"\ "ASC,ASSERTION,AT,AUTHORIZATION,AVG,"\ "BEGIN,BETWEEN,BIT,BIT_LENGTH,BOTH,BY,CASCADE,CASCADED,CASE,CAST,CATALOG,"\ "CHAR,CHAR_LENGTH,CHARACTER,CHARACTER_LENGTH,CHECK,CLOSE,COALESCE,"\ "COBOL,COLLATE,COLLATION,COLUMN,COMMIT,CONNECT,CONNECTION,CONSTRAINT,"\ "CONSTRAINTS,CONTINUE,CONVERT,CORRESPONDING,COUNT,CREATE,CROSS,CURRENT,"\ "CURRENT_DATE,CURRENT_TIME,CURRENT_TIMESTAMP,CURRENT_USER,CURSOR,"\ "DATE,DAY,DEALLOCATE,DEC,DECIMAL,DECLARE,DEFAULT,DEFERRABLE,"\ "DEFERRED,DELETE,DESC,DESCRIBE,DESCRIPTOR,DIAGNOSTICS,DISCONNECT,"\ "DISTINCT,DOMAIN,DOUBLE,DROP,"\ "ELSE,END,END-EXEC,ESCAPE,EXCEPT,EXCEPTION,EXEC,EXECUTE,"\ "EXISTS,EXTERNAL,EXTRACT,"\ "FALSE,FETCH,FIRST,FLOAT,FOR,FOREIGN,FORTRAN,FOUND,FROM,FULL,"\ "GET,GLOBAL,GO,GOTO,GRANT,GROUP,HAVING,HOUR,"\ "IDENTITY,IMMEDIATE,IN,INCLUDE,INDEX,INDICATOR,INITIALLY,INNER,"\ "INPUT,INSENSITIVE,INSERT,INTEGER,INTERSECT,INTERVAL,INTO,IS,ISOLATION,"\ "JOIN,KEY,LANGUAGE,LAST,LEADING,LEFT,LEVEL,LIKE,LOCAL,LOWER,"\ "MATCH,MAX,MIN,MINUTE,MODULE,MONTH,MUMPS,"\ "NAMES,NATIONAL,NATURAL,NCHAR,NEXT,NO,NONE,NOT,NULL,NULLIF,NUMERIC,"\ "OCTET_LENGTH,OF,ON,ONLY,OPEN,OPTION,OR,ORDER,OUTER,OUTPUT,OVERLAPS,"\ "PAD,PARTIAL,PASCAL,PLI,POSITION,PRECISION,PREPARE,PRESERVE,"\ "PRIMARY,PRIOR,PRIVILEGES,PROCEDURE,PUBLIC,"\ "REFERENCES,RELATIVE,RESTRICT,REVOKE,RIGHT,ROLLBACK,ROWS,"\ "SCHEMA,SCROLL,SECOND,SECTION,SELECT,SEQUENCE,SESSION,SESSION_USER,SET,SIZE,"\ "SMALLINT,SOME,SPACE,SQL,SQLCA,SQLCODE,SQLERROR,SQLSTATE,SQLWARNING,"\ "SUBSTRING,SUM,SYSTEM_USER,"\ "TABLE,TEMPORARY,THEN,TIME,TIMESTAMP,TIMEZONE_HOUR,TIMEZONE_MINUTE,"\ "TO,TRAILING,TRANSACTION,TRANSLATE,TRANSLATION,TRIM,TRUE,"\ "UNION,UNIQUE,UNKNOWN,UPDATE,UPPER,USAGE,USER,USING,"\ "VALUE,VALUES,VARCHAR,VARYING,VIEW,WHEN,WHENEVER,WHERE,WITH,WORK,YEAR") |# (defconstant $SQL_PARAM_TYPE_UNKNOWN 0) (defconstant $SQL_PARAM_INPUT 1) (defconstant $SQL_PARAM_INPUT_OUTPUT 2) (defconstant $SQL_RESULT_COL 3) (defconstant $SQL_PARAM_OUTPUT 4) (defconstant $SQL_RETURN_VALUE 5) ;; Defines used by both Level 1 and Level 2 functions ;; generally useful constants (defconstant $SQL_MAX_OPTION_STRING_LENGTH 256) ;; Additional return codes) (defconstant $SQL_STILL_EXECUTING 2) (defconstant $SQL_NEED_DATA 99) ;; SQL extended datatypes) (defconstant $SQL_DATE 9) (defconstant $SQL_TIME 10) (defconstant $SQL_TIMESTAMP 11) (defconstant $SQL_LONGVARCHAR -1) (defconstant $SQL_BINARY -2) (defconstant $SQL_VARBINARY -3) (defconstant $SQL_LONGVARBINARY -4) (defconstant $SQL_BIGINT -5) (defconstant $SQL_TINYINT -6) (defconstant $SQL_BIT -7) ;; For ODBC3 (defconstant $SQL_TYPE_DATE 91) (defconstant $SQL_TYPE_TIME 92) (defconstant $SQL_TYPE_TIMESTAMP 93) (defconstant $SQL_INTERVAL_YEAR -80) (defconstant $SQL_INTERVAL_MONTH -81) (defconstant $SQL_INTERVAL_YEAR_TO_MONTH -82) (defconstant $SQL_INTERVAL_DAY -83) (defconstant $SQL_INTERVAL_HOUR -84) (defconstant $SQL_INTERVAL_MINUTE -85) (defconstant $SQL_INTERVAL_SECOND -86) (defconstant $SQL_INTERVAL_DAY_TO_HOUR -87) (defconstant $SQL_INTERVAL_DAY_TO_MINUTE -88) (defconstant $SQL_INTERVAL_DAY_TO_SECOND -89) (defconstant $SQL_INTERVAL_HOUR_TO_MINUTE -90) (defconstant $SQL_INTERVAL_HOUR_TO_SECOND -91) (defconstant $SQL_INTERVAL_MINUTE_TO_SECOND -92) (defconstant $SQL_UNICODE -95) (defconstant $SQL_TYPE_DRIVER_START $SQL_INTERVAL_YEAR) (defconstant $SQL_TYPE_DRIVER_END $SQL_UNICODE) (defconstant $SQL_SIGNED_OFFSET -20) (defconstant $SQL_UNSIGNED_OFFSET -22) ;; C datatype to SQL datatype mapping (defconstant $SQL_C_DATE $SQL_DATE) (defconstant $SQL_C_TIME $SQL_TIME) (defconstant $SQL_C_TIMESTAMP $SQL_TIMESTAMP) (defconstant $SQL_C_BINARY $SQL_BINARY) (defconstant $SQL_C_BIT $SQL_BIT) (defconstant $SQL_C_TINYINT $SQL_TINYINT) (defconstant $SQL_C_SBIGINT (+ $SQL_BIGINT $SQL_SIGNED_OFFSET)) (defconstant $SQL_C_SLONG (+ $SQL_C_LONG $SQL_SIGNED_OFFSET)) ;; SIGNED INTEGER (defconstant $SQL_C_SSHORT (+ $SQL_C_SHORT $SQL_SIGNED_OFFSET)) ;; SIGNED SMALLINT (defconstant $SQL_C_STINYINT (+ $SQL_TINYINT $SQL_SIGNED_OFFSET)) ;; SIGNED TINYINT (defconstant $SQL_C_ULONG (+ $SQL_C_LONG $SQL_UNSIGNED_OFFSET)) ;; UNSIGNED INTEGER (defconstant $SQL_C_USHORT (+ $SQL_C_SHORT $SQL_UNSIGNED_OFFSET)) ;; UNSIGNED SMALLINT (defconstant $SQL_C_UTINYINT (+ $SQL_TINYINT $SQL_UNSIGNED_OFFSET)) ;;UNSIGNED TINYINT (defconstant $SQL_C_BOOKMARK $SQL_C_ULONG) ;; BOOKMARK ;;; ODBC3 (defconstant $SQL_C_TYPE_DATE $SQL_TYPE_DATE) (defconstant $SQL_C_TYPE_TIME $SQL_TYPE_TIME) (defconstant $SQL_C_TYPE_TIMESTAMP $SQL_TYPE_TIMESTAMP) ;; Options for SQLDriverConnect (defconstant $SQL_DRIVER_NOPROMPT 0) (defconstant $SQL_DRIVER_COMPLETE 1) (defconstant $SQL_DRIVER_PROMPT 2) (defconstant $SQL_DRIVER_COMPLETE_REQUIRED 3) (defconstant $SQL_MAX_CONN_OUT 1024) ;; Level 2 Functions ;; SQLExtendedFetch "fFetchType" values (defconstant $SQL_FETCH_NEXT 1) (defconstant $SQL_FETCH_FIRST 2) (defconstant $SQL_FETCH_LAST 3) (defconstant $SQL_FETCH_PRIOR 4) (defconstant $SQL_FETCH_ABSOLUTE 5) (defconstant $SQL_FETCH_RELATIVE 6) (defconstant $SQL_FETCH_BOOKMARK 8) ;;; ODBC3 constants, added by KMR (defconstant $SQL_ATTR_ODBC_VERSION 200) (defconstant $SQL_OV_ODBC2 2) (defconstant $SQL_OV_ODBC3 3) (defconstant $SQL_INDEX_UNIQUE 0) (defconstant $SQL_INDEX_ALL 1) (defconstant $SQL_QUICK 0) (defconstant $SQL_ENSURE 1) cl-sql-6.4.1/db-odbc/odbc-loader.lisp0000644000175000017500000000302011335067642016267 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; FILE IDENTIFICATION ;;;; ;;;; Name: odbc-loader.sql ;;;; Purpose: ODBC library loader using UFFI ;;;; Programmers: Kevin M. Rosenberg ;;;; Date Started: April 2004 ;;;; ;;;; This file, part of CLSQL, is Copyright (c) 2004 by Kevin M. Rosenberg ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* (in-package #:odbc) (defparameter *odbc-library-filenames* '("odbc32" "libodbc" "libiodbc")) (defvar *odbc-supporting-libraries* '("c") "Used only by CMU. List of library flags needed to be passed to ld to load the Odbc client library succesfully. If this differs at your site, set to the right path before compiling or loading the system.") (defvar *odbc-library-loaded* nil "T if foreign library was able to be loaded successfully") (defmethod clsql-sys:database-type-library-loaded ((database-type (eql :odbc))) *odbc-library-loaded*) (defmethod clsql-sys:database-type-load-foreign ((database-type (eql :odbc))) (clsql-uffi:find-and-load-foreign-library *odbc-library-filenames* :module "odbc") (setq *odbc-library-loaded* t)) (clsql-sys:database-type-load-foreign :odbc) cl-sql-6.4.1/clsql-tests.asd0000644000175000017500000000362211616055736014713 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; FILE IDENTIFICATION ;;;; ;;;; File: clsql-tests.asd ;;;; Authors: Marcus Pearce and Kevin Rosenberg ;;;; Created: 30/03/2004 ;;;; ;;;; This file is part of CLSQL. ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* (in-package #:cl-user) (defpackage #:clsql-tests-system (:use #:asdf #:cl)) (in-package #:clsql-tests-system) (eval-when (:compile-toplevel :load-toplevel :execute) (unless (find-package '#:uffi) (asdf:operate 'asdf:load-op 'uffi))) (defsystem clsql-tests :name "CLSQL Tests" :author "" :maintainer "" :version "" :licence "" :description "A regression test suite for CLSQL." :depends-on (clsql rt) :components ((:module tests :serial t :components ((:file "package") (:file "utils") (:file "test-init") (:file "datasets") (:file "ds-employees") (:file "ds-nodes") (:file "ds-artists") (:file "benchmarks") (:file "test-internal") (:file "test-basic") (:file "test-time") (:file "test-connection") (:file "test-fddl") (:file "test-fdml") (:file "test-ooddl") (:file "test-oodml") (:file "test-syntax") (:file "test-pool") ; #-uffi:no-i18n (:file "test-i18n") )))) (defmethod perform ((o test-op) (c (eql (find-system 'clsql-tests)))) (operate 'load-op 'clsql) (unless (funcall (intern (symbol-name '#:run-tests) (find-package '#:clsql-tests))) (error "test-op failed"))) cl-sql-6.4.1/db-postgresql-socket/0000755000175000017500000000000012134026703016001 5ustar kevinkevincl-sql-6.4.1/db-postgresql-socket/postgresql-socket-api.lisp0000644000175000017500000010711512134025332023134 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; FILE IDENTIFICATION ;;;; ;;;; Name: postgresql-socket-api.lisp ;;;; Purpose: Low-level PostgreSQL interface using sockets ;;;; Authors: Kevin M. Rosenberg based on original code by Pierre R. Mai ;;;; Created: Feb 2002 ;;;; ;;;; This file, part of CLSQL, is Copyright (c) 2002-2010 by Kevin M. Rosenberg ;;;; and Copyright (c) 1999-2001 by Pierre R. Mai ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* (in-package #:postgresql-socket) ;; KMR: 2011-06-12 ;; FIXME: The file has code specific to sb-unicode and CCL ;; to assume UTF8 encoded strings. ;; Best fix would be to use the user-specified encoding that is now ;; stored in the database object and use the UFFI 2.x encoding functions ;; to convert strings to/from octet vectors. This allows encoding ;; other than UTF8 and also works on all CL implementations that ;; support wide character strings (uffi:def-enum pgsql-ftype ((:bytea 17) (:int2 21) (:int4 23) (:int8 20) (:float4 700) (:float8 701))) (defmethod clsql-sys:database-type-library-loaded ((database-type (eql :postgresql-socket))) "T if foreign library was able to be loaded successfully. Always true for socket interface" t) (defmethod clsql-sys:database-type-load-foreign ((database-type (eql :postgresql-socket))) t) ;;; Message I/O stuff (defmacro define-message-constants (description &rest clauses) (assert (evenp (length clauses))) (loop with seen-characters = nil for (name char) on clauses by #'cddr for char-code = (char-code char) for doc-string = (format nil "~A (~:C): ~A" description char name) if (member char seen-characters) do (error "Duplicate message type ~@C for group ~A" char description) else collect `(defconstant ,name ,char-code ,doc-string) into result-clauses and do (push char seen-characters) finally (return `(progn ,@result-clauses)))) (eval-when (:compile-toplevel :load-toplevel :execute) (define-message-constants "Backend Message Constants" +ascii-row-message+ #\D +authentication-message+ #\R +backend-key-message+ #\K +binary-row-message+ #\B +completed-response-message+ #\C +copy-in-response-message+ #\G +copy-out-response-message+ #\H +cursor-response-message+ #\P +empty-query-response-message+ #\I +error-response-message+ #\E +function-response-message+ #\V +notice-response-message+ #\N +notification-response-message+ #\A +ready-for-query-message+ #\Z +row-description-message+ #\T)) #+scl (declaim (inline read-byte write-byte)) (defun send-socket-value-int32 (socket value) (declare (type stream socket) (type (unsigned-byte 32) value)) (write-byte (ldb (byte 8 24) value) socket) (write-byte (ldb (byte 8 16) value) socket) (write-byte (ldb (byte 8 8) value) socket) (write-byte (ldb (byte 8 0) value) socket) nil) (defun send-socket-value-int16 (socket value) (declare (type stream socket) (type (unsigned-byte 16) value)) (write-byte (ldb (byte 8 8) value) socket) (write-byte (ldb (byte 8 0) value) socket) nil) (defun send-socket-value-int8 (socket value) (declare (type stream socket) (type (unsigned-byte 8) value)) (write-byte (ldb (byte 8 0) value) socket) nil) (defun send-socket-value-char-code (socket value) (declare (type stream socket) (type character value)) (write-byte (ldb (byte 8 0) (char-code value)) socket) nil) (defun send-socket-value-string (socket value) (declare (type stream socket) (type string value)) #-(or sb-unicode ccl) (loop for char across value for code = (char-code char) do (write-byte code socket) finally (write-byte 0 socket)) #+ccl (write-sequence (ccl:encode-string-to-octets value :external-format :utf-8) socket) #+ccl (write-byte 0 socket) #+sb-unicode (write-sequence (sb-ext:string-to-octets value :null-terminate t) socket) nil) (defun send-socket-value-limstring (socket value limit) (declare (type stream socket) (type string value) (type fixnum limit)) (let ((length (length value))) (dotimes (i (min length limit)) (let ((code (char-code (char value i)))) (write-byte code socket))) (dotimes (i (- limit length)) (write-byte 0 socket))) nil) (defun read-socket-value-int32 (socket) (declare (type stream socket)) (declare (optimize (speed 3))) (let ((result 0)) (declare (type (unsigned-byte 32) result)) (setf (ldb (byte 8 24) result) (read-byte socket)) (setf (ldb (byte 8 16) result) (read-byte socket)) (setf (ldb (byte 8 8) result) (read-byte socket)) (setf (ldb (byte 8 0) result) (read-byte socket)) result)) (defun read-socket-value-int16 (socket) (declare (type stream socket)) (let ((result 0)) (declare (type (unsigned-byte 16) result)) (setf (ldb (byte 8 8) result) (read-byte socket)) (setf (ldb (byte 8 0) result) (read-byte socket)) result)) (defun read-socket-value-int8 (socket) (declare (type stream socket)) (read-byte socket)) (defun read-socket-value-string (socket) (declare (type stream socket)) #-(or sb-unicode ccl) (with-output-to-string (out) (loop for code = (read-byte socket) until (zerop code) do (write-char (code-char code) out))) #+ccl (let ((bytes (make-array 64 :element-type '(unsigned-byte 8) :adjustable t :fill-pointer 0))) (loop for code = (read-byte socket) until (zerop code) do (vector-push-extend code bytes)) (ccl:decode-string-from-octets bytes :external-format :utf-8)) #+sb-unicode (let ((bytes (make-array 64 :element-type '(unsigned-byte 8) :adjustable t :fill-pointer 0))) (loop for code = (read-byte socket) until (zerop code) do (vector-push-extend code bytes)) (sb-ext:octets-to-string bytes))) (defmacro define-message-sender (name (&rest args) &rest clauses) (let ((socket-var (gensym)) (body nil)) (dolist (clause clauses) (let* ((type (first clause)) (fn (intern (concatenate 'string (symbol-name '#:send-socket-value-) (symbol-name type))))) (push `(,fn ,socket-var ,@(rest clause)) body))) `(defun ,name (,socket-var ,@args) ,@(nreverse body)))) (define-message-sender send-startup-message (database user &optional (command-line "") (backend-tty "")) (int32 296) ; Length (int32 #x00020000) ; Version 2.0 (limstring database 64) (limstring user 32) (limstring command-line 64) (limstring "" 64) ; Unused (limstring backend-tty 64)) (define-message-sender send-terminate-message () (char-code #\X)) (define-message-sender send-unencrypted-password-message (password) (int32 (+ 5 (length password))) (string password)) (define-message-sender send-query-message (query) (char-code #\Q) (string query)) (define-message-sender send-encrypted-password-message (crypted-password) (int32 (+ 5 (length crypted-password))) (string crypted-password)) (define-message-sender send-cancel-request (pid key) (int32 16) ; Length (int32 80877102) ; Magic (int32 pid) (int32 key)) (defun read-socket-sequence (stream length &optional (allow-wide t)) (declare (stream stream) (optimize (speed 3) (safety 0))) #-(or sb-unicode ccl) (let ((result (make-string length))) (dotimes (i length result) (declare (fixnum i)) (setf (char result i) (code-char (read-byte stream))))) #+ccl (let ((bytes (make-array length :element-type '(unsigned-byte 8)))) (declare (type (simple-array (unsigned-byte 8) (*)) bytes)) (read-sequence bytes stream) (if allow-wide (ccl:decode-string-from-octets bytes :external-format :utf-8) (map 'string #'code-char bytes))) #+sb-unicode (let ((bytes (make-array length :element-type '(unsigned-byte 8)))) (declare (type (simple-array (unsigned-byte 8) (*)) bytes)) (read-sequence bytes stream) (if allow-wide (sb-ext:octets-to-string bytes) (map 'string #'code-char bytes)))) ;;; Support for encrypted password transmission #-scl (eval-when (:compile-toplevel :load-toplevel :execute) (defvar *crypt-library-loaded* nil) (unless *crypt-library-loaded* (uffi:load-foreign-library (uffi:find-foreign-library "libcrypt" '(#+(or 64bit x86-64) "/usr/lib64/" "/usr/lib/" "/usr/local/lib/" "/lib/")) :supporting-libraries '("c")) (setq *crypt-library-loaded* t))) (in-package :postgresql-socket) (uffi:def-function ("crypt" crypt) ((key :cstring) (salt :cstring)) :returning :cstring) (defun crypt-password (password salt) "Encrypt a password for transmission to a PostgreSQL server." (uffi:with-cstring (password-cstring password) (uffi:with-cstring (salt-cstring salt) (uffi:convert-from-cstring (crypt password-cstring salt-cstring))))) ;;;; Condition hierarchy (define-condition postgresql-condition (condition) ((connection :initarg :connection :reader postgresql-condition-connection) (message :initarg :message :reader postgresql-condition-message)) (:report (lambda (c stream) (format stream "~@<~A occurred on connection ~A. ~:@_Reason: ~A~:@>" (type-of c) (postgresql-condition-connection c) (postgresql-condition-message c))))) (define-condition postgresql-error (error postgresql-condition) ()) (define-condition postgresql-fatal-error (postgresql-error) ()) (define-condition postgresql-login-error (postgresql-fatal-error) ()) (define-condition postgresql-warning (warning postgresql-condition) ()) (define-condition postgresql-notification (postgresql-condition) () (:report (lambda (c stream) (format stream "~@" (postgresql-condition-connection c) (postgresql-condition-message c))))) ;;; Structures (defstruct postgresql-connection host port database user password options tty socket pid key) (defstruct postgresql-cursor connection name fields) ;;; Socket stuff (defconstant +postgresql-server-default-port+ 5432 "Default port of PostgreSQL server.") (defvar *postgresql-server-socket-timeout* 60 "Timeout in seconds for reads from the PostgreSQL server.") #+(or cmu scl) (defun open-postgresql-socket (host port) (etypecase host (pathname ;; Directory to unix-domain socket (ext:connect-to-unix-socket (namestring (make-pathname :name ".s.PGSQL" :type (princ-to-string port) :defaults host)))) (string (ext:connect-to-inet-socket host port)))) #+sbcl (defun open-postgresql-socket (host port) (etypecase host (pathname ;; Directory to unix-domain socket (let ((sock (make-instance 'sb-bsd-sockets:local-socket :type :stream))) (sb-bsd-sockets:socket-connect sock (namestring (make-pathname :name ".s.PGSQL" :type (princ-to-string port) :defaults host))) sock)) (string (let ((sock (make-instance 'sb-bsd-sockets:inet-socket :type :stream :protocol :tcp))) (sb-bsd-sockets:socket-connect sock (sb-bsd-sockets:host-ent-address (sb-bsd-sockets:get-host-by-name host)) port) sock)))) #+(or cmu scl) (defun open-postgresql-socket-stream (host port) (system:make-fd-stream (open-postgresql-socket host port) :input t :output t :element-type '(unsigned-byte 8) :buffering :none :timeout *postgresql-server-socket-timeout*)) #+sbcl (defun open-postgresql-socket-stream (host port) (sb-bsd-sockets:socket-make-stream (open-postgresql-socket host port) :input t :output t :element-type '(unsigned-byte 8))) #+allegro (defun open-postgresql-socket-stream (host port) (etypecase host (pathname (let ((path (namestring (make-pathname :name ".s.PGSQL" :type (princ-to-string port) :defaults host)))) (socket:make-socket :type :stream :address-family :file :connect :active :remote-filename path :local-filename path))) (string (socket:with-pending-connect (mp:with-timeout (*postgresql-server-socket-timeout* (error "connect failed")) (socket:make-socket :type :stream :address-family :internet :remote-port port :remote-host host :connect :active :nodelay t)))))) #+openmcl (defun open-postgresql-socket-stream (host port) (etypecase host (pathname (let ((path (namestring (make-pathname :name ".s.PGSQL" :type (princ-to-string port) :defaults host)))) (ccl:make-socket :type :stream :address-family :file :connect :active :remote-filename path :local-filename path))) (string (ccl:make-socket :type :stream :address-family :internet :remote-port port :remote-host host :connect :active :nodelay t)))) #+lispworks (defun open-postgresql-socket-stream (host port) (etypecase host (pathname (error "File sockets not supported on Lispworks.")) (string (comm:open-tcp-stream host port :direction :io :element-type '(unsigned-byte 8) :read-timeout *postgresql-server-socket-timeout*)) )) #+clisp (defun open-postgresql-socket-stream (host port) (etypecase host (pathname (error "Not supported")) (string (socket:socket-connect port host :element-type '(unsigned-byte 8) :timeout *postgresql-server-socket-timeout*)))) ;;; Interface Functions (defun open-postgresql-connection (&key (host (cmucl-compat:required-argument)) (port +postgresql-server-default-port+) (database (cmucl-compat:required-argument)) (user (cmucl-compat:required-argument)) options tty password) "Open a connection to a PostgreSQL server with the given parameters. Note that host, database and user arguments must be supplied. If host is a pathname, it is assumed to name a directory containing the local unix-domain sockets of the server, with port selecting which of those sockets to open. If host is a string, it is assumed to be the name of the host running the PostgreSQL server. In that case a TCP connection to the given port on that host is opened in order to communicate with the server. In either case the port argument defaults to `+postgresql-server-default-port+'. Password is the clear-text password to be passed in the authentication phase to the server. Depending on the server set-up, it is either passed in the clear, or encrypted via crypt and a server-supplied salt. In that case the alien function specified by `*crypt-library*' and `*crypt-function-name*' is used for encryption. Note that all the arguments (including the clear-text password argument) are stored in the `postgresql-connection' structure, in order to facilitate automatic reconnection in case of communication troubles." (reopen-postgresql-connection (make-postgresql-connection :host host :port port :options (or options "") :tty (or tty "") :database database :user user :password (or password "")))) (defun encrypt-md5 (plaintext salt) (string-downcase (format nil "~{~2,'0X~}" (coerce (md5sum-string (concatenate 'string plaintext salt)) 'list)))) (defun reopen-postgresql-connection (connection) "Reopen the given PostgreSQL connection. Closes any existing connection, if it is still open." (when (postgresql-connection-open-p connection) (close-postgresql-connection connection)) (let ((socket (open-postgresql-socket-stream (postgresql-connection-host connection) (postgresql-connection-port connection)))) (unwind-protect (progn (setf (postgresql-connection-socket connection) socket) (send-startup-message socket (postgresql-connection-database connection) (postgresql-connection-user connection) (postgresql-connection-options connection) (postgresql-connection-tty connection)) (force-output socket) (loop (case (read-socket-value-int8 socket) (#.+authentication-message+ (case (read-socket-value-int32 socket) (0 (return)) ((1 2) (error 'postgresql-login-error :connection connection :message "Postmaster expects unsupported Kerberos authentication.")) (3 (send-unencrypted-password-message socket (postgresql-connection-password connection)) (force-output socket)) (4 (let ((salt (read-socket-sequence socket 2 nil))) (send-encrypted-password-message socket (crypt-password (postgresql-connection-password connection) salt))) (force-output socket)) (5 (let ((salt (read-socket-sequence socket 4 nil))) (let* ((pwd2 (encrypt-md5 (postgresql-connection-password connection) (postgresql-connection-user connection))) (pwd (encrypt-md5 pwd2 salt))) (send-encrypted-password-message socket (concatenate 'string "md5" pwd)))) (force-output socket)) (t (error 'postgresql-login-error :connection connection :message "Postmaster expects unknown authentication method.")))) (#.+error-response-message+ (let ((message (read-socket-value-string socket))) (error 'postgresql-login-error :connection connection :message message))) (t (error 'postgresql-login-error :connection connection :message "Received garbled message from Postmaster")))) ;; Start backend communication (force-output socket) (loop (case (read-socket-value-int8 socket) (#.+backend-key-message+ (setf (postgresql-connection-pid connection) (read-socket-value-int32 socket) (postgresql-connection-key connection) (read-socket-value-int32 socket))) (#.+ready-for-query-message+ (setq socket nil) (return connection)) (#.+error-response-message+ (let ((message (read-socket-value-string socket))) (error 'postgresql-login-error :connection connection :message message))) (#.+notice-response-message+ (let ((message (read-socket-value-string socket))) (warn 'postgresql-warning :connection connection :message message))) (t (error 'postgresql-login-error :connection connection :message "Received garbled message from Postmaster"))))) (when socket (close socket))))) (defun close-postgresql-connection (connection &optional abort) (unless abort (ignore-errors (send-terminate-message (postgresql-connection-socket connection)))) (close (postgresql-connection-socket connection))) (defun postgresql-connection-open-p (connection) (let ((socket (postgresql-connection-socket connection))) (and socket (streamp socket) (open-stream-p socket)))) (defun ensure-open-postgresql-connection (connection) (unless (postgresql-connection-open-p connection) (reopen-postgresql-connection connection))) (defun process-async-messages (connection) (assert (postgresql-connection-open-p connection)) ;; Process any asnychronous messages (loop with socket = (postgresql-connection-socket connection) while (listen socket) do (case (read-socket-value-int8 socket) (#.+ready-for-query-message+) (#.+notice-response-message+ (let ((message (read-socket-value-string socket))) (warn 'postgresql-warning :connection connection :message message))) (#.+notification-response-message+ (let ((pid (read-socket-value-int32 socket)) (message (read-socket-value-string socket))) (when (= pid (postgresql-connection-pid connection)) (signal 'postgresql-notification :connection connection :message message)))) (t (close-postgresql-connection connection) (error 'postgresql-fatal-error :connection connection :message "Received garbled message from backend"))))) (defun start-query-execution (connection query) (ensure-open-postgresql-connection connection) (process-async-messages connection) (send-query-message (postgresql-connection-socket connection) query) (force-output (postgresql-connection-socket connection))) (defun wait-for-query-results (connection) (assert (postgresql-connection-open-p connection)) (let ((socket (postgresql-connection-socket connection)) (cursor-name nil) (error nil)) (loop (case (read-socket-value-int8 socket) (#.+completed-response-message+ (return (values :completed (read-socket-value-string socket)))) (#.+cursor-response-message+ (setq cursor-name (read-socket-value-string socket))) (#.+row-description-message+ (let* ((count (read-socket-value-int16 socket)) (fields (loop repeat count collect (list (read-socket-value-string socket) (read-socket-value-int32 socket) (read-socket-value-int16 socket) (read-socket-value-int32 socket))))) (return (values :cursor (make-postgresql-cursor :connection connection :name cursor-name :fields fields))))) (#.+copy-in-response-message+ (return :copy-in)) (#.+copy-out-response-message+ (return :copy-out)) (#.+ready-for-query-message+ (when error (error error)) (return nil)) (#.+error-response-message+ (let ((message (read-socket-value-string socket))) (setq error (make-condition 'postgresql-error :connection connection :message message)))) (#.+notice-response-message+ (let ((message (read-socket-value-string socket))) (unless (eq :ignore clsql-sys:*backend-warning-behavior*) (warn 'postgresql-warning :connection connection :message message)))) (#.+notification-response-message+ (let ((pid (read-socket-value-int32 socket)) (message (read-socket-value-string socket))) (when (= pid (postgresql-connection-pid connection)) (signal 'postgresql-notification :connection connection :message message)))) (t (close-postgresql-connection connection) (error 'postgresql-fatal-error :connection connection :message "Received garbled message from backend")))))) (defun read-null-bit-vector (socket count) (let ((result (make-array count :element-type 'bit))) (dotimes (offset (ceiling count 8)) (loop with byte = (read-byte socket) for index from (* offset 8) below (min count (* (1+ offset) 8)) for weight downfrom 7 do (setf (aref result index) (ldb (byte 1 weight) byte)))) result)) (defun read-field (socket type) (let ((length (- (read-socket-value-int32 socket) 4))) (case type ((:int32 :int64) (read-integer-from-socket socket length)) (:double (read-double-from-socket socket length)) (t (read-socket-sequence socket length))))) (uffi:def-constant +char-code-zero+ (char-code #\0)) (uffi:def-constant +char-code-minus+ (char-code #\-)) (uffi:def-constant +char-code-plus+ (char-code #\+)) (uffi:def-constant +char-code-period+ (char-code #\.)) (uffi:def-constant +char-code-lower-e+ (char-code #\e)) (uffi:def-constant +char-code-upper-e+ (char-code #\E)) (defun read-integer-from-socket (socket length) (declare (fixnum length)) (if (zerop length) nil (let ((val 0) (first-char (read-byte socket)) (minusp nil)) (declare (fixnum first-char)) (decf length) ;; read first char (cond ((= first-char +char-code-minus+) (setq minusp t)) ((= first-char +char-code-plus+) ) ;; nothing to do (t (setq val (- first-char +char-code-zero+)))) (dotimes (i length) (declare (fixnum i)) (setq val (+ (* 10 val) (- (read-byte socket) +char-code-zero+)))) (if minusp (- val) val)))) (defmacro ascii-digit (int) (let ((offset (gensym))) `(let ((,offset (- ,int +char-code-zero+))) (declare (fixnum ,int ,offset)) (if (and (>= ,offset 0) (< ,offset 10)) ,offset nil)))) (defun read-double-from-socket (socket length) (declare (fixnum length)) (let ((before-decimal 0) (after-decimal 0) (decimal-count 0) (exponent 0) (decimalp nil) (minusp nil) (result nil) (char (read-byte socket))) (declare (fixnum char exponent decimal-count)) (decf length) ;; already read first character (cond ((= char +char-code-minus+) (setq minusp t)) ((= char +char-code-plus+) ) ((= char +char-code-period+) (setq decimalp t)) (t (setq before-decimal (ascii-digit char)) (unless before-decimal (error "Unexpected value")))) (block loop (dotimes (i length) (setq char (read-byte socket)) ;; (format t "~&len:~D, i:~D, char:~D, minusp:~A, decimalp:~A" length i char minusp decimalp) (let ((weight (ascii-digit char))) (cond ((and weight (not decimalp)) ;; before decimal point (setq before-decimal (+ weight (* 10 before-decimal)))) ((and weight decimalp) ;; after decimal point (setq after-decimal (+ weight (* 10 after-decimal))) (incf decimal-count)) ((and (= char +char-code-period+)) (setq decimalp t)) ((or (= char +char-code-lower-e+) ;; E is for exponent (= char +char-code-upper-e+)) (setq exponent (read-integer-from-socket socket (- length i 1))) (setq exponent (or exponent 0)) (return-from loop)) (t (break "Unexpected value")) ) ))) (setq result (* (+ (coerce before-decimal 'double-float) (* after-decimal (expt 10 (- decimal-count)))) (expt 10 exponent))) (if minusp (- result) result))) #+ignore (defun read-double-from-socket (socket length) (let ((result (make-string length))) (read-socket-sequence result socket) (let ((*read-default-float-format* 'double-float)) (read-from-string result)))) (defun read-cursor-row (cursor types) (let* ((connection (postgresql-cursor-connection cursor)) (socket (postgresql-connection-socket connection)) (fields (postgresql-cursor-fields cursor))) (assert (postgresql-connection-open-p connection)) (loop (let ((code (read-socket-value-int8 socket))) (case code (#.+ascii-row-message+ (return (loop with count = (length fields) with null-vector = (read-null-bit-vector socket count) repeat count for null-bit across null-vector for i from 0 for null-p = (zerop null-bit) if null-p collect nil else collect (read-field socket (nth i types))))) (#.+binary-row-message+ (error "NYI")) (#.+completed-response-message+ (return (values nil (read-socket-value-string socket)))) (#.+error-response-message+ (let ((message (read-socket-value-string socket))) (error 'postgresql-error :connection connection :message message))) (#.+notice-response-message+ (let ((message (read-socket-value-string socket))) (warn 'postgresql-warning :connection connection :message message))) (#.+notification-response-message+ (let ((pid (read-socket-value-int32 socket)) (message (read-socket-value-string socket))) (when (= pid (postgresql-connection-pid connection)) (signal 'postgresql-notification :connection connection :message message)))) (t (close-postgresql-connection connection) (error 'postgresql-fatal-error :connection connection :message "Received garbled message from backend"))))))) (defun map-into-indexed (result-seq func seq) (dotimes (i (length seq)) (declare (fixnum i)) (setf (elt result-seq i) (funcall func (elt seq i) i))) result-seq) (defun copy-cursor-row (cursor sequence types) (let* ((connection (postgresql-cursor-connection cursor)) (socket (postgresql-connection-socket connection)) (fields (postgresql-cursor-fields cursor))) (assert (= (length fields) (length sequence))) (loop (let ((code (read-socket-value-int8 socket))) (case code (#.+ascii-row-message+ (return #+ignore (let* ((count (length sequence)) (null-vector (read-null-bit-vector socket count))) (dotimes (i count) (declare (fixnum i)) (if (zerop (elt null-vector i)) (setf (elt sequence i) nil) (let ((value (read-field socket (nth i types)))) (setf (elt sequence i) value))))) (map-into-indexed sequence #'(lambda (null-bit i) (if (zerop null-bit) nil (read-field socket (nth i types)))) (read-null-bit-vector socket (length sequence))))) (#.+binary-row-message+ (error "NYI")) (#.+completed-response-message+ (return (values nil (read-socket-value-string socket)))) (#.+error-response-message+ (let ((message (read-socket-value-string socket))) (error 'postgresql-error :connection connection :message message))) (#.+notice-response-message+ (let ((message (read-socket-value-string socket))) (warn 'postgresql-warning :connection connection :message message))) (#.+notification-response-message+ (let ((pid (read-socket-value-int32 socket)) (message (read-socket-value-string socket))) (when (= pid (postgresql-connection-pid connection)) (signal 'postgresql-notification :connection connection :message message)))) (t (close-postgresql-connection connection) (error 'postgresql-fatal-error :connection connection :message "Received garbled message from backend"))))))) (defun skip-cursor-row (cursor) (let* ((connection (postgresql-cursor-connection cursor)) (socket (postgresql-connection-socket connection)) (fields (postgresql-cursor-fields cursor))) (loop (let ((code (read-socket-value-int8 socket))) (case code (#.+ascii-row-message+ (loop for null-bit across (read-null-bit-vector socket (length fields)) do (unless (zerop null-bit) (let* ((length (read-socket-value-int32 socket))) (loop repeat (- length 4) do (read-byte socket))))) (return t)) (#.+binary-row-message+ (error "NYI")) (#.+completed-response-message+ (return (values nil (read-socket-value-string socket)))) (#.+error-response-message+ (let ((message (read-socket-value-string socket))) (error 'postgresql-error :connection connection :message message))) (#.+notice-response-message+ (let ((message (read-socket-value-string socket))) (warn 'postgresql-warning :connection connection :message message))) (#.+notification-response-message+ (let ((pid (read-socket-value-int32 socket)) (message (read-socket-value-string socket))) (when (= pid (postgresql-connection-pid connection)) (signal 'postgresql-notification :connection connection :message message)))) (t (close-postgresql-connection connection) (error 'postgresql-fatal-error :connection connection :message "Received garbled message from backend"))))))) (defun run-query (connection query &optional (result-types nil)) (start-query-execution connection query) (multiple-value-bind (status cursor) (wait-for-query-results connection) (assert (eq status :cursor)) (loop for row = (read-cursor-row cursor result-types) while row collect row finally (wait-for-query-results connection)))) #+scl (declaim (ext:maybe-inline read-byte write-byte)) cl-sql-6.4.1/db-postgresql-socket/postgresql-socket-sql.lisp0000644000175000017500000003256111577737507023214 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; FILE IDENTIFICATION ;;;; ;;;; Name: postgresql-socket-sql.sql ;;;; Purpose: High-level PostgreSQL interface using socket ;;;; Authors: Kevin M. Rosenberg based on original code by Pierre R. Mai ;;;; Created: Feb 2002 ;;;; ;;;; This file, part of CLSQL, is Copyright (c) 2002-2010 by Kevin M. Rosenberg ;;;; and Copyright (c) 1999-2001 by Pierre R. Mai ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* (in-package #:cl-user) (defpackage :clsql-postgresql-socket (:use #:common-lisp #:clsql-sys #:postgresql-socket) (:export #:postgresql-socket-database) (:documentation "This is the CLSQL socket interface to PostgreSQL.")) (in-package #:clsql-postgresql-socket) ;; interface foreign library loading routines (clsql-sys:database-type-load-foreign :postgresql-socket) ;; Field type conversion (defun make-type-list-for-auto (cursor) (let* ((fields (postgresql-cursor-fields cursor)) (num-fields (length fields)) (new-types '())) (dotimes (i num-fields) (declare (fixnum i)) (push (canonical-field-type fields i) new-types)) (nreverse new-types))) (defun canonical-field-type (fields index) "Extracts canonical field type from fields list" (let ((oid (cadr (nth index fields)))) (case oid ((#.pgsql-ftype#bytea #.pgsql-ftype#int2 #.pgsql-ftype#int4) :int32) (#.pgsql-ftype#int8 :int64) ((#.pgsql-ftype#float4 #.pgsql-ftype#float8) :double) (otherwise t)))) (defun canonicalize-types (types cursor) (if (null types) nil (let ((auto-list (make-type-list-for-auto cursor))) (cond ((listp types) (canonicalize-type-list types auto-list)) ((eq types :auto) auto-list) (t nil))))) (defun canonicalize-type-list (types auto-list) "Ensure a field type list meets expectations. Essentially if we get a generic term for a type that our auto typer pulls a better type for, use it instead" (let ((length-types (length types))) (loop for i from 0 below (length auto-list) for auto = (nth i auto-list) collect (if (or (>= i length-types) (member (nth i types) (list T :int :double))) auto (nth i types))))) (defun convert-to-clsql-warning (database condition) (ecase *backend-warning-behavior* (:warn (warn 'sql-database-warning :database database :message (postgresql-condition-message condition))) (:error (error 'sql-database-error :database database :message (format nil "Warning upgraded to error: ~A" (postgresql-condition-message condition)))) ((:ignore nil) ;; do nothing ))) (defun convert-to-clsql-error (database expression condition) (error 'sql-database-data-error :database database :expression expression :error-id (type-of condition) :message (postgresql-condition-message condition))) (defmacro with-postgresql-handlers ((database &optional expression) &body body) (let ((database-var (gensym)) (expression-var (gensym))) `(let ((,database-var ,database) (,expression-var ,expression)) (handler-bind ((postgresql-warning (lambda (c) (convert-to-clsql-warning ,database-var c))) (postgresql-error (lambda (c) (convert-to-clsql-error ,database-var ,expression-var c)))) ,@body)))) (defmethod database-initialize-database-type ((database-type (eql :postgresql-socket))) t) (defclass postgresql-socket-database (generic-postgresql-database) ((connection :accessor database-connection :initarg :connection :type postgresql-connection))) (defmethod database-type ((database postgresql-socket-database)) :postgresql-socket) (defmethod database-name-from-spec (connection-spec (database-type (eql :postgresql-socket))) (check-connection-spec connection-spec database-type (host db user password &optional port options tty)) (destructuring-bind (host db user password &optional port options tty) connection-spec (declare (ignore password options tty)) (concatenate 'string (etypecase host (null "localhost") (pathname (namestring host)) (string host)) (when port (concatenate 'string ":" (etypecase port (integer (write-to-string port)) (string port)))) "/" db "/" user))) (defmethod database-connect (connection-spec (database-type (eql :postgresql-socket))) (check-connection-spec connection-spec database-type (host db user password &optional port options tty)) (destructuring-bind (host db user password &optional (port +postgresql-server-default-port+) (options "") (tty "")) connection-spec (handler-case (handler-bind ((postgresql-warning (lambda (c) (warn 'sql-warning :format-control "~A" :format-arguments (list (princ-to-string c)))))) (open-postgresql-connection :host host :port port :options options :tty tty :database db :user user :password password)) (postgresql-error (c) ;; Connect failed (error 'sql-connection-error :database-type database-type :connection-spec connection-spec :error-id (type-of c) :message (postgresql-condition-message c))) (:no-error (connection) ;; Success, make instance (make-instance 'postgresql-socket-database :name (database-name-from-spec connection-spec database-type) :database-type :postgresql-socket :connection-spec connection-spec :connection connection))))) (defmethod database-disconnect ((database postgresql-socket-database)) (close-postgresql-connection (database-connection database)) t) (defmethod database-query (expression (database postgresql-socket-database) result-types field-names) (let ((connection (database-connection database))) (with-postgresql-handlers (database expression) (start-query-execution connection expression) (multiple-value-bind (status cursor) (wait-for-query-results connection) (unless (eq status :cursor) (close-postgresql-connection connection) (error 'sql-database-data-error :database database :expression expression :error-id "missing-result" :message "Didn't receive result cursor for query.")) (setq result-types (canonicalize-types result-types cursor)) (values (loop for row = (read-cursor-row cursor result-types) while row collect row finally (unless (null (wait-for-query-results connection)) (close-postgresql-connection connection) (error 'sql-database-data-error :database database :expression expression :error-id "multiple-results" :message "Received multiple results for query."))) (when field-names (mapcar #'car (postgresql-cursor-fields cursor)))))))) (defmethod database-execute-command (expression (database postgresql-socket-database)) (let ((connection (database-connection database))) (with-postgresql-handlers (database expression) (start-query-execution connection expression) (multiple-value-bind (status result) (wait-for-query-results connection) (when (eq status :cursor) (loop (multiple-value-bind (row stuff) (skip-cursor-row result) (unless row (setq status :completed result stuff) (return))))) (cond ((null status) t) ((eq status :completed) (unless (null (wait-for-query-results connection)) (close-postgresql-connection connection) (error 'sql-database-data-error :database database :expression expression :error-id "multiple-results" :message "Received multiple results for command.")) result) (t (close-postgresql-connection connection) (error 'sql-database-data-error :database database :expression expression :errno "missing-result" :message "Didn't receive completion for command."))))))) (defstruct postgresql-socket-result-set (done nil) (cursor nil) (types nil)) (defmethod database-query-result-set ((expression string) (database postgresql-socket-database) &key full-set result-types) (declare (ignore full-set)) (let ((connection (database-connection database))) (with-postgresql-handlers (database expression) (start-query-execution connection expression) (multiple-value-bind (status cursor) (wait-for-query-results connection) (unless (eq status :cursor) (close-postgresql-connection connection) (error 'sql-database-data-error :database database :expression expression :error-id "missing-result" :message "Didn't receive result cursor for query.")) (values (make-postgresql-socket-result-set :done nil :cursor cursor :types (canonicalize-types result-types cursor)) (length (postgresql-cursor-fields cursor))))))) (defmethod database-dump-result-set (result-set (database postgresql-socket-database)) (if (postgresql-socket-result-set-done result-set) t (with-postgresql-handlers (database) (loop while (skip-cursor-row (postgresql-socket-result-set-cursor result-set)) finally (setf (postgresql-socket-result-set-done result-set) t))))) (defmethod database-store-next-row (result-set (database postgresql-socket-database) list) (let ((cursor (postgresql-socket-result-set-cursor result-set))) (with-postgresql-handlers (database) (if (copy-cursor-row cursor list (postgresql-socket-result-set-types result-set)) t (prog1 nil (setf (postgresql-socket-result-set-done result-set) t) (wait-for-query-results (database-connection database))))))) (defmethod database-create (connection-spec (type (eql :postgresql-socket))) (destructuring-bind (host name user password &optional port options tty) connection-spec (let ((database (database-connect (list host "postgres" user password) type))) (setf (slot-value database 'clsql-sys::state) :open) (unwind-protect (database-execute-command (format nil "create database ~A" name) database) (database-disconnect database))))) (defmethod database-destroy (connection-spec (type (eql :postgresql-socket))) (destructuring-bind (host name user password &optional port optional tty) connection-spec (let ((database (database-connect (list host "postgres" user password) type))) (setf (slot-value database 'clsql-sys::state) :open) (unwind-protect (database-execute-command (format nil "drop database ~A" name) database) (database-disconnect database))))) (defmethod database-probe (connection-spec (type (eql :postgresql-socket))) (when (find (second connection-spec) (database-list connection-spec type) :test #'string-equal) t)) ;; Database capabilities (defmethod db-backend-has-create/destroy-db? ((db-type (eql :postgresql-socket))) nil) (defmethod db-type-has-fancy-math? ((db-type (eql :postgresql-socket))) t) (defmethod db-type-default-case ((db-type (eql :postgresql-socket))) :lower) (defmethod database-underlying-type ((database postgresql-socket-database)) :postgresql) (when (clsql-sys:database-type-library-loaded :postgresql-socket) (clsql-sys:initialize-database-type :database-type :postgresql-socket)) cl-sql-6.4.1/db-postgresql-socket/postgresql-socket-package.lisp0000644000175000017500000000402511335067642023766 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; FILE IDENTIFICATION ;;;; ;;;; Name: postgresql-socket-package.lisp ;;;; Purpose: Package definition for PostgreSQL interface using sockets ;;;; Programmers: Kevin M. Rosenberg ;;;; Date Started: Feb 2002 ;;;; ;;;; This file, part of CLSQL, is Copyright (c) 2002 by Kevin M. Rosenberg ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* (in-package #:cl-user) #+lispworks (require "comm") (defpackage #:postgresql-socket (:use #:cl md5) (:export #:pgsql-ftype #:pgsql-ftype#bytea #:pgsql-ftype#int2 #:pgsql-ftype#int4 #:pgsql-ftype#int8 #:pgsql-ftype#float4 #:pgsql-ftype#float8 #:+crypt-library+ #:postgresql-condition #:postgresql-condition-connection #:postgresql-condition-message #:postgresql-error #:postgresql-fatal-error #:postgresql-login-error #:postgresql-warning #:postgresql-notification #:postgresql-connection #:postgresql-connection-p #:postgresql-cursor #:postgresql-cursor-p #:postgresql-cursor-connection #:postgresql-cursor-name #:postgresql-cursor-fields #:+postgresql-server-default-port+ #:open-postgresql-connection #:reopen-postgresql-connection #:close-postgresql-connection #:postgresql-connection-open-p #:ensure-open-postgresql-connection #:start-query-execution #:wait-for-query-results #:read-cursor-row #:copy-cursor-row #:skip-cursor-row )) cl-sql-6.4.1/db-postgresql-socket/Makefile0000644000175000017500000000011510667176647017464 0ustar kevinkevinSUBDIRS := include ../Makefile.common .PHONY: distclean distclean: clean cl-sql-6.4.1/LATEST-TEST-RESULTS0000644000175000017500000001130012064366222014560 0ustar kevinkevinNote from Russ Tyndall 2012-11-24 : This is the current results of running the test suite against all the database backends I have accessible, on SBCL / UBUNTU64bit. It would be great to continue improving the test suite and skip tests that reliably fail, improve tests so that all pass. In the interim, I would like know that I am not increasing the number of failing :mysql 1 out of 298 total tests failed: :FDDL/CACHE-TABLE-QUERIES/1. :odbc MSSQL2000/5 1 out of 265 total tests failed: :FDDL/CACHE-TABLE-QUERIES/1. :odbc postgres 32 out of 309 total tests failed: :OODML/DB-AUTO-SYNC/4, :OODML/DB-AUTO-SYNC/3, :OODML/UPDATE-INSTANCE/7, :OODML/UPDATE-INSTANCE/6, :OODML/UPDATE-INSTANCE/5, :OODML/UPDATE-INSTANCE/4, :OODML/UPDATE-INSTANCE/3, :OODML/UPDATE-RECORDS/12, :OODML/UPDATE-RECORDS/11, :OODML/UPDATE-RECORDS/9-SLOTS, :OODML/UPDATE-RECORDS/9, :OODML/UPDATE-RECORDS/8, :OODML/UPDATE-RECORDS/7, :OODML/UPDATE-RECORDS/6, :OODML/UPDATE-RECORDS/5-SLOTS, :OODML/UPDATE-RECORDS/5, :OODML/UPDATE-RECORDS/4-SLOTS, :OODML/UPDATE-RECORDS/4, :OODML/SELECT/23, :OODML/SELECT/22, :OODML/SELECT/21, :OODML/SELECT/20, :OODML/SELECT/19, :OODML/SELECT/18, :OODML/SELECT/17, :OODML/SELECT/16, :OODML/SELECT/15, :OODML/SELECT/14, :OODML/SELECT/13, :OODML/SELECT/12, :FDML/SELECT/36, :FDDL/CACHE-TABLE-QUERIES/1. Most of these seem to have to do with not correctly dispatching AUTO_INCREMENT or not correctly skipping those tests :postgres-socket :postgres-socket-3 5 out of 315 total tests failed: :TIME/PG/OODML/USEC, :TIME/PG/OODML/NO-USEC, :TIME/PG/FDML/USEC, :FDML/SELECT/36, :FDDL/CACHE-TABLE-QUERIES/1. :sqlite3 9 out of 267 total tests failed: :FDDL/CACHE-TABLE-QUERIES/1, :FDDL/INDEX/3, :FDDL/ATTRIBUTES/8, :FDDL/ATTRIBUTES/7, :FDDL/ATTRIBUTES/6, :FDDL/ATTRIBUTES/5, :FDDL/ATTRIBUTES/4, :FDDL/ATTRIBUTES/3, :FDDL/ATTRIBUTES/2. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Version 3.0.0 run on August 3, 2004 on x86, x86_64, and PowerPC platforms POSTGRESQL: All 233 tests passed (x86, Allegro CL Enterprise Edition). POSTGRESQL-SOCKET/POSTGRESQL: All 233 tests passed (x86, Allegro CL Enterprise Edition). MYSQL: All 213 tests passed (x86, Allegro CL Enterprise Edition). SQLITE: All 224 tests passed (x86, Allegro CL Enterprise Edition). ODBC/POSTGRESQL: All 232 tests passed (x86, Allegro CL Enterprise Edition). ODBC/MYSQL: All 213 tests passed (x86, Allegro CL Enterprise Edition). ORACLE: All 227 tests passed (x86, Allegro CL Enterprise Edition). AODBC/UNKNOWN: 23 of 231 tests failed (x86, Allegro CL Enterprise Edition). POSTGRESQL: All 233 tests passed (X86, CMU Common Lisp). POSTGRESQL-SOCKET/POSTGRESQL: All 233 tests passed (X86, CMU Common Lisp). MYSQL: All 213 tests passed (X86, CMU Common Lisp). SQLITE: All 224 tests passed (X86, CMU Common Lisp). ODBC/POSTGRESQL: All 232 tests passed (X86, CMU Common Lisp). ODBC/MYSQL: All 213 tests passed (X86, CMU Common Lisp). ORACLE: All 227 tests passed (X86, CMU Common Lisp). POSTGRESQL: All 233 tests passed (NIL, LispWorks). POSTGRESQL-SOCKET/POSTGRESQL: All 233 tests passed (NIL, LispWorks). MYSQL: All 213 tests passed (NIL, LispWorks). SQLITE: All 224 tests passed (NIL, LispWorks). ODBC/POSTGRESQL: All 232 tests passed (NIL, LispWorks). ODBC/MYSQL: All 213 tests passed (NIL, LispWorks). ORACLE: All 227 tests passed (NIL, LispWorks). POSTGRESQL: All 233 tests passed (X86, SBCL). POSTGRESQL-SOCKET/POSTGRESQL: All 233 tests passed (X86, SBCL). MYSQL: All 213 tests passed (X86, SBCL). SQLITE: All 224 tests passed (X86, SBCL). ODBC/POSTGRESQL: All 232 tests passed (X86, SBCL). ODBC/MYSQL: All 213 tests passed (X86, SBCL). ORACLE: All 227 tests passed (X86, SBCL). POSTGRESQL: All 233 tests passed (64-bit AMD64, Allegro CL Enterprise Edition). POSTGRESQL-SOCKET/POSTGRESQL: All 233 tests passed (64-bit AMD64, Allegro CL Enterprise Edition). MYSQL: All 223 tests passed (64-bit AMD64, Allegro CL Enterprise Edition). SQLITE: All 224 tests passed (64-bit AMD64, Allegro CL Enterprise Edition). ORACLE: All 227 tests passed (64-bit AMD64, Allegro CL Enterprise Edition). POSTGRESQL: All 233 tests passed (PowerPC, SBCL). POSTGRESQL-SOCKET/POSTGRESQL: All 233 tests passed (PowerPC, SBCL). MYSQL: All 217 tests passed (PowerPC, SBCL). SQLITE: All 224 tests passed (PowerPC, SBCL). ODBC/POSTGRESQL: All 232 tests passed (PowerPC, SBCL). ODBC/MYSQL: All 217 tests passed (PowerPC, SBCL). POSTGRESQL: All 233 tests passed (ppc, OpenMCL). POSTGRESQL-SOCKET/POSTGRESQL: All 233 tests passed (ppc, OpenMCL). MYSQL: All 217 tests passed (ppc, OpenMCL). SQLITE: All 224 tests passed (ppc, OpenMCL). ODBC/POSTGRESQL: All 232 tests passed (ppc, OpenMCL). ODBC/MYSQL: All 217 tests passed (ppc, OpenMCL). cl-sql-6.4.1/clsql-postgresql-socket3.asd0000644000175000017500000000275011616055736017326 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; FILE IDENTIFICATION ;;;; ;;;; Name: clsql-postgresql-socket.asd ;;;; Purpose: ASDF file for CLSQL PostgresSQL socket (protocol vs 3) backend ;;;; Programmer: Russ Tyndall ;;;; Date Started: Sept 2009 ;;;; ;;;; $Id$ ;;;; ;;;; This file, part of CLSQL, is Copyright (c) 2002 by Kevin M. Rosenberg ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* (defpackage #:clsql-postgresql-socket-system (:use #:asdf #:cl)) (in-package #:clsql-postgresql-socket-system) ;;; System definition (defsystem clsql-postgresql-socket3 :name "cl-sql-postgresql-socket3" :author "Russ Tyndall " :maintainer "Russ Tyndall " :licence "Lessor Lisp General Public License" :description "Common Lisp SQL PostgreSQL Socket Driver" :long-description "cl-sql-postgresql-socket package provides a database driver to the PostgreSQL database via a socket interface." :depends-on (clsql md5 :cl-postgres #+sbcl sb-bsd-sockets) :components ((:module :db-postgresql-socket3 :serial T :components ((:file "package") (:file "api") (:file "sql"))))) cl-sql-6.4.1/clsql-db2.asd0000644000175000017500000000310311332141035014171 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; FILE IDENTIFICATION ;;;; ;;;; Name: clsql-db2.asd ;;;; Purpose: ASDF definition file for CLSQL Db2 backend ;;;; Programmer: Kevin M. Rosenberg ;;;; Date Started: Aug 2002 ;;;; ;;;; This file is part of CLSQL. ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* (defpackage #:clsql-db2-system (:use #:asdf #:cl)) (in-package #:clsql-db2-system) ;;; System definition (defsystem clsql-db2 :name "clsql-db2" :author "Kevin M. Rosenberg " :maintainer "Kevin M. Rosenberg " :licence "Lessor Lisp General Public License" :description "Common Lisp SQL Db2 Driver" :long-description "cl-sql-db2 package provides a database driver to the Db2 database system." :depends-on (clsql-uffi) :components ((:module :db-db2 :components ((:file "db2-package") (:file "db2-loader" :depends-on ("db2-package")) (:file "foreign-resources" :depends-on ("db2-package")) (:file "db2-constants" :depends-on ("db2-package")) (:file "db2-api" :depends-on ("db2-constants" "db2-loader")) (:file "db2-sql" :depends-on ("db2-api" "foreign-resources")) (:file "db2-objects" :depends-on ("db2-sql")))))) cl-sql-6.4.1/ChangeLog0000644000175000017500000037176112134025613013515 0ustar kevinkevin2013-04-17 Kevin Rosenberg * Version 6.4.1 * sql/utils.lisp: Patch from Ben Hyde to add weak hash table support for CCL. 2013-03-07 Ryan Davis * db-postgresql-socket/postgresql-socket-api.lisp - bugfix to adapt to changes in md5:md5sum-sequence. CLSQL now requires a version of MD5 released on or after 2012-11-25 (the latest version currenty in quicklisp). Thanks to Nicolas Neuss for the bug report. * db-odbc/odbc-sql.lisp - keep a reference to the original connection spec used to create `odbc-database` connections 2013-01-09 Russ Tyndall sql/oodml.lisp - changed view-classes-and-storable-slots to a method (as it was intended to be all along) 2012-12-19 Kevin Rosenberg * Version 6.4 2012-11-20 Russ Tyndall ## Large refactoring of sql/oodml.lisp and surrounding code * cleaned up update-records-from-* to utilize a single codepath previously there was much duplicate code * tried to further unify direct/effective slot-defs * cleaned up much of the normalized classes code to be more consistent in how it operated, and the code it used (less copy/paste more functions) * tried to standardize iteration a bit, previously almost all of the iteration constructs in CL were used. Tried to standardize on loop for readability / cohesiveness * made functions to more easily look up particular slots, since this was being done differently in each function * added more doc-strings and updated documentation about normalized classes * inner-joins that are referenced in where clauses are no longer added to the select table list (since they are also referenced in the join position and this led to sql errors) * collect-table-references methods added for sql-ident-table and list ## Semantic changes * disallow where-less updates from objects (ie cannot call update-records-from* with a keyless object) * ordered-class-direct-slots now returns direct-slot-definitions instead of effective-slot-definitions (as per name) * direct-slot-definitions now contain the db-info hash table (same as effective slots) * removed this-class arg from update-instance-from-records - used to be used for normalized code, no longer needed for that. * find-all - bug fixes in table references, previously where clauses surrounded by a list would have none of their references added to the select. This was being exploited by certain code paths. Now all where clauses are searched - No longer includes order-by and distinct as columns in the select list. The values seemed to be ignored in every code path and distinct seemed to be intended to be used as a boolean anyway 2012-11-20 Nathan Bird * update-objects-joins - changed the default of slot from t (which used to mean :deferred) to :immediate (to match the default behavior of other parts of the system). It also seemed like a bad default to pull all the slots that were explicitly specified to be not pulled by default. This function now accepts more special values (:immediate, :deferred, :all, or a list of slots). To get the old behavior call with :slots :deferred. 2012-10-30 Russ Tyndall * sql/command-object.lisp - added dates/times to the parameter value coersion and pulled this into a new generic prepare-sql-parameter 2012-09-04 Kevin Rosenberg * Version 6.3 released 2012-09-04 Russ Tyndall * sql/expressions.lisp - Try to respect the casing of symbols where it seems intentional (ie: is not default). This should fix a failing test case, and I think behaves more understandibly. If you specify a casing '|Foo Bar| lets treat that a string "Foo Bar" and output it escaped 2012-08-28 Ryan Davis * db-sqlite3/sqlite3-api.lisp - allow pathnames in the connection settings, so '("/db/my.sqlite") and '(#P"/db/my.sqlite") are equivalent. Updated the docs to match. 2012-08-17 Russ Tyndall * db-postgresql-socket3/package.lisp - shadow postgresql-notification for compatibility with new cl-postgres (Thanks Zach) 2012-07-09 Russ Tyndall * sql/oodml.lisp - fixed a bug where the order by was being destructively modified, causing odd caching issues when the selected object was not statically known (eg unreferenced tables could show up in the query if they were cached by a previous call through this function. I replaced this code with a non-destructive variant which should solve this. Thanks to Philipp Marek for the bug report 2012-06-25 Russ Tyndall * sql/util.lisp, sql/metaclasses.lisp Dequote database-identifiers if needed (passed a quoted symbol) Metaclass args come through unquoted, so this eases interactions with them 2012-06-22 Russ Tyndall * sql/metaclasses.lisp: Changed compute-effective-slot-definition to correctly copy the autoincrement-sequence slot to the ESD previously it was being skipped (seemingly by accident). Thanks to flip214 on #lisp for the bug report 2012-04-26 Kevin Rosenberg * Version 6.2 released: thanks to all the contributors! 2012-04-25 Nathan Bird * doc/threading-warnings.txt: Adding some notes from J.T.Klein about the current state of thread-safety in clsql. This should be incorporated into the main docs at some point. 2012-04-25 Russ Tyndall * sql/expressions.lisp (output-sql): on rendering update/insert expression values, ensure that *in-subselect* is bound to T so that the values will be correctly paren delimited 2012-04-24 Nathan Bird * sql/expressions.lisp (output-sql): on mysql CREATE TABLE statements use 'ENGINE=innodb' instead of 'Type=InnoDB'. This has apparently been preferred since mysql 4.1 and mysql 5.5 removed type as a valid keyword. 2012-03-28 Russ Tyndall * sql/sequences.lisp: [A Patch FROM 2011-07-28 changed sequences. They were previously prefixed with _CLSQL_SEQ_ but are now suffixed with _CLSQL_SEQ. This is likely to break existing implementations using the default sequence names setting *old-sequence-names* to T, should force using the older naming scheme 2012-03-27 Ryan Davis * sql/expressions.lisp: Fixed bug with subqueries in the where clause of update-records and delete-records generating invalid SQL. Previously subselects in where clauses would not have enough parentheses, for example: "WHERE Id IN SELECT foo_id FROM bar" vs. "WHERE Id IN (SELECT foo_id FROM bar)" * tests/test-syntax.lisp: Added tests for using subqueries in the where clause in update-records and delete-records. Moved asserts in the test-output-sql/sql-ident-table function into the standard test framework. * doc/appendix.xml: added :connection-string to the information on ODBC connection specs, and added example code connecting to ODBC databases. 2012-01-05 Nathan Bird * db-odbc/odbc-dbi.lisp: handle sql decimal type in the same way as numeric type-- read into a double float. 2011-01-04 Russ Tyndall * sql/operations.lisp Fixed bug reported by JTK related to the not-null sql-expression especially as used in conjunction with the is operator. Made null called with more than one argument throw an exception instead of silently discarding all arguments past the first 2012-01-04 Nathan Bird * db-odbc/odbc-api.lisp (%sql-driver-connect): in the call to odbc's SQLDriverConnect default the WindowHandle argument to a null ptr so that connecting with :connection-string will work in the default case of SQL_DRIVER_NOPROMPT. I.e. you can now do things like: (clsql:connect '("DsnName" "UserName" "" :connection-string "DRIVER={FreeTDS};SERVER=...;DATABASE=...;UID=...;PWD=...;PORT=1433;TDS_Version=8.0;APP=clsql") :database-type :odbc) I believe the DsnName and Username at that point are only used when printing the connection information. 2011-12-20 Kevin Rosenberg * Version 6.1.1 * db-oracle/oracle.lisp: Typo correction (Elias Martenson) 2011-12-19 Kevin Rosenberg * Version 6.1.0 * db-oracle/oracle.lisp: Change length function to uffi:foreign-string-length to handle foreign encodings. Thanks to Elias Martenson. 2011-11-28 Russ Tyndall * db-odbc/odbc-api.lisp, tests/test-time.lisp In ODBC backend, avoid going through the common lisp universal-time type (because it lacks support for historic dates) *time-conversion-function* renamed to *time-format* Patch from: Francisco Vides Fernandez 2011-10-18 Russ Tyndall * db-odbc/odbc-api.lisp Added type specifier so MSSQL nvarchar fields can make it through 2011-09-12 Russ Tyndall * sql/fddl.lisp sql/generic-postgres.lisp db-mysql/mysql-sql.lisp sql/generic-odbc.lisp sql/odbc-api.lisp sql/odbc-dbi.lisp Fix bugs in list-attribute(s|-types) where passing an escaped, instead of unescaped column name, caused these functions to return less data than they should have. 2011-08-03 Kevin Rosenberg * CLSQL 6.0.0 released 2011-07-28 Russ Tyndall * db-postgresql-socket3/: Added a backend that utilized postgres socket api version 3. Uses the cl-postgres project (from postmodern) to handle this. Allows use of parameterized / prepared queries using clsql:command-object * sql/{expressions,fddl, generic-postgresql, ooddl}.lisp: Change how database identifiers are emitted to hopefully make this less brittle, and more easily intuitable. Previously every code path that wanted to emit a database identifier was responsible for coercing what was provided into a correctly escaped string. Sometimes two or three functions in a row were trying to correctly quote and output that string. I have tried to centralize this type coercion and logic into a single code path. everything should now call (escaped-database-identifier thing) immediately before splicing a database identifier into string being sent to the database * sql/oodml.lisp: added method choose-database-for-instance, which allows overriding which database connections are used based on object type. Can be used to prevent connection conflicts in multi-threaded environments * sql/syntax.lisp: [foo bar] and [foo.bar] read into the same clsql expression now (they used to be output the same, but after the above database-identifier change, they were output separately * test/: Better, more tests, better type coercion in tests and throughout (%get-int) [edit 2012-03-28 - RT] * sql/sequences.lisp: Sequences were previously prefixed with _CLSQL_SEQ_ but are now suffixed with _CLSQL_SEQ. This is likely to break existing implementations using the default sequence names setting *old-sequence-names* to T, should force using the older naming scheme 2011-07-16 Kevin Rosenberg * Version 5.4.0 release 2011-06-27 Nathan Bird * db-odbc/: memory management improvements: leak slower * MSSQL: TOP + DISTINCT work together 2011-06-20 Nathan Bird * sql/time.lisp: Handle parsing already parsed objects. * sql/oodml.lisp: raise exception if we generate an update with no where clause; incorporate Ryszard Szopa's patch for functional expressions in :order-by * sql/expressions.lisp: (listify nil) => nil instead of (nil). * db-odbc/: bugfixes for working with older versions of FreeTDS; support for bigints that works on mssql and postgres * MSSQL improvements: use top instead of limit, IDENTITY can be a column constraint, clsql:date becomes 'smalldatetime' 2011-06-20 Nathan Bird * Version 5.3.4 * db-postgresql-socket/postgresql-socket-api.lisp: Addendum to Otto Diesenbacher's patch that had a spurious write a 0 byte (to terminate string) that should have been just CCL. 2011-06-12 Kevin Rosenberg * Version 5.3.3 * db-postgresql-socket/postgresql-socket-api.lisp: Patch from Otto Diesenbacher for UTF8 encoded strings for CCL. FIXME: The best patch would be to use the user-set encoding from the database object and use UFFI's encoding strings to/from octet vectors rather than SB-UNICODE and CCL specific code in this file. 2011-04-21 Kevin Rosenberg * sql/generics.lisp: Add defgeneric for new database-last-auto-increment-id 2011-04-01 Kevin Rosenberg * Version 5.3.2 * db-mysql/mysql-client-info.lisp: Add recognition of version 6 of MySQL client library. * sql/metaclass.lisp: Fix the fix in the reader conditional 2011-03-30 Kevin Rosenberg * Version 5.3.1 * sql/metaclasses.lisp: Fix previous patch to work on non-SBCL systems 2011-03-29 Kevin Rosenberg * Version 5.3.0 * sql/metaclasses.lisp: Apply one-line patch to fix for newer SBCL (thanks to Nikodemus Siivola) * many_files: Applied multiple patches from Holger Schauer to improve autoincrement capability. 2010-10-24 Kevin Rosenberg * Version 5.2.0 * db-odbc/odbc-api.lisp: Change from SBCL-specific to UFFI version of octets-to-strings. Reported by Daniel Brunner * sql/oodml.lisp: Apply patch from Rupert Swarbrick : Fix behaviour with auto-inc primary keys. * sql/expressions.lisp, tests/test-syntax.lisp: Apply patch from Russ Tyndall to quote identifiers with space or special character. 2010-09-20 Kevin Rosenberg * Version 5.1.4 * sql/{pool,database}.lisp: Pass encoding argument to connections made from pool and with reconnect. 2010-08-16 Kevin Rosenberg * Version 5.1.3 * db-odbc/odbc-{api,dbi}.lisp: Commit patch from Memet Bilgin to fix issue with unicode and ODBC. 2010-08-16 Kevin Rosenberg * Version 5.1.2 * uffi/clsql-uffi.lisp: Commit patch from JT Klein fixing invocation of uffi:convert-from-foreign-string macro. When time allows, I'll investigate changing UFFI's macro to a function call and then revert this patch. 2010-06-15 Kevin Rosenberg * Version 5.1.1 * clsql-{uffi,mysql}.asd: Modify operation-done-p functions to guard against change introduced in new ASDF traversing. 2010-04-20 Kevin Rosenberg * Version 5.1.0 [DEPENDENCY UPGRADE: UFFI 2.x needed] * clsql-uffi.asd: Depend on UFFI version >= 2.0 to support foreign encoding of strings. 2010-04-16 Kevin Rosenberg * Version 5.0.6 * db-postgresql.lisp, sql/fddl.lisp: Fix typos [Thanks to Walter C. Pelissero] * sql/metaclasses.lisp: Work around type-check-function being set during defclass expansion in SBCL [Thanks to Walter C. Pelissero] * uffi/clsql-uffi.lisp: In call to uffi:convert-from-foreign-string, Set null-terminated-p to T when length not specified. [Thanks to Walter C. Pelissero] 2010-03-21 Kevin Rosenberg * Version 5.0.5 * sql/fdml.lisp: Fix DO-QUERY to actually return the last value of the body. 2010-03-02 Nathan Bird * doc/: Added a README on how to build doc; now builds on Ubuntu. * sql/oodml.lisp: READ-SQL-VALUE now has explicit method for handling double-floats and the default method will no longer attempt to convert values that have already been converted. * sql/syntax.lisp: Introduce file-enable-sql-reader-syntax which enables the syntax for the scope of the file without trying to keep track of the current syntax state. * sql/pool.lisp: Introduce clsql-sys:*db-pool-max-free-connections* which is a heuristic threshold for when to disconnect a connection rather than returning it to the pool. * sql/pool.lisp: Check connections for validity before returning to the user. 2010-03-01 Kevin Rosenberg * db-mysql/mysql-api.lisp: Remove spurious enumeration 2010-02-16 Kevin Rosenberg * Version 5.0.4 * db-mysql/mysql-api.lisp: Fix mysql_options UFFI parameter list * doc/ref-connect.xml: Document the MySQL options parameter as part of the connection-spec. 2010-02-15 Kevin Rosenberg * db-mysql/mysql-{api,sql}.lisp: Support sending options to MySQL using mysql_options, which occurs between the API calls of mysql_init and mysql_real_connect. 2010-02-11 Kevin Rosenberg * Version 5.0.3 * multiple-files: Further internationalization. Change UFFI:CONVERT-RAW-FIELD and UFFI:CONVERT-FROM-FOREIGN-STRINGS invocations to use the foreign character set encoding of the database object. Requires UFFI v.1.8.6 * Makefile.common: Fix OS_DARWIN64 setting 2010-02-11 Nathan Bird * MSSQL: better support for fddl 'date type. 2010-02-11 Kevin Rosenberg * Makefile.common, uffi/Makefile, db-mysql/Makefile: Better support OS X Snow Leopard by building universal (x86_64,i386) dylib bundles 2010-02-08 Kevin Rosenberg * Version 5.0.2 * sql/database.lisp: Fix missing slot-accessor (Thanks to Stelian Ionescu) * sql/generics.lisp: Add missing keyword to defgeneric (Thanks to Stelian Ionescu) 2010-02-07 Kevin Rosenberg * Version 5.0.1 * sql/{base-classes,database}.lisp: Add encoding slot for non-ASCII strings. * db-mysql/mysql-sql.lisp: Use UFFI:FOREIGN-ENCODED-OCTET-COUNT. Requires UFFI version 1.8.2 or above. 2010-02-06 Kevin Rosenberg * Version 5.0.0: First release of CLSQL to formally and consistently support non-ASCII strings with encoding of external formats for SQL strings. UFFI version 1.8.1 is higher is required. This change may introduce some differences in string handling for people who are using non-ASCII encoded characters. Thus, because of the risk of BACKWARD INCOMPATIBILITY, the major version number was incremented with this release. 2010-02-06 Kevin Rosenberg * tests/test-i18n.lisp: Bind UFFI:*DEFAULT-EXTERNAL-FORMAT* for testing multibyte encodings. * uffi/clsql-uffi.lisp: Changes for UFFI 1.7.4's new support for encoding foreign strings with a specified external format. 2010-02-06 Kevin Rosenberg * sql/metaclasses.lisp: If no declared slot type in compute-lisp-type-from-specified-type, then use t as lisp type. Issue noted when testing Clozure CL 1.4. 2010-02-06 Kevin Rosenberg * tests/test-init.lisp: Turn off the benign console notices for testing on postgres. 2010-02-05 Kevin Rosenberg * clsql-test.asd, tests/{test-i18n,test-init}.lisp: Load test-i18n.lisp and use its tests as long as 'uffi:no-i18n is not present in cl:*features*. This requires UFFI 1.7.2 or above. 2010-02-05 Kevin Rosenberg * sql/utils.lisp: Reading #\no-break_space causes an error for non-unicode SBCL. Conditionalize read of #\no-break_space for non-unicode SBCL and 8-bit string Allegro. 2010-02-03 Kevin Rosenberg * tests/test-init.lisp: Add *test-report-width* variable and word-wrap skipped test reason field. 2010-01-29 Kevin Rosenberg * Version 4.3.3 * clsql-cffi.asd: New file that causes CLSQL to use CFFI-UFFI-COMPAT library rather than UFFI. Perform 'asdf:load-op on CLSQL-CFFI rather than CLSQL system to use CFFI-UFFI-COMPAT. 2010-01-29 Nathan Bird * tests/*.lisp: A lot more tests and test setup tweaks. * sql/expressions.lisp: output-sql on sql-relational-exp does better arity checking now. (apply #'sql-and some-list) gives better results. 29 Jan 2009 Kevin Rosenberg * sql/oodml.lisp: Fix for UPDATE-RECORD-FROM-SLOTS for normalized view classes 28 Jan 2009 Kevin Rosenberg * Version 4.3.2 * Change "normalise" from British spelling for consistency with other American spellings in CLSQL. 28 Jan 2009 Kevin Rosenberg * db-mysql/Makefile: Add directory for Fedora 11/12 on 64-bit platform (Thanks to Michael Pheasant) and remove a 32-bit directory 28 Jan 2009 Kevin Rosenberg * Version 4.3.1 * sql/utils.lisp: Ensure Lispworks 6 lock is created in sharing mode 20 Jan 2009 Nathan Bird * Version 4.3.0 * Rewrite tests to use datasets 07 Jan 2009 Kevin Rosenberg * sql/utils.lisp: Changes to support Lispworks 6 10 Dec 2009 Kevin Rosenberg * Version 4.2.0 * doc/ref-ooddl.lisp: Add needed CDATA escapes * doc/clsql.pdf, doc/html.tar.gz: Build new manuals with normalized view classes. 10 Dec 2009 Kevin Rosenberg Large patch from Thijs Oppermann to add support for normalized view classes. When having view class that inherit from others, CLSQL by default builds tab all the columns from the parent in the child. This patch is meant to normali so that a join is done on the primary keys of the concerned tables to get a set. 10 Dec 2009 Kevin Rosenberg * sql/time.lisp: Patch from Oleg Tihonov to SYNTAX-PARSE-ISO-8601 to properly parse fractions of seconds. 10 Dec 2009 Kevin Rosenberg * sql/time.lisp: Patch from Oleg Tihonov to roll function to properly use USEC argument. 21 Nov 2009 Kevin Rosenberg * Version 4.1.2 * Makefiles: On 64-bit Linux systems, try to build both 32 and 64-bit interface libraries. This requires the installation of multiarch build tools as well as 32-bit support libraries (libc, libz and libmysqlclient). 04 Sep 2009 Kevin Rosenberg * Version 4.1.1 * sql/fdml.lisp: Rework do-query to use supplied database parameter when passed a sql-object-query (thanks to JTK ) * sql/generic-postgresql.lisp: Allow optional connect parameters for postgresql databases (thanks to Stephen Compall) * doc/ref-{clsql,connect}.xml, sql/db-interfaces.lisp: Fix transposed letters (thanks to Stephen Compall) * db-mysql/Makefile: Add directory for MacPorts mysql5 port (thanks to Stephen Compall) * sql/database.lisp: Have database-type default be *default-database-type* (thanks to Desmond O. Chang) * sql/transactions.lisp: Improved handlining of nested transactions (thanks to Eli Naeher) * sql/time.lisp: Commit patch to fix parse-iso-8601-duration (thanks to Stephen Compall) * sql/database.lisp: Use :verbose nil for asdf:operate invocation (Thanks to Mackram Raydan) * sql/metaclasses.lisp: Rework initialize-instance for view-class-direct-slot-definition (thanks to Stephen Compall) 31 Aug 2009 Kevin Rosenberg * sql/db-interface.lisp: Fix spelling error (thanks to David Thompson) * clsql-mysql.asd/db-mysql/mysql-loader.lisp: Commit patch from Andreas Franke to honor windows drive letter when loading clsql_mysql C library. 31 Aug 2009 Kevin Rosenberg * Version 4.1.0 * db-mysql/mysql-{sql,api}.lisp,db-mysql/clsql_mysql.c: Latest version of mysqlclient once again changed the C structures from which the mysql backend reads data. Rather than adding yet another structure definition which is enabled by the client version as read by mysql-client-info.lisp, the mysql backend has been re-written to ignore in the internal C structures. Instead, C wrapper functions for slot access have been added to clsql_mysql.c and are used by mysql-sql.lisp to access the internals of C structures. This adds a bit of overhead, but completely separates the lisp code from trying to keep up with the continually changing internal C structure of mysql. All tests in the test suite executed correctly with this change. 31 Aug 2009 Kevin Rosenberg * Version 4.0.6 * sql/database.lisp: Fix syntax on process-lock (thanks to Stian Sletner) * db-mysql/mysql-sql.lisp: Allow use of database parameter in database-list function (thanks to Michael Pheasant) * sql/oodml.lisp: Allow NULL values for floating-point fields (thanks to Jan Rychter) 02 Jun 2009 Kevin Rosenberg * Version 4.0.5 * sql/database.lisp: Add process-lock for deleting database from a pool (thanks to Ralf Mattes). 25 Feb 2008 Kevin Rosenberg * Version 4.0.4 * sql/expressions.lisp: Remove stray form (thanks to Samuel Ward) 12 Dec 2007 Kevin Rosenberg * sql/expressions.lisp: Bind *in-subselect* when outputting selections (patch from unknown source). 11 Dec 2007 Kevin Rosenberg * Version 4.0.3 * sql/metaclasses.lisp: Unify base-table processing by extracting the correct code from initialize-instance :around into the helper function set-view-table-slot. Call that function also in reinitialize-instance :around replacing erroneous code discovered by Josh Feinstein. 17 Nov 2007 Kevin Rosenberg * BUGS: Add note about benefit of using configure file to create Makefiles (suggestion from Joe Corneli) 22 Oct 2007 Kevin Rosenberg * Version 4.0.2 * db-postgresql/postgresql-sql.lisp: Patch from Gabriele Favalessa based on Andrew Golding suggestion for more informative :error-id slot. 17 Sep 2007 Kevin Rosenberg * Version 4.0.1 * db-mysql/mysql-sql.lisp: Convert query to uffi cstring (thanks to Albert Krewinkel). * doc/Makefile, doc/html.xsl: Change output encoding from ISO-8859-1 to UTF-8 14 Sep 2007 Kevin Rosenberg * Version 4.0.0: Major version increase to warn of potential backwards incompatibility. * NEWS: Document potentional backward incompatible changes * db-mysql/mysql-sql.lisp: Changes session SQL mode to ANSI immediately after connecting. This may break compatibility with some applications who are using non-ANSI features with MySQL. This change is required to properly support view-classes using a string as their :base-table attribute. This allows users to specify the case of table names. This is feature is even more essential for MySQL itself since MySQL uses case-sensitive table names. Use connection-based database-create and database-destroy rather than trying to invoke command-line mysql utility. Remove automatic upcasing of strings from list-indices. * db-postgresql/postgresql-sql.lisp: Use connection-based database-create and database-destroy rather than trying to invoke command-line utilities. * db-postgresql-socket/postgresql-socket-sql.lisp: Use database-execute-command rather than execute-command for database-{create,destroy}. Connect to postgres database rather than template1 for those database creation/deletion. * sql/metaclasses.lisp: Store the string value of :base-table if a string is provided. Perform sql-escape at time of view-table name creation. * tests/test-init.lisp: Use "ej_join" as a string, rather than a symbol, since "ej_join" is specified as :base-table. Clear the expression output-cache in case the code for generating sql output has changed. * test/test-oodml.lisp: whitespace fix * sql/ooddl.lisp: Use quoted string for primary key constraint if table name is specified as a string. * sql/oodml.lisp: Don't convert a string view-table name to database's default case. * sql/expressions.lisp: Properly handle table and attribute identifiers when they are a string. Do not change case of symbols to match database default case. * sql/operations.lisp: Change multiword symbols to upper case. * sql/fddl.lisp: Quote base-table if a string to preserve case for drop-table and create-table. * tests/test-syntax.lisp: Add tests of low-level string attribute identifiers. 20 Jul 2007 Kevin Rosenberg * Version 3.8.6 * db-oracle/oracle-loader.lisp: Rework use of ORACLE_HOME directory (problem noted on clsql-devel by icardo Boccato Alves) * sql/pool.lisp: Remove incorrect keyword * sql/database.lisp: Rework WITH-DATABASE to not make the database the default database (reported by Saurabh Nanda and Chaitanya Gupta) * doc/ref-connect.lisp: Update the documentation to WITH-DATABASE to emphasis that make-default has a default value of nil. * sql/transaction.lisp: Adjust commit/rollback messages for Microsoft SQL Server. (patch from Nathan Bird) * sql/metaclasses.lisp: Use finalize-inheritance hack on SBCL because of trouble with def-view-class compilations (patch from Nathan Bird) 15 Jul 2007 Kevin Rosenberg * Version 3.8.5 * db-mysql/mysql-loader.lisp: Revert previous change since libmysql is not dynamically loaded on Windows 22 Jun 2007 Kevin Rosenberg * Version 3.8.4 * db-mysql/mysql-loader.lisp: Do not bother loading libmysqlclient since that library is dymically linked to clsql-mysql library. Thus, the mysql library will be automatically loaded. This has only been tested on Linux, thus far. 29 May 2007 Kevin Rosenberg * tests/test-fddl.lisp: Add :order-by for :fddl/big/1 as reported by Ricardo Boccato Alves 02 May 2007 Kevin Rosenberg * sql/database.lisp: Add ability of WITH-DATABASE to return multiple values (patch from Liam Healy) 25 Apr 2007 Kevin Rosenberg * Version 3.8.3 * doc/connect.xml: variable description fix by Liam Healy * db-sqlite3/sqlite3-api.lisp, uffi/clsql-uffi-loader.lisp: Apply patches from Marcus Pierce to reduce load-time warnings * sql/package.lisp: Export iso-timestring as requested by Kevin Blaisdell 23 Mar 2007 Kevin Rosenberg * Version 3.8.2 * sql/db-postgresql-socket-api.lisp: Change read-socket-sequence to disable wide characters for crypt salt sequence on SBCL, based on patch from Lars Nostdal. 26 Jan 2007 Kevin Rosenberg * Version 3.8.1 * sql/pool.lisp: Test pooled connection when popped from the pool to ensure the connection still works. Currently, implemented only for MySQL. 17 Jan 2007 Kevin Rosenberg * db-mysql/Makefile: Add potential mysql directories 31 Dec 2006 Kevin Rosenberg * sql/metaclasses.lisp: Remove usused saved-initargs * clsql.asd: Also check ~/.clsql-init.lisp at load-time (usually used to push search libraries) 30 Dec 2006 Kevin Rosenberg * Version 3.8.0: BACKWARD INCOMPATABLE CHANGE! * db-postgresql/postgresql-{api,loader,sql,package}.lisp: Apply patch from Edi Weitz to avoid conflict with new Lispworks 5 POSTGRESQL package name. CLSQL's new package will be PGSQL, however on non-Lispworks platforms, the nickname POSTGRESQL will still be available. Applications directly using low-level POSTGRESQL package are recommended to use the new PGSQL name. * db-oracle/oracle-{api,sql}.lisp, sql/{expressions,loop-extension}.lisp, Apply patch from Edi Weitz to reduce compiler warnings. 28 Dec 2006 Kevin Rosenberg * Version 3.7.9 * sql/expressions.lisp: Commit patch from Edi Weitz to use *default-database* for SQL-OUTPUT if no database is explicitly passed to function. * uffi/clsql-uffi-loader.lisp: Change load order to first try plain name/type before attempting user-specified paths (patch from Edi Weitz) * uffi/ptrbits.c: New file to return number of bits in an pointer * uffi/Makefile: use intbits to name .so file based on bit size. Build both 32-bit and 64-bit libraries on 64-bit platform. 30 Nov 2006 Kevin Rosenberg * Version 3.7.8 * db-sqlite3/sqlite3-sql.lisp: Commit patch from Edi Weitz fixing error display 16 Oct 2006 Kevin Rosenberg * Version 3.7.7 * db-postgresql/postgresql-sql.lisp: Remove uffi:convert-foreign-to-native wrapper since using cstring for PQresultErrorField 16 Oct 2006 Kevin Rosenberg * Version 3.7.6 * db-postgresql/postgresql-api.lisp: Fix UFFI return type for PQresultErrorField foreign function. 16 Oct 2006 Kevin Rosenberg * Version 3.7.5 * doc/intro.xml: Update supported platforms. * db-postgresql/postgresql-{package,api,sql}.lisp: Apply changes from Andew Golding to use a more-specific error code from PostgreSQL than the generic fatal error code of the result set. 03 Oct 2006 Kevin Rosenberg * sql/syntax.lisp: Commit patch from Marcus Pearce to improve readtable modifications 02 Oct 2006 Kevin Rosenberg * sql/syntax.lisp: Check that original reader syntax functions stored before trying to restore them. 20 Sep 2006 Kevin Rosenberg * sql/syntax.lisp: Apply patch from Marcus Pearce to correctly display sql reader syntax. 06 Sep 2006 Kevin Rosenberg * uffi/clsql-uffi-loader.lisp, db-mysql/mysql-loader.lisp: Change from using *features* to decide on 64-bit platform and check size of most-positive-fixnum instead. Needed to support clisp amd64. 03 Sep 2006 Kevin Rosenberg * Version 3.7.1 * sql/metaclasses.lisp: Rework slot type's to be more AMOP compatibile. Add warning for a metaclass condition that should not occur. * sql/time.lisp: Fixed symbol case inconsistency causing problem in AllegroCL's modern lisp. First sign of bug noted by Joel Reymond on clsql-devel. * clsql.asd: Make time.lisp depend on utils.lisp 31 Aug 2006 Kevin Rosenberg * db-mysql/mysql-loader.lisp: Apply patch from Marcus Pearce to push *library-file-dir* to CLSQL's library path. 30 Aug 2006 Kevin Rosenberg * Version 3.7.0: New platforms supported: SBCL/Win32, CLISP/Win32, CLISP/Cygwin, CLISP/Linux x86, CLISP/Linux amd64, OpenMCL amd64. CLISP support requires the latest development versions of CLISP, cffi, and cffi-uffi-compat packages. * Makefile.common: Add OS detection * uffi/make.sh, db-mysql/make.sh: Remove files * uffi/Makefile, db-mysql/Makefile: Add support for cygwin compilation. Refactor to remove need to make.sh shell scripts. * clsql.asd: Add support for loop extensions for clisp. Support clisp via cffi. * sql/loop-extension.lisp: Define loop-record-iteration-path in CLSQL-SYS package rather than CL-USER. Add support for ansi-loop on clisp. * sql/ansi-loop.lisp: New file to support iteration on clisp. * db-mysql/mysql-api.lisp: Remove old mysql C API functions that no longer exist in the mysql client library. * doc/ref-fdml.lisp: Correct default field-type. * sql/expressions.lisp: Use database-output-as-type if value exists for boolean output. Fixed bug with noted with MySQL 5.0.24 and boolean values. 28 Aug 2006 Kevin Rosenberg * Version 3.6.7 * sql/oodml.lisp: Remove high debugging level declaration 14 Aug 2006 Kevin Rosenberg * Version 3.6.6 * sql/generic-postgresql.lisp: Fix assumption that postgres user id is always 1. Fixes problem noted with PostgreSQL 8.1. 12 Aug 2006 Kevin Rosenberg * Version 3.6.5 * sql/generic-postgresql.lisp: Add slot for has-table-pg_roles to lazily cache if pg_roles tables exist. Selectively use SQL from Joel's previous patch if pg_roles table exists. Should now work with both postgresql 7.4 and 8.x. 12 Aug 2006 Kevin Rosenberg * Version 3.6.4 * clsql.asd: Add support for c:\etc\clsql-init.lisp as possible local initialization file * db-mysql/mysql-loader.lisp: Remove former method of using pathnames as name candidates. * db-odbc/odbc-api.lisp: Work-around Allegro/Windows FFI bug that generates incorrect integer return type * sql/generic-postgresql.lisp: Revert patch from Joel Reymont since it fails on versions of postgresql that lack the pg_role table 07 Jul 2006 Kevin Rosenberg * Version 3.6.3 * sql/transactions.lisp: Important typo fix from Alexey Antipov for database-start-transaction 04 Jul 2006 Kevin Rosenberg * Version 3.6.2 * db-postgresql/postgresql-sql.lisp: Apply patch from Vladimir Sekissov to close connection when failing to connect to database. * sql/generic-postgresql.lisp: Apply patch from Joel Reymont to avoid dropping system views. * sql/oodml.lisp: Apply patch from Joel Reymont to avoid listify a nil value [patch sponsored by Flektor] * clsql-uffi.asd, uffi/make.sh: Patch from Richard Kreuter for netbsd compilation 15 May 2006 Kevin Rosenberg * doc/ref-ooddl.xml: Add documentation for :db-reader and :db-writer slots for def-view-class macro [as reported missing by Thomas Fischbacher]. 09 May 2006 Kevin Rosenberg * db-postgresql-socket/postgresql-socket-api.lisp: Apply patch from Marko Kocic adding the socket creation function needed for CLISP. 08 May 2006 Kevin Rosenberg * Version: 3.6.0 (requires UFFI v1.5.11 or greater) * db-oracle/metaclasses.lisp: Patch from James Bielman for checking slot constraints. * db-oracle/oracle-{api,sql}.lisp: Avoid dead pointers on loading saved openmcl images (based on patch from James Bielman) 06 May 2006 Kevin Rosenberg * doc/ref-fdml.xml: Documentation patch from Marcus Pearce for limit keyword 03 May 2006 Kevin Rosenberg * Version 3.5.7 * sql/time.lisp: Apply patch from Aleksandar Bakic to extended duration parsing and unparsing to include year and month. * clsql-uffi.asd, uffi/clsql-uffi-loader.lisp: Apply patch from Nathan Bird improving library search on Windows platform. * doc/ref-fdml.xml, /doc/TODO, tests/test-fdml.lisp, tests/test-init.lisp: Apply patch from Marcus Pearce documenting and testing :limit and :offset for SELECT 20 Mar 2006 Kevin Rosenberg * Version 3.5.6 * clsql-postgresql-socket.asd, * db-postgresql-socket/postgresql-socket-package.lisp: Use the cl-md5 package on all platforms. Based on report from Alan Caulkins. 09 Mar 2006 Kevin Rosenberg * Version 3.5.5 * uffi/make.sh, db-mysql/make.sh: Add GNU uname 28 Feb 2006 Kevin Rosenberg * Version 3.5.4 * sql/metaclasses.lisp: Apply patch from Friedrich Dominicus to fix accessor for new versions of SBCL * db-oracle/oracle-sql.lisp: Apply patch from James Bielman to improving parsing of time. * db-db2/db2-constants.lisp: Change NULL_HANDLE has suggested by Harold Lee. * db-oracle/oracle-dbi.lisp: Add support for SQL BIT type as noted by Russ Tyndall. 16 Jan 2006 Kevin Rosenberg * Version 3.5.3 * sql/time.lisp: Commit patch from Aleksandar Bakic to properly handle destructive flag * db-postgresql-socket/postgresql-socket-api.lisp: Apply patch from Steven Harris for socket files with SBCL. * sql/pool.lisp: Apply patch from Vladimir Sekissov so that new connections added to the pool do not become the *default-database* * sql/connect.lisp: Optionally set *default-database* for pooled connection when make-default is generalized true. 23 Dec 2005 Kevin Rosenberg * Version 3.5.1 * sql/expressions.lisp: Ensure table names are properly escaped before comparing -- fixes bug reported by Asbjørn Bjørnstad on CLSQL-Devel. 02 Dec 2005 Kevin Rosenberg * sql/generic-postgresql.lisp: improved decoding of table attribute parameters [from Vladimir Sekissov] * sql/metaclasses.lisp: check that metaclass is standard-db-class or it's subclass to prevent adding standard-db-object to supers if somebody in the path has it already when metaclass inherited from standard-db-class. [from Vladimir Sekissov] 26 Nov 2005 Kevin Rosenberg * Version 3.5.0 * tests/test-init.lisp, tests/test-fddl.lisp, tests/test-fdml.lisp, * db-odbc/odbc-api.lisp, db-odbc/odbc-ff-interface.lisp, * db-odbc/odbc-package.lisp, db-odbc/odbc-constants.lisp * db-odbc/odbc-dbi.lisp, db-odbc/odbc-sql.lisp * sql/fddl.lisp, sql/generic-odbc.lisp, sql/db-interface.lisp * sql/transaction.lisp, sql/package.lisp, sql/time.lisp Commit patch from Dominic Robinson providing support for Microsoft SQL Server * doc/csql.lisp: Fix typo in slot name 24 Nov 2005 Kevin Rosenberg * Version 3.4.7 * sql/time.lisp: Commit patch from Aleksandar Bakic for correct handling of decode-time usec value * clsql-mysql.asd: Commit patch from Harald Hanche-Olsen to correct the name of the shared library file. 16 Nov 2005 Kevin Rosenberg * version 3.4.6 * sql/metaclasses.lisp: Avoid calling change-class on effective-slot-definitions on sbcl to conform to sbcl 0.9.6.38 changes. 15 Nov 2005 Kevin Rosenberg * Version 3.4.5 * sql/expressions.lisp: Patch from James Biel to add subselects 14 Nov 2005 Kevin Rosenberg * Version 3.4.4 [ Requires UFFI 1.5.7+] * db-oracle/oracle-{api,sql}.lisp: Patch from James Biel to fix lifetime of foreign strings for Oracle calls 13 Nov 2005 Kevin Rosenberg * Version 3.4.3 * db-oracle/oracle-{api,sql}.lisp: Patch from James Biel to improve performance 12 Nov 2005 Kevin Rosenberg * Version 3.4.2 * clsql-uffi.asd: Patch from James Biel improving loading * db-oracle/oracle-{api,sql}.lisp: Patch from James Biel to support 64-bit lisps 12 Nov 2005 Kevin Rosenberg * Version 3.4.1 * sql/expressions.lisp: Escape numbers to SQL strings at expression level. 11 Nov 2005 Kevin Rosenberg * Version 3.4: Add MySQL 5 support * db-mysql/mysql-client-info.lisp: Recognize MySQL 5 * db-mysql/mysql-sql.lisp: Add support for views in MySQL 5 * doc/mysql-macosx-notes.txt: New document from Martin Brooks 7 Nov 2005 Kevin Rosenberg * src/time.lisp: Apply patch from Aleksandar Bakic for ROLL function. * BUGS: Added report for update-object-joins by Aleksandar Bakic 4 Nov 2005 Kevin Rosenberg * Version 3.3.4 [UFFI >= 1.5.5 needed] * db-odbc/odbc-api.lisp: Apply patch from Yaroslav Kavenchuk to add missing #\' character. * clsql.asd: Add support for CLSQLINIT environmental variable, based on patch from Yaroslav Kavenchcuk. New version of UFFI required. 30 Oct 2005 Kevin Rosenberg * Version 3.3.3 * sql/oodml.lisp: Apply patch from Drew Crampsie to fix update-objects-joins when using the :target-slot attribute 26 Oct 2005 Kevin Rosenberg * Version 3.3.2 * sql/expressions.lisp: Avoid parenthesis on multiple group-by fields as noted by Harald Hanche-Olsen. * tests/test-syntax.lisp: Add test for multiple field group-by 25 Oct 2005 Kevin Rosenberg * Version 3.3.1 * sql/time.lisp: Commit patch from Alan Shields to display escape string on wall-time display only when *print-escape* is true. 11 Oct 2005 Kevin Rosenberg * sql/metaclasses.lisp: Commit patch from Will to properly set db-reader slot in effective-slot-definition * sql/expressions.lisp: Commit patch from Alan Shields adding make-load-form for sql-relational-exp * sql/generic-postgresql.lisp: Commit patch from Aleksandar Bakic adding support for new NUMBER type 17 Sep 2005 Kevin Rosenberg * Version 3.3.0 * sql/time.lisp: Apply patch from Alan Shields adding DATE type. * doc/ref-ooddl.xml: Documentation of new type * notes/add-type-hints.txt: New file from Alan Shields * sql/fddl.lisp: Add owner keyword to drop-table as suggested by Francis Leboutte * db-postgresql-socket/postgresql-socket-sql.lisp: Fix database-probe as noted by Francis Leboutte. Similar fix applied to db-mysql and db-postgresql. * sql/expressions.lisp: Allow string table names for output as contributed by Francis Leboutte. * examples/clsql-tutorial.lisp: Support :postgresql-socket as noted by Francis Leboutte 08 Sep 2005 Kevin Rosenberg * Version 3.2.4 * doc/into.xml: Change download from ftp to http protocol 08 Sep 2005 Kevin Rosenberg * Version 3.2.3 * db-oracle/oracle-sql.lisp: Correction for v3.2.2 changes by Edi Weitz 08 Sep 2005 Kevin Rosenberg * Version 3.2.2 * db-oracle/oracle-sql.lisp: Add check for zero increment as suggested by Edi Weitz. Add missing database-sequence-last function as noted and tested by Edi Weitz. Ensure that UFFI buffer is freed in handle-oci-error. Add unwind-protect to sql-stmt-exec. Free UFFI stmthp object when query cursor is freed with OCI. 22 Aug 2005 Kevin Rosenberg * uffi/clsql-uffi-loader.lisp: Commit patch from astor@pvv.ntnu.no to display search path when error occurs loading foreign library. 05 Jul 2005 Kevin Rosenberg * Version 3.2.1 * doc/appendix.xml: Incorporate Edi Weitz's notes into documentation with changes to support case-sensitive lisp implementations. Add paragraph on using /etc/clsql-init.lisp site initialization file. * clsql.asd: Load file /etc/clsql-init.lisp, if it exists, after package is loaded to set site-specific configuration 2005-06-24 Edi Weitz * sql/db-interface.lisp: Added new special variable *FOREIGN-LIBRARY-SEARCH-PATHS* and function PUSH-LIBRARY-PATH to manipulate it. * sql/package.lisp: Export these. * uffi/clsql-uffi-loader.lisp: Used new variable; changed order of libs. * db-mysql/mysql-loader.lisp: Changed order of libs. 09 Jun 2005 Kevin Rosenberg * Version 3.2.0: REQUIRES UFFI VERSION 1.4.38 OR HIGHER * clsql-mysql.asd: Renamed clsql/mysql interface library from mysql to clsql_mysql * clsql-uffi.asd: Renamed clsql/uffi interface library from mysql to clsql_uffi * uffi/clsql_uffi.c: Renamed from uffi.c * db-mysql/clsql_mysql.c: Renamed from mysql.c * db-mysql/Makefile, db-mysql/Makefile.msvc, db-mysql/mysql-loader.lisp: Rename shared library * uffi/Makefile, uffi/Makefile.msvc, uffi/uffi-loader.lisp: Rename shared library * db-*/*-loader.lisp: Commit big patch from Edi Weitz to remove absolute pathnames when searching for foreign libraries. foreign library loading. 07 Jun 2005 Kevin Rosenberg * Version 3.1.16 * db-mysql/mysql-api.lisp: Commit patch from Espen Wiborn to support UTF-8 on sbcl unicode. 18 May 2005 Kevin Rosenberg * Version 3.1.15 * sql/time.lisp: Fix bug in roll that caused failure in test suite 17 May 2005 Kevin Rosenberg * Version 3.1.14 * sql/oodml.lisp: Properly handle when db-writer is NIL 11 May 2005 Kevin Rosenberg * sql/expressions.lisp: Avoid using simple-string declaration when a non-simple string may be encountered. [issue noted by will@cesmail.net] Add a simple-string declaration for a local string generated. 06 May 2005 Kevin Rosenberg * sql/oodml.lisp: Change db-writer and db-reader processing to accept a symbol as well as function to serve as a function designator [issue noted by will@cesmail.net] 05 May 2005 Kevin Rosenberg * Version 3.1.13 * sql/time.lisp: Fix error in submitted patch which caused error in timestrings with 19 or less characters. 27 Apr 2005 Kevin Rosenberg * Version 3.1.12 * db-postgresql-socket/postgresql-api.lisp: Commit patch from Tim Howe to fix read-socket-sequence on non-sb-unicode sbcl. 26 Apr 2005 Kevin Rosenberg * Version 3.1.12 * sql/time.lisp: Commit patch from Daniel Lowe which adds support for fractional seconds which is required by PostgreSQL * db-postgresql/postgresql-loader.lisp: Add library path for Windows 25 Apr 2005 Kevin Rosenberg * sql/csql.lisp: Update URL for "SQL for Web Dummies" [Sean Champ] 24 Apr 2005 Kevin Rosenberg * Version 3.1.11 * sql/syntax: Commit patch from Alan Shields to supress reader macros when *read-supress* is T. 13 Apr 2005 Kevin Rosenberg * Version 3.1.10 * db-postgresql-socket/postgresql-socket-api.lisp: Commit patch from Janis Dzerins to support unicode on SBCL * sql/syntax: Commit patch from Alan Shields to improve reporting of invalid syntax statements. 06 Apr 2005 Kevin Rosenberg * Version 3.1.9 * db-mysql/mysql-sql.lisp: Add port to connection specification based on patch from Dave Watson * doc/appendix.xml: Document MySQL port parameter to connection spec 03 Apr 2005 Kevin Rosenberg * Version 3.1.8 * sql/time.lisp: Patch from Keith James for parsing ISO-8601 timestamps 18 Mar 2005 Kevin Rosenberg * sql/oodml.lisp: Add missing database argument [Patch from Alan Caulkins] 03 Mar 2005 Kevin Rosenberg * sql/oodml.lisp: Improve database priority in update-records-from-instance [Patch from Walter C. Pelissero] 17 Feb 2005 Kevin Rosenberg * Version 3.1.7 * sql/package.lisp: Export database-reconnect from clsql-sys 08 Feb 2005 Kevin Rosenberg * sql/oodml.lisp: Use explicit database in fault-join-target-slot [Patch from Walter Pelissero] 29 Jan 2005 Kevin Rosenberg * db-postgresql/postgresql-loader.lisp: Add additional directories to Fink on darwin [patch from Cyrus Harmon]. 29 Jan 2005 Kevin Rosenberg * Version 3.1.6 * sql/oodml.lisp: Clear view instance cache when delete-instance-records is invoked [suggested by Alan Shutko]. * uffi/clsql-uffi-loader.lisp: Improvements for loading with SBCL X86-64 * sql/metaclasses.lisp: Don't change case of a :base-table string supplied to def-view-class [fix suggested by Fred Gilham]. 25 Jan 2005 Kevin Rosenberg * tests/*.lisp: Change Vladamir to Vladimir per Cyrus Harmon's suggestion. * sql/utils.lisp: Fix unnecessary consing noted by Fred Gilham. * doc/*.xml: Fix spelling of Vladimir 24 Jan 2005 Kevin Rosenberg * doc/bookinfo.xml, doc/csql.xml, doc/intro.xml: Update links now that LispWorks is an independant company [noted by Martin Thornquist] 22 Jan 2005 Kevin Rosenberg * db-sqlite/sqlite-sql.lisp, db-sqlite3/sqlite3-sql.lisp: Better support for 64 bit environments 05 Jan 2005 Kevin Rosenberg * Version 3.1.5 * sql/metaclass.lisp: Make t the default value of :set [noted by Cyrus Harmon] 28 Dec 2004 Kevin Rosenberg * Version 3.1.4 * uffi/clsql-uffi.lisp: Add support for unsigned integers * db-mysql/mysql-sql.lisp: Add support for detecting/marking unsigned integers. Apply patch from Yannick Gingras to implement database-sequence-last. 26 Dec 2004 Kevin Rosenberg * doc/ref-fdml.lisp: Fix variable tag name to varname [noted by Eduardo Munoz] * db-mysql/mysql-loader.lisp: Handle library paths for 64-bit systems 06 Dec 2004 Kevin Rosenberg * Version 3.1.2 * sql/ooddl.lisp: Accept patch from Klaus Harbo for update-object-joins. * sql/metaclass.lisp: Remove unnecssary (and runtime error causing) change-class invocation when running on CLISP. * db-mysql/mysql-api.lisp: Commit patch from Paul Werkowski to fix structure name. * sql/database.lisp: More specific error message with trying to use a database value of NIL. * sql/expressions.lisp: Accept a string for the table name in (sql-output sql-delete database) [suggested by Ed Symanzik]. 11 Nov 2004 Kevin Rosenberg * Version 3.1.1 * sql/generic-postgresql.lisp: Commit patch from Chris Capel to ignore columns which have been dropped. * clsql-postgresql-socket.asd, db-postgresql-socket/postgresql-socket-package.lisp: Use sb-md5 package on SBCL, recommended by Chris Capel 09 Nov 2004 Kevin Rosenberg * Version 3.1.0 released: New SQLite3 backend by Aurelio Bignoli * doc/appendix.xml: Document SQLITE3 backend, patch by Aurelio Bignoli * sql/operations.lisp: Add lower and upper SQL functions [Daniel Lowe]. 08 Nov 2004 Kevin Rosenberg * sql/expressions.lisp: Fix slot name [thanks to Daniel Lowe] 31 Oct 2004 Kevin Rosenberg * clsql-sqlite3, db-sqlite3/*: NEW BACKEND contributed by Aurelio Bignoli 23 Oct 2004 Kevin Rosenberg * sql/oodml.lisp: Commit patch from Walter Pelis to use an object's database for a select on its slot. 20 Oct 2004 Kevin Rosenberg * uffi/uffi.c, uffi/clsql-uffi.lisp: Commit patch from Aurelio Bignoli to fix negative 64-bit integers 07 Oct 2004 Kevin Rosenberg * db-mysql/mysql.c: Fix parameters in bind_param call 07 Oct 2004 Kevin Rosenberg * uffi/clsql-uffi.lisp: Add support for :blob result-type * db-mysql/mysql-sql.lisp: Add support for :blob result-type 04 Oct 2004 Kevin Rosenberg * db-mysql/mysql-sql.lisp, db-db2/db2-sql.lisp: Add missing quotes for types in code that is still in development (thanks to Joerg Hoehle) 03 Oct 2004 Kevin Rosenberg * Version 3.0.8 released * db-sqlite/sqlite-*.lisp: Apply patch from Aurelio Bignoli with improvements 01 Oct 2004 Kevin Rosenberg * multiple: Apply patch from Joerg Hoehle with multiple improvements. 01 Oct 2004 Kevin Rosenberg * Version 3.0.7 released * sql/oodml.lisp, sql/package.lisp, db-mysql/mysql-objects.lisp: Add support for mediumint. * sql/metaclass.lisp: Rework CLISP MOP handling * sql/ooddl.lisp: Work-around to have CLISP finalize standard-db-class 28 Sep 2004 Kevin Rosenberg * sql/metaclass.lisp: Support CLISP's attribute name for the type field in direct class slots 27 Sep 2004 Kevin Rosenberg * Version 3.0.6 released * BUGS: New file. Document suspected SIGPIPE interaction between SBCL and libpq used in postgresql backend. * doc/ref-fdml.lisp: Document the :caching and :refresh keywords of the SELECT function. * doc/ref-ooddml.lisp: Document the new *default-caching* variable. * sql/package.lisp: Export *default-caching* * sql/oodml.lisp: Use *default-caching* to control default caching behavior. 21 Sep 2004 Kevin Rosenberg * Version 3.0.5 release * doc/appendix.xml: Add note about loading Oracle8 version * db-oracle/oracle-loader.lisp: Support Oracle8 based on data from David Young. 10 Sep 2004 Kevin Rosenberg * doc/Makefile, doc/catalog-darwin.xml: Apply patch from Cyrus Harmon for building docs on Mac OS X * sql/package.lisp: Add new (pre-release) clisp MOP package 09 Sep 2004 Kevin Rosenberg * Version 3.0.4 Release * multiple: Remove superfluous quotes in UFFI def-type and def-foreign-type forms. 07 Sep 2004 Kevin Rosenberg * Version 3.0.3 Release * db-postgresql-socket/postgresql-socket-api.lisp: Commit patch from Tagore Smith to call force-output after sending authentication * db-odbc/odbc-api.lisp: Move ODBC v3 conversons * db-odbc/odbc-sql.lisp: Load mysql or postgresql package when connecting to a database of that type so that functions that indicate capabilities of database are available. 02 Sep 2004 Kevin Rosenberg * db-odbc/odbc-api.lisp: More conversions to ODBC v3 02 Sep 2004 Kevin Rosenberg * Version 3.0.2 Release * TODO: Add note about ODBC on Windows * db-odbc/odbc-loader.lisp: Add /winnt/system32/ to search directories * db-odbc/odbc-ff-interface.lisp: Change the return type of SQLSetEnvAttr to :short 02 Sep 2004 Marcus Pearce * examples/clsql-tutorial.lisp: added missing initarg for the COMPANYID slot of the employee View Class definition [reported by Franz Deuzer]. 01 Sep 2004 Kevin Rosenberg * Version 3.0.1 Release * tests/test-init.lisp: Add second join class to employee-address to test a class with two join slots. * sql/oodml.lisp: Fix find-all function for a class with multiple join slots * TODO: Remove need to test/fix multiple join classes 27 Aug 2004 Kevin Rosenberg * db-mysql/Makefile, db-mysql/mysql-loader.lisp: accept patch from Jon Buffington for file locations on Darwin. 17 Aug 2004 Kevin Rosenberg * sql/db-interface.lisp: Improve messages when functions are passed a database object, but the method is not specialized for that database type. * sql/metaclasses.lisp: Fix inline declaration (reported by Cyrus Harmon) 14 Aug 2004 Kevin Rosenberg * TODO: Add bug report about SQL generation with a table containing two join slots. * sql/oodml.lisp: Add optional size to VARCHAR type 3 Aug 2004 Kevin Rosenberg * Version 3.0.0 Release * sql/expressions.lisp: Change declaration that caused error on openmcl * db-aodbc/aodbc-sql.lisp: Fix storage location of odbc connection. Specialize database-query since dbi's :types keyword is different than generic-odbc's :result-types keyword * sql/db-interface.lisp: Add warnings for methods not specialized by a db backends * tests/test-fddl.lisp: Fix case of symbols to support case-sensitive Allegro * db-oracle/oracle-sql.lisp: Rework errbuf in handle-oci-error * tests/test-init.lisp: Note that odbc driver for postgresql doesn't properly handle table ownership * LATEST-TEST-RESULTS: update with version 3.0.0 1 Aug 2004 Marcus Pearce * sql/expressions.lisp: conditionalise escaping of backslash in generated SQL strings on backend. * tests/test-fdml.lisp: test for escaping of backslash. * sql/oodml.lisp: minor tidying in FIND-ALL. 26 Jul 2004 Kevin Rosenberg * NEWS: Initial 3.0 announcement draft * README: Expand acknowledgements of incorporated projects * CONTRIBUTORS: Further document Marcus Pearce contributions 23 Jul 2004 Marcus Pearce * sql/oodml.lisp: add DATABASE-OUTPUT-SQL-AS-TYPE method specialisation to print floats with the exponent markers removed. * tests/test-oodml.lisp: add tests for updating records with floats. 22 Jul 2004 Marcus Pearce * db-oracle/oracle-sql.lisp: enable :OWNER :ALL in DATABASE-LIST-* for CommonSQL compatibility. * tests/test-init.lisp: skip test :FDDL/TABLE/6 on Oracle since this column constraint syntax is not supported. * tests/test-fddl.lisp: change column indexed in test :FDDL/INDEXES/2 from EMPLID to LAST_NAME since Oracle complains that EMPLID is already indexed. 17 Jul 2004 Marcus Pearce * doc/ref-fdml.xml: document CACHE-TABLE-QUERIES. * tests/test-fdml.xml: add test for CACHE-TABLE-QUERIES. * doc/ref-ooddl.xml: minor changes to syntax and examples entries for uniformity. * doc/ref-oodml.xml: add examples for OODML. * sql/oodml.lisp: ensure SELECT passes on its REFRESH argument to FIND-ALL. * sql/metaclasses.lisp: update docstrings. * tests/test-init.lisp: change :db-constraints for emplid to (:not-null :unique) as a temporary test for multiple column constraints in DEF-VIEW-CLASS. * tests/test-oodml.lisp: add tests for *DB-AUTO-SYNC* and return type of (SETF SLOT-VALUE-USING-CLASS). * TODO, doc/TODO: remove items done. * README: fix typo. 16 Jul 2004 Marcus Pearce * sql/oodml.lisp: on Lispworks, use weak valued hash tables for object caching. * sql/expressions.lisp: Fix SQL generation for the symbol NIL. 16 Jul 2004 Marcus Pearce * sql/expressions.lisp: reactivate caching of generated SQL strings. Move methods for DATABASE-OUTPUT-SQL, OUTPUT-SQL and SQL-HASH-KEY here from sql/fdml.lisp. Rationalise behaviour of SQL-OUTPUT, OUTPUT-SQL and DATABASE-OUTPUT-SQL. * sql/fdml.lisp: remove disabled method ADD-STORAGE-CLASS. Move methods for DATABASE-OUTPUT-SQL, OUTPUT-SQL and SQL-HASH-KEY to sql/expressions.lisp. * sql/ooddl.lisp: replace call to DATABASE-OUTPUT-SQL in DATABASE-PKEY-CONSTRAINT with call to SQL-OUTPUT. * sql/generics.lisp: add docstrings. 15 Jul 2004 Kevin Rosenberg * Version 2.11.16 * db-oracle/oracle-sql.lisp: Remove OpenMCL specific code in favor of fixing UFFI with James Bielman's patch 14 Jul 2004 Kevin Rosenberg * Version 2.11.15 * db-oracle/oracle-sql.lisp: Apply patch for OpenMCL/OSX from James Bielman 14 Jul 2004 Marcus Pearce * README, INSTALL: update URLs. Minor updates to descriptions. * tests/README: remove stuff about editing contexts. 12 Jul 2004 Kevin Rosenberg * db-oracle/oracle-objects.lisp: Change *default-varchar-length* to *default-string-length* 12 Jul 2004 Marcus Pearce * tests/test-syntax.lisp, tests/test-fdml.lisp: add tests for escaping of single quotes. * tests/test-fddl.lisp: add tests for column and table constraints in CREATE-TABLE. Add test for OWNER keyword parameter to LIST-TABLES (assuming same underlying machinery in other FDDL functions). * tests/test-init.lisp: restrict above test to postgresql and oracle. 12 Jul 2004 Kevin Rosenberg * db-sqlite/sqlite-sql.lisp: Fix condition as reported by Aurelio Bignoli. 11 Jul 2004 Kevin Rosenberg * sql/oodml.lisp, sql/package.lisp, doc/ref-ooddl.lisp, db-mysql/mysql-objects.lisp: Add tinyint type 10 Jul 2004 Kevin Rosenberg * Version 2.11.14 * doc/*.xml: documentation additionals and fixes so that docbook passes xmllint. 9 Jul 2004 Kevin Rosenberg * Version 2.11.13 * sql/fdml.lisp: Apply patch from Kim Minh Kaplan to change escaping of single quotes. Mild optimizations for escaped string output. * doc/ref-ooddl.lisp: documentation additions * doc/ref-oodml.lisp: Add purpose to functions * TODO: Add need to test single quote escaping 7 Jul 2004 Kevin Rosenberg * doc/ref-ooddl.xml, doc-ref-oodml.xml: documentation additions * sql/ooddl.lisp: Added SMALLINT type * sql/generic-postgresql.lisp: Added INT2 as SMALLINT type * db-mysql/mysql-objects.lisp: Added SMALLINT type * sql/package.lisp: Export SMALLINT * sql/expressions.lisp: Add MYSQL's UNSIGNED and ZEROFILL as db-constraints 6 Jul 2004 Marcus Pearce * sql/expressions.lisp: add AUTO-INCREMENT and UNIQUE to the recognised column constraints for CREATE-TABLE and the :DB-CONSTRAINTS View Class slot option. * sql/ooddl.lisp: fix bug preventing the :DB-CONSTRAINTS View Class slot option accepting a list of constraints [reported by Travis Cross]. * doc/ref-fddl.xml: add some examples of specifying column and table constraints to the documentation for CREATE-TABLE. * TODO: add note about adding tests for table/column constraints. Add optimisation note about using cached attribute types in insert/update operations. 3 Jul 2004 Marcus Pearce * doc/appendix.xml: add notes about idiosyncrasies/unsupported features and so on the documentation for each backend. * doc/TODO: remove items done. * doc/ref-transaction.xml: add note in introduction about autocommit mode as a difference from CommonSQL. * doc/ref-syntax.xml: add notes about SQL syntax state functions being macros in CLSQL. Add note about SQL operators which are CLSQL extensions. 2 Jul 2004 Marcus Pearce * Version 2.11.12 released * doc/ref-recording.xml: document SQL I/O recording. * doc/ref-prepared.xml: new file for documenting prepared statements. * doc/clsql.xml: comment out include for large object and CLSQL-SYS documentation. * doc/ref-conditions.xml: complete documentation of condition system. * doc/global-index.xml: add symbols from condition system and remove those from LOB and prepared statement APIs. * doc/ref-fdml.xml: complete documentation of FDML. * doc/glossary.xml: add View Class. * doc/TODO: remove items done. * sql/conditions.lisp: make SQL-CONDITION a parent of SQL-ERROR. * sql/package.lisp: remove FOR-EACH-ROW from exports list. Export additional slot accessors for condition classes. 1 Jul 2004 Kevin Rosenberg * doc/ref-ooddl.lisp: Add documentation * doc/ooddl.lisp: Move *DEFAULT-VARCHAR-LENGTH* from oodml.lisp and rename to *DEFAULT-STRING-LENGTH*. Add docstring. * doc/oodml.lisp: Rename references to new name of *DEFAULT-STRING-LENGTH* 1 Jul 2004 Marcus Pearce * doc/ref-transaction.xml: document transaction handling. * sql/transaction.lisp: ensure that COMMIT, ROLLBACK and START-TRANSACTION return NIL as per the CommonSQL spec. Modify ADD-TRANSACTION-{ROLLBACK|COMMIT}-HOOK such that a database is passed as a keyword argument defaulting to *DEFAULT-DATABASE*. Added docstrings. 30 Jun 2004 Marcus Pearce * doc/ref-fdml.xml: document the FDML. * doc/ref-fddl.xml: move documentation for TRUNCATE-DATABASE here. * sql/ooddl.lisp: moved *default-varchar-length* to here from oodml.lisp and renamed to *default-string-length* 23 Jun 2004 Kevin Rosenberg * sql/oodml.lisp: Add keyword :transactions to def-view-from-class to allow specifying transactionless table creation * doc/ref-oodml.lisp: Add new keyword to signature of DEF-VIEW-FROM-CLASS 18 Jun 2004 Marcus Pearce * Version 2.11.11 * sql/expressions.lisp: when removing duplicate table identifiers in the FROM clause of a query, check both table name and alias are equivalent. * sql/fdml.lisp: remove DESCRIBE-TABLE. * sql/db-interface.lisp: remove generics DESCRIBE-TABLE and DATABASE-DESCRIBE-TABLE. * sql/package.lisp: remove DESCRIBE-TABLE, DATABASE-DESCRIBE-TABLE and LIST-TABLE-INDEXES. * sql/generic-postgresql.lisp: add reader conditional #+nil for DATABASE-DESCRIBE-TABLE and comment about its uses for re-implementing LIST-ATTRIBUTE-TYPES with a single SQL query returning type info for all attributes. Fix DATABASE-SEQUENCE-LAST. * sql/fddl.lisp: remove LIST-TABLE-INDEXES and redefine LIST-INDEXES with additional keyword parameter :ON. * tests/test-fddl.lisp: replace LIST-TABLE-INDEXES in :fddl/index/3 with LIST-INDEXES (with :ON parameter). * doc/global-index.xml: remove DESCRIBE-TABLE and LIST-TABLE-INDEXES. * doc/ref-connect.xml: minor tidying. * doc/ref-fddl.xml: document the FDDL. * doc/TODO: removed items done. Moved note about transaction handling from TODO to here. * TODO: move note about transaction handling to doc/TODO. Added optimization note about LIST-ATTRIBUTE-TYPES and LIST-INDEXES. 13 Jun 2004 Marcus Pearce * Version 2.11.10 * sql/syntax.lisp: updated docstrings. * sql/package.lisp: exported DATABASE-NAME-FROM-SPEC from CLSQL package. * sql/database.lisp: add docstrings for CREATE-DATABASE, DESTROY-DATABASE, TRUNCATE-DATABASE and LIST-DATABASES. Replace CLSQL-GENERIC-ERROR signalled in RECONNECT with SQL-CONNECTION-ERROR. * doc/ref-syntax.xml, doc/global-index.xml: minor tidying. * doc/ref-connect.xml: document connection/initialisation. * doc/ref-fdml.xml: move TRUNCATE-DATABASE reference entry here. * doc/TODO: remove items done. * Makefile: add db-oracle to to SUBDIRS. 13 Jun 2004 Kevin Rosenberg * sql/oodml.lisp: Add new serialization functions: WRITE-INSTANCE-TO-STREAM and READ-INSTANCE-FROM-STREAM * sql/expressions.lisp: Avoid duplicate FROM names when selecting from a table that has more than one primary index. * sql/conditions.lisp: Fix printing of closed-database error 13 Jun 2004 Kevin Rosenberg * Version 2.11.9 * sql/conditions.lisp: Set initial slot value for message in SQL-WARNING * sql/transactions.lisp: Correctly set slots of SQL-WARNING 12 Jun 2004 Marcus Pearce * sql/package.lisp: export DATABASE-TYPE from CLSQL and subclasses of SQL-EXPRESSION from CLSQL-SYS. * sql/syntax.lisp: make error signalled in SQL-OPERATION an SQL-USER-ERROR. Make SQL-OPERATOR return just one value. * doc/Makefile: added Mandrake linux. * doc/catalog-redhat.xml, doc/catalog-mandrake.xml: new files. * doc/appendix.xml: fixed little typo (adsf). * doc/glossary.xml: removed closed-database and note about sql-expression, added some entries. * doc/ref-syntax.xml: documented the symbolic SQL syntax. 10 Jun 2004 Kevin Rosenberg * Version 2.11.8 * db-mysql/mysql-loader.lisp: Remove load of unnecessary zlib library * multiple: Add generalized-boolean type as requested by Edi Weitz * TODO: Added need for test of generalized-boolean 9 Jun 2004 Kevin Rosenberg * Version 2.11.7 released * uffi/clsql-uffi-loader.lisp: Apply patch from Edi Weitz for loading with clc-register-user-package. Remove personal directory from path lisp. * db-mysql/mysql-loader.lisp: Similar changes 8 Jun 2004 Kevin Rosenberg * Version 2.11.6 released * sql/oodml.lisp: Commit patch from Edi Weitz to fix symbol writing/reading * TODO: Add need for symbol slot test 7 Jun 2004 Marcus Pearce * sql/package.lisp: remove duplicate export of *CACHE-TABLE-QUERIES-DEFAULT*. * doc/ref-*.xml, doc/global-index.xml: new files documenting the CommonSQL compatible api. * tests/test-fdml.lisp: modified the test :fdml/transaction/3 to reflect changes in return values of WITH-TRANSACTION. 04 Jun 2004 Kevin Rosenberg * tests/README: Fix filename [reported by Bill Clementson] * sql/transactions.lisp: Apply return value patch from Edi Weitz for WITH-TRANSACTION * tests/README: Remove ptester package requirement (as noted by Bill Clementson) 03 Jun 2004 Kevin Rosenberg * Version 2.11.5 released * examples/clsql-tutorial.lisp: Remove obsolete :nulls-ok attribute, Select connection-spec based on connection type. Bugs reported by Bill Clementson. * uffi/uffi.dll, uffi/uffi.lib: Recompile with Visual Studio 2003 * db-mysql/mysql-loader.lisp: Update check for zlibwapi library name on Windows, add \bin\ directory to search path 31 May 2004 Marcus Pearce * db-odbc/odbc-sql.lisp: DB-TYPE replaced with DATABASE-TYPE in DATABASE-CONNECT. * sql/operations.lisp: substr now generates SUBSTR for use on Oracle; added a new operator SUBSTRING for use elsewhere. minus now generates MINUS for use on Oracle. Nvl signals an error if not called with exactly 2 arguments. Add concat function for use instead of the || operator on MySQL and Oracle. * sql/syntax.lisp: changed internal symbol for the || operator to CONCAT-OP. * sql/expressions.lisp: removed redundant and unused functions GENERATE-SQL (cf. SQL-OUTPUT) and DATABASE-CONSTRAINT-DESCRIPTION (cf. MAKE-CONSTRAINTS-DESCRIPTION). * sql/generics.lisp: removed generic function for DATABASE-CONSTRAINT-DESCRIPTION (see above). * tests/test-syntax.lisp: modified/added tests according to changes in sql/operations.lisp. * tests/test-fdml.lisp: changed SUBSTR to SUBSTRING in test :fdml/select/21. * sql/package.lisp: added the operators SQL-SUBSTRING, SQL-CONCAT-OP and SQL-USERENV to the shared exports list. Removed ROLLBACK-TRANSACTION, COMMIT-TRANSACTION, DATABASE-START-TRANSACTION, DATABASE-ABORT-TRANSACTION, DATABASE-COMMIT-TRANSACTION, TRANSACTION-LEVEL, TRANSACTION, RECORD-SQL-COMMAND and RECORD-SQL-RESULT from shared exports list. 30 May 2004 Kevin Rosenberg * db-postgresql/postgresl-sql.lisp: Avoid computing result-types lisp when nil result-types. Return only one value when field-types nil. * db-mysql/mysql-sql.lisp: Simple queries now working with prepared statements. 30 May 2004 Kevin Rosenberg * Version 2.11.4: MySQL 4.1 now passes all tests * sql/package.lisp: Add API for prepared statments. * sql/fdml.lisp: Change implicit flatp processing for string map-query for greater CommonSQL conformance. Add high-high API for prepared statements. * tests/test-basic.lisp: Add test for map-query and single argument. * sql/transactions.lisp: Change name/semantics of autocommit to set-autocommit. * sql/generic-postgresql.lisp: Add support for prepared statements. * tests/test-internal.lisp: New file * sql/odbc-api.lisp: Update to using ODBC V3 protocol * clsql-mysql.asd, clsql-uffi.asd: Remove check and Common Lisp Controller invocation. * db-mysql/mysql-api.lisp: Add support for MySQL 4.1 field structure * sql/expressions.lisp: Avoid emitting double parenthesis when a function contains a subselect. 27 May 2004 Kevin Rosenberg * Version 2.11.3 * sql/ooddl.lisp: Commit patch from Edi Weitz fixing return type (setf slot-value-using-class) * TODO: add not that need a test case for the above fix * db-sqlite: Remove clisp support since clisp can not run CLSQL with its MOP usage * db-oracle/oracle-sql.lisp: By default, use OCIEnvCreate as introduced in Oracle8. Leave older code selectable by a reader macro for Oracle7 and prior. Avoid use of OCIServerAttach since CLSQL uses OCILogon and does not the more complex session management. 26 May 2004 Kevin Rosenberg * sql/oodml.lisp: Commit universal-time typo patch from Edi Weitz * test/test-init.lisp: Add universal-time slot to person. * test/test-fddl.lisp: Add tests of universal-time slot * test/test-ooddl.lisp: Test universal-time slot in an object * TODO: Remove need for universal-time test * debian/rules, debian/control: Add cl-sql-oracle binary package * doc/appendix.xml: Add Oracle backend information * db-oracle/oracle-objects.lisp: Add database-get-type-specifier for universal-time. Convert BIGINT CLSQL type to CHAR SQL type * db-mysql/mysql-sql.lisp: Fix condition name to sql-connection-error * doc/ref-clsql.xml: Renamed from ref_clsql.xml. Change the documentation for map-query to reflect changed in arguments to be CommonSQL compatible. Updated old clsql conditions to new CommonSQL compatible conditions. 25 May 2004 Kevin Rosenberg * sql/oodml.lisp: (string n) now produces a CHAR field. Add new VARCHAR type. Added *default-varchar-length* rather than previous hard-coded varchar length. Remove 'simple-string and 'simple-base-string since they are subtypes of 'string. * db-oracle/oracle-sql.lisp: Use *default-varchar-length* rather than local hard-coded value. * sql/metaclasses.lisp: Convert specified type VARCHAR and (VARCHAR n) to Lisp type string. Convert specified-type (CHAR n) to string. Convert specified-type CHAR to lisp type character. * sql/generic-postgresql.lisp: (string n) => (CHAR n) * sql/operations.lisp: Add userenv * doc/TODO: Add AUTOCOMMIT. Remove need for large table and bigint slot tests * sql/oracle-sql.lisp: Add 64-bit bigint direct conversion * uffi/clsql-uffi.lisp: Handle signed 64-bit integers * test/test-init.lisp: Add large table with bigint slot 25 May 2004 Kevin Rosenberg * Version 2.11.1 released: Much simpler Oracle client library loading. Now uses ORACLE_HOME environmental variable as well as tests default path for Oracle Instant Client. 25 May 2004 Kevin Rosenberg * Version 2.11.0 released: Full Oracle support. All tests pass * db-oracle/oracle-sql.lisp: Add declaration so that SBCL runs efficiently. * tests/test-init.lisp: capitalize odbc backend name in banner * CONTRIBUTORS: Add note about Marcus' excellent work * sql/oodml.lisp: Removed old stub function * clsql.asd: Use module names in current package rather than keyword package * db-oracle/oracle-sql.lisp: Don't trim trailing spaces. Prevent interrupts in setting sequence position. Make autocommits more efficient. * tests/test-init.lisp: Skip 2 tests on Oracle which have unsupported syntax * sql/oodml.lisp: Get rid of undocumented raw-string type. CommonSQL strings are raw (non-trimmed trailing whitespace). Add database-get-type-specifier and read-sql-value for NUMBER and CHAR. * sql/base-classes.lisp: Add autocommit slot * sql/transaction.lisp: Added autocommit processing, mild cleaning. * doc/intro.xml: Add Oracle 24 May 2004: Marcus Pearce (m.t.pearce@city.ac.uk) * db-postgresql-socket/postgresql-socket-sql.lisp: replace CLSQL-SIMPLE-WARNING with SQL-WARNING. * db-sqlite/sqlite-sql.lisp: replace CLSQL-SIMPLE-WARNING with SQL-WARNING. * db-aodbc/aodbc-sql.lisp: replace CLSQL-ERROR with SQL-ERROR. * clsql.asd: reworked module structure in package definition and file names to better reflect component functionality. * sql/package.lisp: added SQL-FATAL-ERROR and SQL-TIMEOUT-ERROR to exports list. Removed duplicate and obsolete exports. Exported remaining SQL operations: SQL-SOME, SQL-<>, SQL-BETWEEN, SQL-DISTINCT, SQL-NVL and SQL-FUNCTION. Organised exports by functionality/file and according to whether they are specified by CommonSQL or CLSQL extensions. * sql/transaction.lisp: replace CLSQL-SIMPLE-WARNING with SQL-WARNING. * sql/generics.lisp: moved generics for QUERY and EXECUTE-COMMAND here from basic-sql.lisp. * sql/expressions.lisp: NEW FILE: renamed from classes.lisp (deleted). * sql/fddl.lisp: NEW FILE: renamed from table.lisp (deleted). * sql/fdml.lisp: NEW FILE: merger of basic-sql.lisp and sql.lisp (both deleted). * sql/ooddl.lisp: NEW FILE: ooddl from objects.lisp (deleted). * sql/oodml.lisp: NEW FILE: oodml from objects.lisp (deleted). 23 May 2004 Kevin Rosenberg * Version 2.10.22 released * sql/kmr-mop.lisp, sql/objects.lisp: Since SBCL is the only implementation that has reversed class slots, change the default for ordered-class-slots so that slots are now in the same order an in the def-view-class. * sql/sql.lisp: Honor case of string table identifier to INSERT-RECORDS * test/test-fddl.lisp: Add two tests for mixed case names * db-oracle/oracle-sql.lisp: Add missing database qualifier. Return NUMBER (double) for computed fields, this will require some adjustment to the test suite which in many cases expects integers. * test/test-fdml.lisp: Accomodate that Oracle returns doubles for computed columns 22 May 2004 Kevin Rosenberg * Version 2.10.21 released * sql/sequences.lisp: Move generic sequence functions here from db-sqlite, db-odbc, and db-aodbc. * sql/*.lisp: Add db-type parameter to generic functions READ-SQL-VALUE, DATABASE-GET-TYPE-SPECIFIER, and OUTPUT-SQL-VALUE-AS-TYPE. Update methods to use these. * sql/generic-postgresql.lisp, sql/generic-odbc.lisp: New files * db-odbc/odbc-sql.lisp, db-aodbc/aodbc-sql.lisp: Move common code to sql/generic-odbc.lisp * db-postgresql/postgresql-sql.lisp, db-postgresql-socket/postgresql-socket-sql.lisp: Move common code to sql/generic-postgresql.lisp * sql/classes.lisp: honor case of string tables when outputting queries * sql/objects.lisp: Add database type to default database-get-type-specifier method * sql/sql.lisp: Add database type to default database-abort-transaction method * db-mysql/mysql-objects.lisp: New file * sql/objects.lisp: Move MySQL specific code to mysql-objects.lisp * sql/utils.lisp: Add GETENV function which will be used to get ORACLE_HOME from environment * test/test-fdml.lisp: String table names are now case sensitive, so convert to default db case for FDML/SELECT/25 22 May 2004 Kevin Rosenberg * Version 2.10.20 released: Oracle backend now fails 6 out of 200 tests * TODO: Added 2 variances from CommonSQL. Add tests for owner phrases and string identifiers with non-default case * sql/table.lisp: Don't convert string table name to a symbol. * sql/classes.lisp: Honor case of string identifiers * sql/sql.lisp: Ensure recyclebin is purged for Oracle in TRUNCATE-DATABASE * db-oracle/oracle-sql.lisp: Add sequence functions, fix use of of owner phrases. Obtain server and client versions. * db-oracle/oracle-objects.lisp: Fix type specifiers * tests/test-fddl.lisp: Allow :varchar2 and :number as data types * tests/test-init.lisp: Properly get username from Oracle connection-spec 22 May 2004 Marcus Pearce (m.t.pearce@city.ac.uk) * sql/generics.lisp: reworked docstrings. Remove generics for ADD-TO-RELATION and REMOVE-FROM-RELATION. * sql/objects.lisp: reworked docstrings. Changed UPDATE-OBJECT-JOINS to UPDATE-OBJECTS-JOINS for CommonSQL compatibility. * sql/package.lisp: Changed UPDATE-OBJECT-JOINS to UPDATE-OBJECTS-JOINS for CommonSQL compatibility. Remove ADD-TO-RELATION and REMOVE-FROM-RELATION. * tests/test-oodml.lisp: Changed UPDATE-OBJECT-JOINS to UPDATE-OBJECTS-JOINS for CommonSQL compatibility. * doc/TODO: added notes about extra slot options to DEF-VIEW-CLASS. * sql/conditions.lisp: add documentation for conditions. Add SQL-TIMEOUT-ERROR and SQL-FATAL-ERROR for CommonSQL compatibility. 21 May 2004 Marcus Pearce (m.t.pearce@city.ac.uk) * sql/basic-sql.lisp: reworked docstrings. * sql/transactions.lisp: reworked docstrings. * sql/sql.lisp: reworked docstrings. * sql/initialize.lisp: reworked docstrings. INITIALIZE-DATABASE-TYPE sets *DEFAULT-DATABASE-TYPE* for CommonSQL compatibility. * sql/database.lisp: reworked docstrings. * doc/TODO: added notes about START-TRANSACTION and IN-TRANSACTION-P and FDML extensions and database extensions. 20 May 2004 Kevin Rosenberg (kevin@rosenberg.net) * db-oracle/oracle-sql: Use clsql-specific error conditions. Use owner keyword. * db-oracle/make9.sh: add makefile for building with Oracle 9 client libraries * sql/table.lisp: Add logic for dealing with Oracle 10g vs. previous Oracle versions with the PURGE option required for drop table. This needs to be converted to a generic function and moved to db-oracle/oracle-sql.lisp 20 May 2004 Marcus Pearce (m.t.pearce@city.ac.uk) * sql/classes.lisp: remove unused PARAMS slot in SQL-IDENT-ATTRIBUTE. * sql/syntax.lisp: remove unused PARAMS keyword arg to SQL-EXPRESSION. * sql/table.lisp: reworked docstrings. * sql/objects.lisp: moved *default-update-objects-max-len* here from table.lisp. * doc/TODO: notes about :if-does-not-exist arg to DROP-TABLE, DROP-VIEW and DROP-INDEX and the use of the :transactions and :constraints keyword args to CREATE-TABLE. * sql/classes.lisp: the DESCRIPTION argument to CREATE-TABLE is now CommonSQL compatible with respect to column constraints. 20 May 2004 Kevin Rosenberg (kevin@rosenberg.net) * sql/oracle-sql.lisp: Now compiles and runs on SBCL. Requires UFFI 1.5.0 or higher 20 May 2004 Kevin Rosenberg (kevin@rosenberg.net) * Version 2.10.19 * sql/conditions.lisp: Fix cerror 19 May 2004 Kevin Rosenberg (kevin@rosenberg.net) * Version 2.10.18 released: New condition hierarchy to be compatible with CommonSQL -- not backward compatible with previous CLSQL. * sql/db-interface.lisp: Add more default methods * sql/objects.lisp: Add explicit table name to order-by parameters in find-all when only one table to avoid selecting a duplicate row. Fix error in FIND-ALL when using :order-by such as (([foo] :asc)) as previous logic was adding two fields (foo asc) to SELECT query. Make :result-types :auto be the default for object selections. Properly handle caching key when using multiple order-by with asc/desc directions. * db-oracle/*.lisp: Much improvements, now passes 90% of test suite 19 May 2004 Marcus Pearce (m.t.pearce@city.ac.uk) * sql/recording.lisp: reworked docstrings. * sql/syntax.lisp: reworked docstrings. * doc/TODO: added notes about extensions to SQL-RECORDING-P and the SQL syntax state functions being macros. 19 May 2004 Kevin Rosenberg (kevin@rosenberg.net) * sql/package.lisp: Export initialize-database-type and *initialize-database-types* from CLSQL package. * sql/conditions.lisp: Add new CommonSQL compatible conditions, remove old CLSQL conditions. * sql/loop-extensions.lisp: Make errors of type sql-user-error * */*.lisp: Convert to from old to new conditions 18 May 2004 Kevin Rosenberg (kevin@rosenberg.net) * sql/table.lisp: Add PURGE to drop command for oracle 10g backend. To handle this difference, will need to add a new database-drop-table generic function. * db-oracle/oracle-sql.lisp: Move server-version and major-version-number to database object to allow multiple connections to Oracle servers of different versions. 18 May 2004 Marcus Pearce (m.t.pearce@city.ac.uk) * TODO: moved notes about backends to doc/TODO. * doc/TODO: added notes about backends and select extensions. * sql/base-classes.lisp: remove obsolete schema slot in database class. 16 May 2004 Kevin Rosenberg (kevin@rosenberg.net) * db-oracle/oracle-api: Add OCIServerVersion * db-oracle/oracle-sql: Query and store server version on connect * sql/db-interface.lisp: Add new db-type-has-bigint? generic function to handle OCI's lack of bigint support * test/test-basic.lisp: Separate bigint testing * test/test-utils.lisp: Add oracle to specs and list of backends * doc/TODO: New file * test/test-fdml.lisp: Added FDML/SELECT/34 to test run-time instantiation of variables in reader macros. * TODO: Remove item already complete. Add note about condition variances 16 May 2004 Marcus Pearce (m.t.pearce@city.ac.uk) * sql/syntax.lisp: added condition to the reader macro to treat [*] as a column identifier (rather than an operation) for CommonSQL compatibility. * tests/test-fdml.lisp: add tests for ORDER-BY and SET-OPERATION keword args to SELECT, [*] as column identifier, new MAP-QUERY behaviour and the ANY and ALL operators in subqueries. * tests/test-init.lisp: add set-operation and subquery tests to appropriate skip lists. * sql/objects.lisp: remove redundant and non CommonSQL compatible ORDER-BY-DESCENDING keyword argument for SELECT. * sql/classes.lisp: remove redundant and non CommonSQL compatible ORDER-BY-DESCENDING keyword argument for SELECT. * tests/test-oodml.lisp: add test for ORDER-BY keyword to SELECT with object queries. 15 May 2004 Kevin Rosenberg (kevin@rosenberg.net) * sql/db-interface.lisp: Add new db-type-has-union? since Mysql 3.23 does not support unions. * sql/test-init.lisp: Don't try union tests on database backends which do not support it. * db-oracle/*.lisp: initial port to UFFI * sql/objects.lisp: implement UPDATE-OBJECT-JOINS, implement REFRESH for SELECT. * tests/test-oodml.lisp: Add tests for deferred retrieval, caching, refresh, and update-object-joins * tests/test-init.lisp: Add deferred-employee-address class 15 May 2004 Marcus Pearce (m.t.pearce@city.ac.uk) * sql/operations.lisp: make MINUS operator a synonym for EXCEPT. Add COALESCE operator and make NVL a synonym for this. Make ANY, SOME, ALL and EXISTS generate function expressions so they output the correct SQL. * sql/classes.lisp: SELECT now generates appropriate SQL when passed the SET-OPERATION and ALL keyword arguments. * sql/classes.lisp: the ORDER-BY keyword argument to SELECT now accepts ordering constraints as pairs of the form (column direction) where direction may be :ASC or :DESC. * tests/test-syntax.lisp: added tests for MINUS and COALESCE/NVL. Correct tests for ANY, SOME, ALL and EXISTS. * tests/test-fdml.lisp: added test for COALESCE. * sql/sql.lisp: MAP-QUERY now applies FUNCTION to QUERY-EXPRESSION using funcall unless QUERY-EXPRESSION returns one column and its FLATP slot is not nil in which case apply is used. * tests/test-basic.lisp: modified calls to MAP-QUERY to reflect the changes. * TODO: remove items done. * db-postgresql/postgresql-sql.lisp: no need to reverse results in DATABASE-LIST-ATTRIBUTES. * db-postgresql-socket/postgresql-socket-sql.lisp: no need to reverse results in DATABASE-LIST-ATTRIBUTES. 15 May 2004 Marcus Pearce (m.t.pearce@city.ac.uk) * sql/classes.lisp: SELECT now accepts table identifiers as strings for CommonSQL compliance. Add support for qualified sql identifiers with aliased table names. * tests/test-fdml.lisp: added tests for table identifiers as strings in SELECT and for aliased definitions. * tests/test-syntax.lisp: added tests for alias definitions. 15 May 2004 Marcus Pearce (m.t.pearce@city.ac.uk) * sql/sql.lisp: PRINT-QUERY now calls QUERY with result-types and field-names set to nil. * sql/sql.lisp: PRINT-QUERY now computes column sizes correctly with null attribute values. * sql/operations.lisp: modify SQL concatenation operator to accept unescaped || symbol. * sql/syntax.lisp: modify sql reader macro function to accept unescaped sql concatenation operator. * tests/test-fdml.lisp: unescape sql concatenation operator. * tests/test-syntax.lisp: unescape sql concatenation operator. * TODO: remove items done. Add notes about SQLITE/MYSQL backends. Note to add test for universal-time. Note about difference from CommonSQL in transaction handling. 13 May 2004 Kevin Rosenberg (kevin@rosenberg.net) * tests/test-init.lisp: Add deferred-employee-address class * tests/test-oodml.lisp: Add deferred retrieval testgs 12 May 2004 Kevin Rosenberg (kevin@rosenberg.net) * Version 2.10.17 * LATEST-TEST-RESULTS: Run on all platforms, add AMD64 * sql/sql.lisp: Add FOR-EACH-ROW macro from clsql-classic/sql.lisp * db-sqlite/sqlite-uffi-api.lisp: Fix row-pointer type * *: Fix minor style warnings * clsql-classic: Remove system and subdirectory * clsql-base: Remove system and subdirectory and fold into clsql system * doc/intro.xml: Remove reference to old clsql-base. Add x86_64 as supported platform. 12 May 2004 Kevin Rosenberg (kevin@rosenberg.net) * Version 2.10.16: CLSQL now fully supports AllegroCL AMD64 * db-odbc/odbc-api.lisp: work around return-type bug [spr28889] in Allegro 7.0beta AMD64 * db-odbc/*.lisp: Add a layer of indirection to foreign-type of ODBC longs since this type can vary on 64-bit platforms depending upon the compilation options of unixODBC. * db-mysql/mysql-api.lisp: Fix int vs. long slots in foreign structures found by testing with AllegroCL 7.0b AMD64. * db-*/*-loader.lisp: Load 64-bit libraries on 64-bit platorms * sql/objects.lisp: Simple implementation of UPDATE-OBJECT-JOINS. Initial caching support for SELECT * tests/test-oodml.lisp: Avoid using cache when testing select. * sql/kmr-mop.lisp: Explicitly check slot order and store as a cl:*feature* * sql/recording.lisp: Remove additional types to increase CommonSQL conformance. * tests/test-init.lisp: Change a :column attribute to test symbols as value * sql/relations.lisp: Remove functions since they don't support many to many relationships. * examples/clsql-tutorial.lisp, doc/csql.lisp: Remove use of add-to-relations function and replace with explicit field settings. * base/classes.lisp: Remove obsolute query-stream. Add record-caches slot. 9 May 2004 Kevin Rosenberg (kevin@rosenberg.net) * Version 2.10.15 * LATEST-TEST-RESULTS: results with current version * sql/kmr-mop.lisp: Make CMUCL reader macros specific for cmu18 since cmu19 has opposite order of class slots. * sql/objects.lisp: Fix (setf slot-value-using-class) for Lispworks * tests/test-fdml.lisp: Renumber SELECT tests to avoid overwriting a previous test * tests/test-init.lisp: Check test-database-underlying-type for ODBC/MySQL tests 8 May 2004 Marcus Pearce (m.t.pearce@city.ac.uk) * sql/operations.lisp: complete remaining operations for the sql syntax: SUBSTR, SOME, ORDER-BY, GROUP-BY, NULL, DISTINCT, EXCEPT, UNION, INTERSECT, BETWEEN. * sql/classes.lisp: add new classes: SQL-BETWEEN-EXPRESSION, SQL-QUERY-MODIFIER-EXPRESSION and SQL-SET-EXPRESSION. * tests/test-syntax.lisp: add tests for new operations. * tests/test-fdml.lisp: add tests for queries based on new operations. * tests/test-init.lisp: add select/20 to tests skipped for sqlite and select/20, query/5, query/7 and query/8 to tests skipped by mysql. * TODO: removed entries done. 8 May 2004 Kevin Rosenberg (kevin@rosenberg.net) * tests/benchmarks.lisp: Add immediate vs. deferred join test. 8 May 2004 Kevin Rosenberg (kevin@rosenberg.net) * Version 2.10.13: Now works on openmcl 0.14.2 * sql/objects.lisp: Add :retrieval :immediate for object selections * tests/test-init.lisp: Add non-index fields for testing join class employee-addresss * test/test-oodml.lisp: Add tests for retrieval immediate * sql/metaclasses.lisp: Handle differences in direct-slot-definition values which are now listifed by openmcl 14.2. * sql/objects.lisp: more framework for supporing immediate retrieval 7 May 2004 Kevin Rosenberg (kevin@rosenberg.net) * docs/intro.xml: Upload location of a README file * sql/metaclass.lisp: Work-around openmcl's CHANGE-CLASS changing the type-specifier. Use a lisp type of (OR NULL FOO) for a specified-type of FOO unless :db-constraints :not-null. No need to specialize finalize-inheritance for openmcl. * tests/test-*.lisp: Rename fields so that joins occur on fields with different names. This ensures that join code is selecting the proper name. * test/test-init.lisp: Add :base-table for employee-address view class for testing. * sql/objects.lisp: Use view-table rather than name of table in a number of places to fix errors noted with using :base-table. 6 May 2004 Marcus Pearce (m.t.pearce@city.ac.uk) * sql/objects.lisp: replace *update-records-on-make-instance* with *db-auto-sync* which also controls both automatic creation of new records on creation of new instance and updating of record fields on setting of instance slots (as suggested by Edi Weitz). * tests/test-init.lisp: replace *update-records-on-make-instance* with *db-auto-sync*. * sql/package.lisp: replace *update-records-on-make-instance* with *db-auto-sync*. * TODO: replace *update-records-on-make-instance* with *db-auto-sync*. * sql/objects.lisp: remove redundant rebindings of *db-initializing* and *default-database* in FIND-ALL. * sql/package.lisp: import time functions from CLSQL-BASE. * tests/test-time.lisp: replace CLSQl-BASE package qualifier with CLSQL. * tests/test-fdml.lisp: replace CLSQl-BASE package qualifier with CLSQL. * tests/test-init.lisp: replace CLSQl-BASE package qualifier with CLSQL. * tests/test-ooddl.lisp: replace CLSQl-BASE package qualifier with CLSQL. 4 May 2004 Kevin Rosenberg (kevin@rosenberg.net) * sql/classes.lisp: Add SQL-OBJECT-QUERY type. Have [select 'class] now return a sql-object-query type rather than directly performing a query. This improves CommonSQL conformance. * sql/sql.lisp: Add new QUERY method for SQL-OBJECT-QUERY. Move from basic/basic-sql.lisp the DO-QUERY and MAP-QUERY since they now depend on sql-object-query-type. * sql/loop-extensions.lisp: Move from base package * classic/package.lisp: remove references to map-query and do-query 4 May 2004 Kevin Rosenberg (kevin@rosenberg.net) * TODO: New section on optimizations, especially optimizing JOINs. * sql/objects.lisp: Have :target-slot return of list of lists rather than a list of cons pairs to be conformant with CommonSQL. Make :target-slot much more efficient by using a SQL inner join statement and just requiring one SQL query. Add :retrieval :deferrred to target-slot joins. Add placeholder for update-objects-join. * sql/classes.lisp: Add :inner-join and :on slots to sql-query class and process them for query output-sql. 4 May 2004 Kevin Rosenberg (kevin@rosenberg.net) * Version 2.10.11 * base/basic-sql.lisp: Avoid multiple evaluation of query-expression in DO-QUERY * sql/objects.lisp: Make SELECT a normal function. SELECT now accepts type-modified database identifiers, such as [foo :string] which means that the values in column foo are returned as Lisp strings. Add new *update-records-on-make-instance* special variable controlling automatic creation of new instances. Add missing RESULT-TYPES keyword to FIND-ALL. Add :target-slot support. * sql/packages.lisp: Export *update-records-on-make-instance* * test/test-oodml.lisp: Add tests for :target-slot and many-to-many selections. * test/test-fdml.lisp: Add tests for type-modified database identifiers. * test/test-init.lisp: Stop using add-relation since implementing many-to-many joins. Use *update-records-on-make-instance* to automatically store records on instance creation. Add many-to-many employee-address view-class. 4 May 2004 Kevin Rosenberg (kevin@rosenberg.net) * Version 2.10.10 * base/loop.lisp: Add object iteration. Use :result-type :auto for result-set. Remove duplicate (and non-correct) code for non-list variables by simply making an atom variable into a list. * sql/package.lisp: Remove unnecessary clsql-sys package and replace it with clsql. * sql/metaclasses.lisp: Properly store specified-type from direct-slot-definition and then store translated type in effective-slot-definition * sql/classes.lisp: Don't output type in sql-output for SQL-IDENT-ATTRIBUTE. This is in preparation for supporting [foo :integer] as fields in SELECT. * sql/query.lisp: Set default for :result-types to :auto in FDML QUERY. * sql/objects.lisp: Use specified-type when invocating database-get-type-specifier. def-view-class macro now returns the class instance. * base/basic-sql.lisp: Make :AUTO the default value for :RESULT-TYPES for MAP-QUERY and DO-QUERY. * sql/objects.lisp: Add bigint type * test/tests-basic.lisp: Add tests for :result-types for MAP-QUERY and DO-QUERY * test/test-fdml.lisp: Add test for result-types in LOOP and also using single symbol rather than a list for variables. Add test that default :result-types is auto for FDML QUERY. * test/test-syntax.lisp: Don't expect TYPE in the SQL-OUTPUT of SQL-IDENT-ATTRIBUTE. * test/test-oodml.lisp: Enable OO loop iteration test, modify it so it doesn't depend on boolean where. 4 May 2004 Marcus Pearce (m.t.pearce@city.ac.uk) * Version 2.10.9 * sql/objects.lisp: added derived type specifier for universal time. * sql/package.lisp: added #:universal-time to clsql-sys exports. * tests/test-oodml.lisp: added test for translation of boolean slots in SELECT with object queries. 3 May 2004 Kevin Rosenberg (kevin@rosenberg.net) * db-odbc/odbc-api.lisp: Fix changing nil to "NIL" for odbc/postgresql backend. * db-odbc/odbc-sql.lisp: Fix ATTRIBUTE-TYPE so that it can handle NIL values from the ODBC driver * tests/benchmarks.lisp: New file with initial benchmark suite * sql/relations.lisp: fix to add subclassing support, minor optimizations [Edi Weitz] 3 May 2004 Kevin Rosenberg (kevin@rosenberg.net) * Version 2.10.8 * base/conditions.lisp: Add *backend-warning-behavior* special variable. * db-postgresql-socket/postgresql-socket-sql.lisp: Honor value of *backend-warning-behavior* * tests/test-fdml.lisp: Remove test of raw boolean value since different backends handle this differently. Add test for :column attribute. * tests/test-oodml.lisp: Add tests for boolean slot value and for :void-value attribute * tests/test-init.lisp: Use *backend-warning-behavior* to suppress warnings from postgresql about implicitly creating primary key in tables. Add new address table. 3 May 2004 Kevin Rosenberg (kevin@rosenberg.net) * Version 2.10.7 * db-odbc/odbc-dbi.lisp: Convert TINYINT to integers when result-types is :auto * sql/objects.lisp: Properly handled writing/reading Boolean values from SQL database when retrieving objects. * test/test-fdml.lisp: Add another test for boolean results * test/utils.lisp: Fix incorrect declaration 2 May 2004 Marcus Pearce (m.t.pearce@city.ac.uk) * Version 2.10.6 * sql/generics.lisp: add generic function for SELECT. * sql/objects.lisp: make SELECT a method specialisation. * sql/classes.lisp: MAKE-QUERY now calls SELECT if the selections referred to are View Classes. * base/basic-sql.lisp: in DO-QUERY and MAP-QUERY, if the query-expression arg evaluates to a list, then we have an object query. * tests/test-oodml.lisp: add tests for DO-QUERY and MAP-QUERY with object queries. * TODO: remove items done and add a todo for SELECT. * sql/objects.lisp: SELECT takes a :field-names arg to pass on to QUERY. * sql/sql.lisp: add :field-names arg to QUERY. * tests/test-fdml.lisp: minor rework to use :field-names arg to SELECT. 2 May 2004 Marcus Pearce (m.t.pearce@city.ac.uk) * sql/objects.lisp: fix bug in FIND-ALL when SELECT called with 2 or more View Classes. * sql/objects.lisp: make the :flatp argument to SELECT work with object queries. * sql/objects.lisp: make SELECT accept a :result-types argument (defaults to :auto) which is passed on to QUERY. * sql/objects.lisp: SELECT returns field-names as a second value. * tests/test-ooddl.lisp: add flatp arg to SELECT calls as appropriate. * tests/test-fdml.lisp: add flatp/result-types arguments to calls to SELECT and take only first value as appropriate. * tests/test-fdml.lisp: add two new tests for query result coercion and the field-names returned as a second value from SELECT. * tests/test-oodml.lisp: add flatp arg to SELECT calls as appropriate. 1 May 2004 Kevin Rosenberg (kevin@rosenberg.net) * Version 2.10.6-pre1 * sql/metaclasses.lisp: Add void-value slot * doc/csql.xml: Update def-view-class documentation * test/test-init.lisp: Change old :db-type to :db-kind. Remove old :nulls-ok attributes. * sql/objects.lisp: Add new universal-time and bigint types. Optimize reading of integers using parse-integer rather than read-from-string. * */*.lisp: Merge clsql-base-sys and clsql-base packages into clsql-base package * classic/sql.lisp: Move large object support into base, leaving classic without any functionality that is provided in the clsql system. * classic/package.lisp: Rename clsql-classic-sys package to its former nickname of clsql-classic 1 May 2004 Kevin Rosenberg (kevin@rosenberg.net) * Version 2.10.5: SQLite backend now passes all result-types tests * clsql-sqlite.asd: Depend on clsql-uffi system * db-sqlite/sqlite-sql.lisp: Use clsql-uffi:convert-raw-field for efficiency and code reuse. * db-sqlite/sqlite-api-uffi.lisp: Change (* :char) to (* :unsigned-char) for better cross-implementation compatibility. 1 May 2004 Kevin Rosenberg (kevin@rosenberg.net) * Version 2.10.4 * sql/tables.lisp: Fix typo in CACHE-TABLE-QUERIES [Marcus Pearce] * db-postgresql/postgresql-sql.lisp: Fix foreign-string vs. cstring bug on SBCL in result-field-names function as reported by Marcus Pearce * db-sqlite/sqlite-sql.lisp: Fix in database-store-next-row manifest in SBCL testing 1 May 2004 Kevin Rosenberg (kevin@rosenberg.net) * Version 2.10.3 * sql/database.lisp: Conform more to CommonSQL output for STATUS command [Marcus Pearce] * sql/sqlite-sql.lisp: Rework to use result-types * sql/sqlite-api-clisp.lisp: Add compatibility layer with sqlite-api-uffi.lisp so that sqlite-sql.lisp can be cleaned up of most clisp reader conditionals * sql/test-init.lisp: Now run field type tests on sqlite backend 30 Apr 2004 Kevin Rosenberg (kevin@rosenberg.net) * Version 2.10.2 * base/basic-sql.lisp: Set default value of :result-types to :auto for more CommonSQL conformance. * test/test-fdml.lisp: Add tests for numeric value of fields 30 Apr 2004 Kevin Rosenberg (kevin@rosenberg.net) * Version 2.10.1: New API function: CACHE-TABLE-QUERIES. * base/basic-sql.lisp, db-*/*-sql.lisp: More CommonSQL conformance. Return field names as second value for QUERY. This can be overridden for efficiency with the new keyword :FIELD-NAMES set to NIL in the QUERY invocation. * test/test-fdml.lisp: Add tests for new field-name feature * sql/metaclass.lisp: Remove old Lispworks cruft and replace it with invocation of new code in kmr-mop.lisp which actually works with Lispworks 4.2 * doc/ref_clsql.xml: Document new :FIELD-NAMES keyword to QUERY function * base/db-interface.lisp: Document the multiple values returned by DATABASE-ATTRIBUTE-TYPE so matches the undocumented CommonSQL behavior. * sql/table.lisp: Add *CACHE-TABLE-QUERIES-DEFAULT* and *DEFAULT-UPDATE-OBJECTS-MAX-LEN* variables and export them. LIST-ATTRIBUTE-TYPES now conforms to CommonSQL spec. Implement CACHE-TABLE-QUERIES. * db-odbc/odbc-sql.lisp: Fix attribute-type function * test/test-fddl.lisp: Add tests for attribute type * db-mysql/mysql-sql.lisp: Mild optimization in accessing field structures. * base/classes.lisp: Add attribute-cache slot to database clas * base/initialize.lisp: initialize-database-type now automatically loads database-type backend as needed. * base/test-init.lisp: Utilize new initialize-database-type functionality. * TODO: remove items done 30 Apr 2004 Marcus Pearce (m.t.pearce@city.ac.uk) * Version 2.9.6 * sql/objects.lisp: remove create/drop-sequence-from-class. * sql/objects.lisp: add INSTANCE-REFRESHED generic function. * sql/objects.lisp: improved CommonSQL compatibility for UPDATE-RECORD-FROM-SLOT, UPDATE-RECORD-FROM-SLOTS, UPDATE-RECORDS-FROM-INSTANCE and DELETE-INSTANCE-RECORDS. * sql/generics.lisp: move generics from objects.lisp to here. 29 Apr 2004 Kevin Rosenberg (kevin@rosenberg.net) * Version 2.9.6-pre1 * db-mysql/mysql-client-info.lisp: Add client version 4.1 detection * sql/sql.lisp: Make *default-database* the default for TRUNCATE-DATABASE 28 Apr 2004 Kevin Rosenberg (kevin@rosenberg.net) * Version 2.9.5 * db-mysql/mysql-sql.lisp: Fix bug in transaction capability detection * sql/objects.lisp: Commit patch from Slawek Zak to allow specifying :metaclass in DEF-VIEW-CLASS invocation. This allows defining classes on a metaclass specialized from standard-db-class. 24 Apr 2004 Kevin Rosenberg (kevin@rosenberg.net) * Version 2.9.4: Multiple changes to support Allegro's "modern" lisp which uses a lowercase reader and has case-sensitive symbols * sql/classes.lisp: Fix make-load-form bug for sql-ident-table exposed by case-sensitive mlisp. 22 Apr 2004 Kevin Rosenberg (kevin@rosenberg.net) * Version 2.9.3: All tests now pass on all platforms! * LATEST-TEST-RESULTS: New file with summary of test results * sql/generics.lisp: New file for generic function definitions. * test/test-init.lisp: Display names of skipped tests. Use unwind-protect to ensure disconnect * sql/objects.lisp: Change database-type to database-underlying-type so that actual database engine is properly identified * db-odbc/odbc-api.lisp: Have default *time-conversion-function* return an ISO timestring for compatibility with other drivers. Workaround bug in MyODBC for LIST-TABLE-INDEXES * test/test-fdml.lisp: Accomodate that odbc-postgresql driver returns floating-point values for floor and truncate operations * db-aodbc/aodbc-sql.lisp: Implement DATABASE-LIST-VIEWS * tests/test-basic.lisp: Port to regression tester * test/test-init.lisp: Output to *report-stream* * docs/appendix.xml: Document ODBC and SQLite backends. * sql/classes.lisp: Make output-sql require a database parameter. This allows SQL generation to have the proper case to support the differences in case handling between CommonSQL API, Postgresql, MySQL, Oracle. 21 Apr 2004 Kevin Rosenberg (kevin@rosenberg.net) * Version 2.9.2: Improvments in database capability introspection and querying. Support transactions in MySQL where available. All tests now pass on MySQL and SQLite in addition to postgresql and postgresql-socket. ODBC fails only with OODDL/TIME/1 and OODDL/TIME/2. * db-odbc/odbc-sql.lisp: Add DATABASE-LIST-VIEWS. Better support DATABASE-LIST-SEQUENCES. * clsql-uffi.asd, clsql-mysql.asd: Improve shared library loading * Database_capabilies: add HAS-VIEWS, HAS-CREATE/DESTROY-DB, HAS-BOOLEAN-WHERE, TRANSACTION-CAPABLE * tests/*.lisp: Check database capabilities and remove tests which the database backend does not support * sql/table.lisp: Add :TRANSACTIONS keyword to create table which controls whether InnoDB tables will be created when supported on the underlying MySQL server. 20 Apr 2004 Kevin Rosenberg (kevin@rosenberg.net) * Version 2.9.0: New API function: LIST-TABLE-INDEXES, supported by all database backends (except AODBC since AODBC doesn't support index querying) * db-obdc/odbc-sql.lisp: Support DATABASE-LIST-INDEXES * db-odbc/odbc-api.lisp: Add %TABLE-STATISTICS function to support index queries * db-aodbc/aodbc-sql.lisp: Filter driver manager "information_schema" tables from LIST-TABLES * tests/test-basic.lisp: Remove table after testing * tests/test-fddl.lisp: Test LIST-TABLE-INDEXES * base/db-interface.lisp: Add DATABASE-UNDERLYING-TYPE which gets the underlying type of database -- required when dealing with ODBC databases and want to query database capabilities. Added DB-USE-COLUMN-ON-DROP-TABLES? as first database-backend specific feature. Is T on :mysql, NIL on other backends. Change DROP-TABLE to query this. 19 Apr 2004 Kevin Rosenberg (kevin@rosenberg.net) * Version 2.8.2: Build changes for FreeBSD [Slawek Zak] 19 Apr 2004 Kevin Rosenberg (kevin@rosenberg.net) * Version 2.8.1 * db-odbc/odbc-sql.lisp: Add DATABASE-LIST function * db-odbc/odbc-dbi.lisp: Add LIST-ALL-DATA-SOURCES function 19 Apr 2004 Kevin Rosenberg (kevin@rosenberg.net) * Version 2.8.0: New API function: LIST-DATABASES * base/utils.lisp: Fix command-output on CMUCL/SBCL * db-*/*-sql.lisp: Add new database-list function * base/database.lisp: Add new LIST-DATABASES command 18 Apr 2004 Kevin Rosenberg (kevin@rosenberg.net) * Version 2.7.9 * db-sqlite/sqlite-sql.lisp: Fix sequence functions. * db-sqlite/sqlite-api-uffi.lisp: Print error string correctly. 18 Apr 2004 Kevin Rosenberg (kevin@rosenberg.net) * Version 2.7.7 * doc/csql.xml, examples/clsql-tutorial.lisp: Patch for db-kind from Eduardo Munoz. 17 Apr 2004 Kevin Rosenberg (kevin@rosenberg.net) * Version 2.7.6 * base/objects.lisp, base/classes.lisp: Patch for db-kind from Eduardo Munoz 16 Apr 2004 Kevin Rosenberg (kevin@rosenberg.net) * Version 2.7.5 * base/basic-sql.lisp: Fix FLATP in QUERY 16 Apr 2004 Kevin Rosenberg (kevin@rosenberg.net) * Version 2.7.3: Implement RECONNECT 15 Apr 2004 Kevin Rosenberg (kevin@rosenberg.net) * Version 2.7.2: Fix ODBC on Lispworks Windows 15 Apr 2004 Kevin Rosenberg (kevin@rosenberg.net) * Version 2.7.1: Fix for new ODBC backend. clsql-odbc now works on SBCL, CMUCL, OpenMCL in addition to AllegroCL and Lispworks. 15 Apr 2004 Kevin Rosenberg (kevin@rosenberg.net) * Version 2.7.0: New backend: ODBC. Tests as well as AODBC backend on Allegro,Lispworks. SBCL and CMUCL don't work quite yet. Requires UFFI v1.4.11+ * db-odbc/*.lisp: Add ODBC3 function SQLSetEnvAttr to explicitly set ODBC2 support. Add BIGINT support. Add result-types support. Added SQLTables. Fix array type in fetch-all-rows. Make width changable by database or query. * base/utils.lisp: Add process functions * base/package.lisp: Export utils to CLSQL-BASE-SYS * db-aodbc: Implement sequence functions, database-list-tables, database-list-attributes * tests/utils.lisp: Add support for ODBC backend, rework READ-SPECS to use +all-db-types+ * db-mysql/mysql-sql.lisp: Use WITHOUT-INTERRUPTS for SEQUENCE-NEXT 13 Apr 2004 Kevin Rosenberg (kevin@rosenberg.net) * Version 2.6.13. Requires UFFI version 1.4.9 * db-odbc/*.lisp: Further porting. Pre-alpha code! But, basic query is now working. 13 Apr 2004 Kevin Rosenberg (kevin@rosenberg.net) * Version 2.6.12 * base/transactions.lisp: Add quote for macro expansion of WITH-TRANSACTIONS [Time Howe] * db-sqlite/sqlite-sql.lisp: Support memory database in database-probe [Ng Pheng Siong] * db-odbc/*.lisp: Initial port to UFFI of SQL-ODBC. The DBI layer is not finished. 12 Apr 2004 Kevin Rosenberg (kevin@rosenberg.net) * Version 2.6.11 * sql/objects.lisp: add :root-class functionality for list-classes and add duration type support [Marcus Pearce] * db-odbc: Add mid-level [DBI] layer 12 Apr 2004 Kevin Rosenberg (kevin@rosenberg.net) * Version 2.6.10 * db-aodbc: Add methods for generic functions, some are not yet implemented. * clsql-odbc.asd, db-odbc/*.lisp: Initial start of ODBC support 12 Apr 2004 Kevin Rosenberg (kevin@rosenberg.net) * Version 2.6.9 * base/package.lisp: Add missing symbols [Marcus Pearce] 12 Apr 2004 Kevin Rosenberg (kevin@rosenberg.net) * Version 2.6.8 * test/test-fddl.lisp: Cleanup fix [Marcus Pearce] * utils/time.lisp: Multiple fixes [Marcus Pearce] * sql/sql.lisp: Fix for truncate-database [Marcus Pearce] 12 Apr 2004 Kevin Rosenberg (kevin@rosenberg.net) * Version 2.6.7 * sql/*.lisp: Remove schema versioning cruft [Marcus Pearce] * Makefile: Add classic subdirectory 12 Apr 2004 Kevin Rosenberg (kevin@rosenberg.net) * Version 2.6.6 * sql/sql.lisp: Fix TRUNCATE command, bug reported by Marcus Pearce * sql/sql.lisp: Remove EXPLAIN function. Postgresql/Oracle specific and easy for an application to directly support. Idea from Marcus Pearce. * base/basic-sql.lisp: Remove DESCRIBE-TABLE top-level API as duplicates LIST-ATTRIBUTE-TYPES [Marcus Pearce]. Keep low-level interface for future optimization supporting LIST-ATTRIBUTE-TYPES command. * Makefile: Add to db-sqlite and test directories. Include them in top-level Makefile 12 Apr 2004 Kevin Rosenberg (kevin@rosenberg.net) * Version 2.6.5 * sql/relations.lisp: Add missing file * utils/time.lisp: Fixes/extensions [Marcus Pearce] * test/test-time.lips: New file [Marcus Pearce] 10 Apr 2004 Kevin Rosenberg (kevin@rosenberg.net) * Version 2.6.4 * test/test-init.lisp: Properly handle object creation. Close database after use. * sql/sql.lisp: Make DESCRIBE-TABLE a generic function so can have methods specialized on table being a string or an sql-table object. * base/pool.lisp: Really fix CMUCL locking 10 Apr 2004 Kevin Rosenberg (kevin@rosenberg.net) * Version 2.6.3 * test/test-init.lisp: Signal correctly if any errors occurred in any test suite * base/loop-extensions.lisp: Fix error introduced for Lispworks * base/pool.lisp: Fix locking for CMUCL * base/objects.lisp: Remove schema-version cruft 10 Apr 2004 Kevin Rosenberg (kevin@rosenberg.net) * Version 2.6.2: New CLSQL API functions: DESCRIBE-TABLE AND TRUNCATE-DATABASE Currently, this are only supported on :postgresql and :postgresql-socket * base/database.lisp: automatically load ASDF system in CONNECT if not already loaded * base/tests.lisp: disconnect database after testing * base/*.lisp: Remove CLOSED-DATABASE type in favor of storing open/closed status in slot of database * base/pool.lisp: Support locks for CMUCL, OpenMCL, SBCL * db-postgresql/postgresql-sql.lisp: add DATABASE-RECONNECT, DATABASE-DESCRIBE-TABLE * db-sqlite/sqlite-sql.lisp: Add missing slots in database * base/conditions: Remove duplicate condition * db-*/*-sql.lisp: Fill new database slot DATABASE-TYPE * base/recording.lisp: Add new :QUERY type for recording 10 Apr 2004 Kevin Rosenberg (kevin@rosenberg.net) * Version 2.6.1: documentation fixes, merged classic-tests into tests 10 Apr 2004 Kevin Rosenberg (kevin@rosenberg.net) * Version 2.6.0 released: New API functions CREATE-DATABASE, DESTORY-DATABASE, PROBE-DATABASE * doc/ref_clsql.xml: Document new functions * base/database.lisp: New API functions * base/conditions.lisp: Added CLSQL-ACCESS-ERROR * base/utils.lisp: Fix use of position-char. Add COMMAND-OUTPUT used by backends for running external programs. Fix parsing of SQL*NET-compatible connection-specs. * base/loop-extension.lisp: Simplify package use for Lispworks and Allegro * db-*/*-sql.lisp: Added DATABASE-CREATE, DATABASE-DESTORY, PROBE-DATABASE methods * tests/test-init.lisp, clasic-tests/tests.lisp: Use destroy-database and create-database to ensure testing with empty database * tests/test-connection.lisp: Add tests for parsing of string connection-specs * examples/run-tests.sh: New file for running test suite on all installed CL implementations * examples/clsql-tutorial.lisp: moved from doc directory * examples/dot.clsql-tests.config: New file giving an example test configuration * test/README: Add notes about rtest/ptester downloads and link to sample test configuration file. 10 Apr 2004 Kevin Rosenberg (kevin@rosenberg.net) * Version 2.5.1 released: * tests/*.lisp: Rework so tests are run on multiple backends automatically based on the contents of ~/.clsql-tests.config. Reuse helper functions from classic-tests. * base/database.lisp: Support connection-spec as string for CONNECT * classic-tests/tests.lisp: Automatically load database backends as needed. 09 Apr 2004 Kevin Rosenberg (kevin@rosenberg.net) * Version 2.5.0 released: All tests for CLSQL and CLSQL-CLASSIC pass on all platforms. * base/loop-extension.lisp: Add Lispworks loop-extension. Improve type specifying on other platforms. 09 Apr 2004 Kevin Rosenberg (kevin@rosenberg.net) * Version 2.4.2 released: loop extension now supported on Allegro, all CLSQL-TESTS pass on Allegro. * sql/metaclasses.lisp: Some optimization of compute-slots, be selective when ordered-class-slots needs to be called instead of class-slots * TODO: add URL with documentation on extending Lispworks LOOP form 09 Apr 2004 Kevin Rosenberg (kevin@rosenberg.net) * Version 2.4.1 released: CLSQL-TESt suite passes all tests for postgresql and CMUCL, SBCL, OpenMCL. Allegro and Lispworks pass all tests except for FDML/LOOP/1 since the loop extension have not yet been ported to those implementions. * sql/metaclasses.lisp: Added new slot to standard-db-class to hold user-specified type. OpenMCL adjustments to compensate for its type-predicate function. Since AllegroCL, Lispworks, and OpenMCL have different slot orders, added compute-slots and ordered-class-slots functions so their slot order matches SBCL/CMUCL. 08 Apr 2004 Kevin Rosenberg (kevin@rosenberg.net) * Version 2.4.0 released: All tests for clsql-classic now finish correctly on Allegro, Lispworks, CMUCL, SBCL, OpenMCL for mysql, postgresql, postgresql-sockets, and sqlite backends. * db-mysql/mysql-sql.lisp: Fix array dereferencing * classic-tests/tests.lisp: Fix package name of number-to-sql-string. * clsql.asd/clsql-tests.asd: Add support for asdf:test-op * db-sqlite/sqlite-api-{uffi,sql}.lisp: Multiple UFFI fixes, now passes tests on all support UFFI platforms. * db-postgresql-socket/postgresql-socket-api.list: Ported to SBCL and OpenMCL * multiple: Finish renaming of :types keyword to :result-types for greater CommonSQL compatibility, including documentation * sql/basic-cmds.lisp: Remove obsolete file 08 Apr 2004 Kevin Rosenberg (kevin@rosenberg.net) * Version 2.3.3 released * Fixes for sequences on mysql and sqlite [Marcus Pearce] * Fixes for uffi sqlite backend [Aurelio Bignoli / Kevin Rosenberg] * Fix for schema table [Marcus Pearce] * Add loop extension support for SBCL and OpenMCL [Marcus Pearce] * Fixes to test suite [Marcus Pearce] 06 Apr 2004 Kevin Rosenberg (kevin@rosenberg.net) * db-*/*-sql.lisp: Ensure that expr in database-query-result-set is a string * Documentation integration 06 Apr 2004 Kevin Rosenberg (kevin@rosenberg.net) * With for Marcus Pearce's excellent work, I've merged his clsql-usql port into clsql. The original clsql interface is available in the clsql-classic package. 02 Apr 2004 Kevin Rosenberg (kevin@rosenberg.net) * Integrate patch from Marcus Pearce adding further support for providing backend for UncommonSQL 10 Mar 2004 Kevin Rosenberg (kevin@rosenberg.net) * Integrate patch from Aurelio Bignoli for SQLite backend 11 Nov 2003 Kevin Rosenberg (kevin@rosenberg.net) * Converted documentation to XML format * Made package installable with asdf-install 23 Jul 2003 Kevin Rosenberg (kevin@rosenberg.net) * Add for-each-row macro 12 Dec 2002 Kevin Rosenberg (kevin@rosenberg.net) * uffi/clsql-uffi.lisp: return NIL for numeric fields that are NULL 16 Oct 2002 Kevin Rosenberg (kevin@rosenberg.net) * Add support for SBCL, OpenMCL, and SCL * Add *load-truename* to search path for clsql's compiled libraries. 01 Sep 2002 Kevin Rosenberg (kevin@rosenberg.net) * Rework use of file types in .asd files 17 Aug 2002 Kevin Rosenberg (kevin@rosenberg.net) * Add .asd definition files for ASDF users 31 Jul 2002 Kevin Rosenberg (kevin@rosenberg.net) * Restructure directories for Common Lisp Controller v3 compatibility 25 Jul 2002 Kevin Rosenberg (kevin@rosenberg.net) * Also change case of logical host in loader files * Rework handling of logical pathnames 05 Jul 2002 Kevin Rosenberg (kevin@rosenberg.net) * Change case of logical host 14 May 2002 Kevin Rosenberg (kevin@rosenberg.net) * clsql-base.system: Added base package that can be used without high-level SQL commands. Used for adding support for UncommonSQL. * *.system: Reworked logical pathnames to be more consistent with Common Lisp Controller. * debian/*: Completed initial Debian support 10 May 2002 Marc Battyani (marc.battyani@fractalconcept.com) * sql/classes.cl: * sql/transactions.cl: Added transaction support. Functions/macros added: with-transaction, commit-transaction, rollback-transaction, add-transaction-commit-hook, add-transaction-rollback-hook 04 May 2002 Marc Battyani (marc.battyani@fractalconcept.com) * sql/sql.cl: * sql/pool.cl: * sql/functional.cl: Added pool support in connect/disconnect and with-database. Removed with-db-from-pool as with-database can now works with the connections pool 01 May 2002 Marc Battyani (marc.battyani@fractalconcept.com) * sql/sql.cl: * sql/pool.cl: * sql/classes.cl: * sql/package.cl: Completed connection pool. Added with-db-from-pool macro. 27 Apr 2002 Kevin Rosenberg (kevin@rosenberg.net) * Multiple files: Added initial support for connection pool * sql/transactions.cl Took transaction code from UncommonSQL and integrated into CLSQL code. See file for disclaimer about why this was added. 23 Apr 2002 Kevin Rosenberg (kevin@rosenberg.net) * interfaces/postgresql/postgresql-sql.cl: Fix keyword typo in database-read-large-object * interfaces/mysql/mysql-loader.cl Fix loading on Win32 * test-suite/tester-clsql.cl Fix type coercion of double-float * doc/* Added debian docbook catalog, made it the default 19 Apr 2002 Marc Battyani (marc.battyani@fractalconcept.com) * interface/postgresql/postgresql-api.cl: * interface/postgresql/postgresql-sql.cl: * sql/sql.cl: * sql/db-interface.cl: Added large objects support for postgresql. 07 Apr 2002 Kevin Rosenberg (kevin@rosenberg.net) * src/postgresql-socket/postgresql-socket-api.cl: Fixed find-foreign-function call, eliminated crypt warning * Makefiles: Multiple improvements * sql/usql.cl: Moved functionality from low-level interfaces to this file via generic functions * test-suite/tester.cl: Added test with acl-compat-tester, moved others to old-tests directory. 06 Apr 2002 Kevin Rosenberg (kevin@rosenberg.net) * src/usql.cl: Reinstated commented out sections * interfaces/postgresql/postgresql-loader.cl: * interfaces/mysql/mysql-loader.cl: Updated find-forieign-library support. * interfaces/postgresql-socket/postgresql-socket-package.cl: Fixed require form for Lispworks (Thanks Marc Battyani!) * interfaces/postgresql-socket/postgresql-socket-api.cl: Fixed eval of def-function for crypt library. 31 Mar 2002 Kevin Rosenberg (kevin@rosenberg.net) * Added interface to support USQL high-level rouines 29 Mar 2002 Kevin Rosenberg (kevin@rosenberg.net) * Separated db-interface and conditions from sql/sql.cl * Improved foreign library loading testing * interfaces/postgresql/postgresql-api.cl Added PQisBusy function * interfaces/clsql-uffi/clsql-uffi.cl Fixed sign error for 64-bit processing 27 Mar 2002 Kevin Rosenberg (kevin@rosenberg.net) * interfaces/postgresql-socket/postgresql-socket-api.cl: Fixes to read-double-from-socket. Added 64-bit integer support. * test-suite/xptest-clsql.cl Added testint for 64-bit integers * Additons to installation docs 26 Mar 2002 Kevin Rosenberg (kevin@rosenberg.net) * interfaces/postgresql-socket/postgresql-socket-api.cl: Implemented direct socket reading for field type :double * Added usage information for :types to documentation * interfaces/mysql/mysql-sql.cl: Fixed type specifiers in atoi, atol, atof calls * interfaces/clsql-uffi: Created new directory. Split common interface routines that use UFFI into this package. Required especially to support direct reading of 64-bit integers into bignums and bypassing temporary strings. * test-clsql.cl: Updated to test postgresql-socket's read-double-from-socket function. * test-suite/xptest-clsql.cl Started work on test suite 25 Mar 2002 Kevin Rosenberg (kevin@rosenberg.net) * interfaces/mysql/mysql-api.cl: Added mysql-fetch-fields, mysql-fetch-field-direct Got :auto types working * interfaces/postgresql/postgresql-api.cl * interfaces/postgresql-socket/postgresql-socket-api.cl Added pgsql-field-types enum. Got :auto types working. * multiple-files Renamed :field-types to :types. 24 Mar 2002 Kevin Rosenberg (kevin@rosenberg.net) * Added field-types parameter to query, database-query, database-query-result-set, map-query. Haven't added code to utilize field types, yet. * Changed postgresql-socket result set from cons to a structure * Updated test-clsql.cl to use automated testing with a config file * Changed return types of field accessors from cstring to (* :unsigned-char). This prepares for being able to use specified type conversions when taking field data into lisp. * Added field-type processing for most interfaces. Not done yet. 23 Mar 2002 Kevin Rosenberg (kevin@rosenberg.net) * doc/ref.sgml: Updated MAP-QUERY example to use *read-default-float-format* (John Foderaro) * Extensive work to foreign library loaders and .system files to check for successful loading of foreign libraries. * Modified test-clsql.cl to allow more modularity and automated testing in future release. * mysql/mysql-sql.lisp: Added field types 01 Jan 2002 Kevin Rosenberg (kevin@rosenberg.net) * mysql/mysql-sql.lisp: - Added support for Allegro CL and Lispworks using UFFI layer - Changed database-connect to use mysql-real-connect. This way, can avoid using double (unwind-protect) - Changed database-connect to have MySQL library allocate space for MYSQL structure. This will make the code more robust in the event that MySQL library changes the size of the mysql-mysql structure. cl-sql-6.4.1/db-mysql/0000755000175000017500000000000012134026703013455 5ustar kevinkevincl-sql-6.4.1/db-mysql/mysql-client-info.lisp0000644000175000017500000000371511577723152017742 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; FILE IDENTIFICATION ;;;; ;;;; Name: mysql-client-info.lisp ;;;; Purpose: Check mysql client version ;;;; Programmer: Kevin M. Rosenberg ;;;; Date Started: April 2004 ;;;; ;;;; This file, part of CLSQL, is Copyright (c) 2004 by Kevin M. Rosenberg ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* (in-package #:mysql) (declaim (inline mysql-get-client-info)) (defvar *mysql-client-info* nil) (eval-when (:compile-toplevel :load-toplevel :execute) (uffi:def-function ("mysql_get_client_info" mysql-get-client-info) () :module "mysql" :returning :cstring) (setf *mysql-client-info* (uffi:convert-from-cstring (mysql-get-client-info))) (when (and (stringp *mysql-client-info*) (plusp (length *mysql-client-info*))) (cond ((eql (schar *mysql-client-info* 0) #\3) (pushnew :mysql-client-v3 cl:*features*)) ((eql (schar *mysql-client-info* 0) #\4) (pushnew :mysql-client-v4 cl:*features*) (when (and (>= (length *mysql-client-info*) 3) (string-equal "4.1" *mysql-client-info* :end2 3)) (pushnew :mysql-client-v4.1 cl:*features*))) ((eql (schar *mysql-client-info* 0) #\5) (pushnew :mysql-client-v5 cl:*features*) (when (and (>= (length *mysql-client-info*) 3) (string-equal "5.1" *mysql-client-info* :end2 3)) (pushnew :mysql-client-v5.1 cl:*features*))) ((eql (schar *mysql-client-info* 0) #\6) (pushnew :mysql-client-v6 cl:*features*)) (t (error "Unknown mysql client version '~A'." *mysql-client-info*))))) cl-sql-6.4.1/db-mysql/mysql-objects.lisp0000644000175000017500000000430711335067642017157 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; FILE IDENTIFICATION ;;;; ;;;; Name: mysql-objects.lisp ;;;; Purpose: CLSQL Object layer for MySQL ;;;; Created: May 2004 ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* (in-package #:clsql-mysql) (defmethod database-get-type-specifier ((type (eql 'wall-time)) args database (db-type (eql :mysql))) (declare (ignore args database)) "DATETIME") (defmethod database-get-type-specifier ((type (eql 'smallint)) args database (db-type (eql :mysql))) (declare (ignore args database)) "SMALLINT") (defmethod database-get-type-specifier ((type (eql 'mediumint)) args database (db-type (eql :mysql))) (declare (ignore args database)) "MEDIUMINT") (defmethod database-get-type-specifier ((type (eql 'tinyint)) args database (db-type (eql :mysql))) (declare (ignore args database)) "TINYINT") (defmethod database-output-sql-as-type ((type (eql 'boolean)) val database (db-type (eql :mysql))) (declare (ignore database)) (if val 1 0)) (defmethod database-output-sql-as-type ((type (eql 'generalized-boolean)) val database (db-type (eql :mysql))) (declare (ignore database)) (if val 1 0)) (defmethod read-sql-value (val (type (eql 'boolean)) database (db-type (eql :mysql))) (declare (ignore database)) (etypecase val (string (if (string= "0" val) nil t)) (integer (if (zerop val) nil t)))) (defmethod read-sql-value (val (type (eql 'generalized-boolean)) database (db-type (eql :mysql))) (declare (ignore database)) (etypecase val (string (if (string= "0" val) nil t)) (integer (if (zerop val) nil t)))) cl-sql-6.4.1/db-mysql/testing/0000755000175000017500000000000010667176647015160 5ustar kevinkevincl-sql-6.4.1/db-mysql/testing/mysql-struct-size.lisp0000644000175000017500000000044210667176647021510 0ustar kevinkevin(in-package :mysql) #+lispworks (progn (setq c (fli:allocate-foreign-object :type 'mysql-mysql)) (format t "~&Size MYSQL structure: ~d" (fli:pointer-element-size c))) #+allegro (progn (setq c (ff:allocate-fobject 'mysql-mysql :foreign)) (format t "~&Size MYSQL structure: ~A" c)) cl-sql-6.4.1/db-mysql/testing/mysql-struct-size.cc0000644000175000017500000000050610667176647021127 0ustar kevinkevin#include #include "/usr/include/mysql/mysql.h" int main (int argc, char** argv) { printf ("Size of MYSQL struct: %ld\n", sizeof (MYSQL)); printf("Sizeof MYSQL_BIND: %d\n", sizeof(MYSQL_BIND)); printf("Sizeof MYSQL_FIELD: %d\n", sizeof(MYSQL_FIELD)); printf("Sizeof MYSQL_TIME: %d\n", sizeof(MYSQL_TIME)); } cl-sql-6.4.1/db-mysql/Makefile0000644000175000017500000000641311336541306015125 0ustar kevinkevin#!/usr/bin/make # FILE IDENTIFICATION # # Name: Makefile # Purpose: Makefile for CLSQL MySQL interface # Programer: Kevin M. Rosenberg # Date Started: Mar 2002 # # This file, part of CLSQL, is Copyright (c) 2002 by Kevin M. Rosenberg # # CLSQL users are granted the rights to distribute and use this software # as governed by the terms of the Lisp Lesser GNU Public License # (http://opensource.franz.com/preamble.html), also known as the LLGPL. SUBDIRS= include ../Makefile.common base=clsql_mysql source=$(base).c object=$(base).o shared_lib=$(base).so shared64_lib=$(base)64.so dylib=$(base).dylib .PHONY: all all: $(shared_lib) CFLAGS=-I /usr/local/include/mysql -I /usr/include/mysql -I /sw/include/mysql -I /opt/local/include/mysql -I /opt/local/include/mysql5/mysql -I /usr/local/mysql/include LDFLAGS=-L/usr/local/lib64/mysql -L/usr/local/lib/mysql -L/usr/lib64/mysql -L/usr/lib/mysql -L/sw/lib -L/opt/local/lib/mysql -L/opt/local/lib/mysql5/mysql -L/usr/local/mysql/lib -L/usr/lib/gcc/i686-pc-cygwin/3.4.4 -lmysqlclient -lz -lc CFLAGS32=-I /usr/local/include/mysql -I /usr/include/mysql -I /sw/include/mysql -I /opt/local/include/mysql -I /opt/local/include/mysql5/mysql -I /usr/local/mysql/include -m32 LDFLAGS32=-L/lib32 -L/usr/lib32 -melf_i386 -lmysqlclient -lz -lc ifneq ($(OS_CYGWIN),0) CFLAGS=-I /cygdrive/c/Program\ Files/MySQL/MySQL\ Server\ 5.0/include LDFLAGS=-L/usr/local/lib64/mysql -L/usr/local/lib/mysql -L/usr/lib/mysql -L/sw/lib -L/opt/local/lib/mysql -L/usr/lib/gcc/i686-pc-cygwin/3.4.4 -lmysqlclient -lpthread -lz -lm -lgcc -lc endif $(shared_lib): $(source) Makefile ifneq ($(OS_AIX),0) gcc $(CFLAGS) -c -D_BSD -D_NO_PROTO -D_NONSTD_TYPES -D_MBI=void $(source) make_shared $(LDFLAGS) -o $(shared_lib) $(object) else ifneq ($(OS_SUNOS),0) cc $(CFLAGS) -KPIC -c $(source) -o $(object) cc -G $(object) $(LDFLAGS) -o $(shared_lib) else ifneq ($(OS_DARWIN64),0) cc $(CFLAGS) -arch x86_64 -arch i386 -bundle /usr/lib/bundle1.o -flat_namespace -undefined suppress $(source) -o $(dylib) cc -arch x86_64 -arch i386 -bundle /usr/lib/bundle1.o -flat_namespace -undefined suppress /usr/lib/libz.dylib -o z.dylib else ifneq ($(OS_DARWIN),0) cc $(CFLAGS) -arch i386 -bundle /usr/lib/bundle1.o -flat_namespace -undefined suppress $(source) -o $(dylib) cc -arch i386 -bundle /usr/lib/bundle1.o -flat_namespace -undefined suppress /usr/lib/libz.dylib -o z.dylib else ifneq ($(OS_CYGWIN),0) gcc $(CFLAGS) -DWIN32 -c $(source) -o $(object) ld -shared -soname=$(base) $(object) $(LDFLAGS) -o $(shared_lib) else ifneq ($(OS_LINUX64),0) gcc $(CFLAGS) -fPIC -c $(source) -o $(object) ld -shared -soname=$(base) $(object) $(LDFLAGS) -o $(shared64_lib) rm $(object) @echo "Ensure that you have multiarch i386 build tools and libraries if you want to build 32-bit library" -gcc $(CFLAGS32) -fPIC -c $(source) -o $(object) -ld -shared -soname=$(base) $(object) $(LDFLAGS32) -o $(shared_lib) else gcc $(CFLAGS) -fPIC -c $(source) -o $(object) ld -shared -soname=$(base) $(object) $(LDFLAGS) -o $(shared_lib) endif endif endif endif endif endif rm -f $(object) .PHONY: distclean distclean: clean @rm -f $(dylib) $(shared_lib) $(shared64_lib) $(object) z.dylib cl-sql-6.4.1/db-mysql/clsql_mysql.dll0000644000175000017500000001100010667176647016533 0ustar kevinkevinMZÿÿ¸@躴 Í!¸LÍ!This program cannot be run in DOS mode. $;Zg^; ; ; ü3T }; z7T }; z7i ~; z7 |; € |; ; r; z7V w; z7U ~; z7S ~; Rich; PELPÓÀ@à!  } P`"AÔ P@€x H @.text¨ `.rdata¡  @@.data(0@À.reloc”@@BU‹ì¸] ÌÌÌÌU‹ìƒì‹E 3ɉEø‰Mü‹Eø‹Uü± èR‰Eø‰Uü‹U3ÀUø‹MüȉUø‰Mü‹UüR‹EøP‹MQè‹å]ÃÌÌÌÌU‹ìƒì‹EPèó‰Eø‰Uü‹Eø‹Uü± è‹M ‰‹Eø#@ ‹å]ÃÌÌÌÌÌÌÌÌÌÌÌÌU‹ìƒì‹EP蹉Eø‰Uü‹Eø‹Uü± èÞ‹M ‰‹Eø#@ ‹å]ÃÌÌÌÌÌÌÌÌÌÌÌÌU‹ìƒì‹EPè‰Eø‰Uü‹Eø‹Uü± èž‹M ‰‹Eø#@ ‹å]ÃÌÌÌÌÌÌÌÌÌÌÌÌU‹ì‹Ef‹@L]ÃÌÌÌÌU‹ì‹E‹]ÃÌÌÌÌÌÌU‹ì‹E‹@]ÃÌÌÌÌÌU‹ì‹E‹@ ]ÃÌÿ% ÿ% ÿ% ÿ% ÌÌÌÌÌÌÌÌÌÌÌÌ€ù@s€ù s¥ÂÓàËÐ3À€áÓâÃ3À3ÒÃÌ€ù@s€ù s­ÐÓêËÂ3Ò€áÓèÃ3À3ÒËD$…Àu90~.ÿ 0ƒø‹ 8 ‹ ‰ 0uOh€ÿ …ÀY£ 0u3Àëyƒ ¡ 0£0èhäèqÇ$0h0è4ÿ0Yë?…Àu<¡ 0…Àt3ë‹ 0‹ …ÉtÿÑ¡ 0ƒ-090sÞPÿ4 ƒ% 0Y3À@ j hH èÇ3À@‰Eä3ÿ‰}ü‹u ;÷u 9=0„¬;ðtƒþu1¡$0;Çt ÿuVÿuÿЉEä9}ä„…ÿuVÿuèåþÿÿ‰Eä;Çtr‹]SVÿuè@‰Eäƒþu;Çu SWÿuè»þÿÿ;÷tƒþu)SVÿuè¨þÿÿ…Àu‰}ä9}ät¡$0;Çt SVÿuÿЉEäƒMüÿ‹Eäë‹Eì‹‹ PQèÛYYËeèƒMüÿ3Àè- Ìÿ% ƒ= 0ÿuÿ%0 h0h 0ÿt$ èƒÄ Ãÿt$èÑÿÿÿ÷ØÀ÷ØYHÃj hX è¤ÇEäÈ }äÈ s"ƒeü‹Eä‹…Àt ÿÐë3À@ËeèƒMüÿƒEäëÕè¨Ãj hh è`ÇEäÐ }äÐ s"ƒeü‹Eä‹…Àt ÿÐë3À@ËeèƒMüÿƒEäëÕèdÃÿ%$ ƒ|$uƒ=$0u ÿt$ÿ 3À@ ÌÌhœd¡P‹D$‰l$l$+àSVW‹Eø‰eèP‹EüÇEüÿÿÿÿ‰EøEðd£Ã‹Mðd‰ Y_^[ÉQÃÿ%( ÿ%, 6"ž!ˆ!v!d!Ò!Æ!ì!þ!","¾!Ü!ÿÿÿÿÿÿÿÿ?PÿÿÿÿÍÑÿÿÿÿH0À œ,!°! @!" $!R" 6"ž!ˆ!v!d!Ò!Æ!ì!þ!","¾!Ü!mysql_data_seek7mysql_num_rowsmysql_affected_rows0mysql_insert_idLIBMYSQL.dll¬free?_inittermßmalloc»_adjust_fdivL__CppXcptFilterñ_except_handler3MSVCR71.dllk__dllonexit¸_onexit„DisableThreadLibraryCallsKERNEL32.dllPÓÀ@Ø"ˆ"¨"È" @P0 à`â"ü"#+#H#_#v#Œ#mysql.dllclsql_mysql_affected_rowsclsql_mysql_data_seekclsql_mysql_field_lengthclsql_mysql_field_max_lengthclsql_mysql_field_nameclsql_mysql_field_typeclsql_mysql_insert_idclsql_mysql_num_rowsNæ@»hŒ0Ì0 1^1d1j1p1É1Ñ1Ú1â1ï1÷12 22 2%202<2H2U2[2b2k2q2€22±2$3d3j3s3x3}3£3¯3¶3ç3ó3ú3*474D4Q4ž4¤4 L0P0\0`0l0p0´0¸0cl-sql-6.4.1/db-mysql/clsql_mysql.c0000644000175000017500000000676511335067642016213 0ustar kevinkevin/**************************************************************************** * FILE IDENTIFICATION * * Name: clsql-mysql.c * Purpose: Helper functions for mysql.cl to handle 64-bit parts of API * Programmer: Kevin M. Rosenberg * Date Started: Mar 2002 * * This file, part of CLSQL, is Copyright (c) 2002 by Kevin M. Rosenberg * * CLSQL users are granted the rights to distribute and use this software * as governed by the terms of the Lisp Lesser GNU Public License * (http://opensource.franz.com/preamble.html), also known as the LLGPL. ***************************************************************************/ #if defined(WIN32)||defined(WIN64) #include BOOL WINAPI DllEntryPoint(HINSTANCE hinstdll, DWORD fdwReason, LPVOID lpvReserved) { return 1; } #define DLLEXPORT __declspec(dllexport) #else #define DLLEXPORT #endif #include /* Need to assemble a 64-bit integer to send to MySQL */ DLLEXPORT void clsql_mysql_data_seek (MYSQL_RES* res, unsigned int offset_high32, unsigned int offset_low32) { my_ulonglong offset; offset = offset_high32; offset = offset << 32; offset += offset_low32; mysql_data_seek (res, offset); } /* The following functions are used to return 64-bit integers to Lisp. They return the 32-bit low part and store in upper 32-bits in a located sent via a pointer */ static const unsigned int bitmask_32bits = 0xFFFFFFFF; #define lower_32bits(int64) ((unsigned int) int64 & bitmask_32bits) #define upper_32bits(int64) ((unsigned int) (int64 >> 32)) DLLEXPORT unsigned int clsql_mysql_num_rows (MYSQL_RES* res, unsigned int* pHigh32) { my_ulonglong nRows = mysql_num_rows (res); *pHigh32 = upper_32bits(nRows); return lower_32bits(nRows); } DLLEXPORT unsigned int clsql_mysql_affected_rows (MYSQL* res, unsigned int* pHigh32) { my_ulonglong nAffected = mysql_affected_rows (res); *pHigh32 = upper_32bits(nAffected); return lower_32bits(nAffected); } DLLEXPORT unsigned int clsql_mysql_insert_id (MYSQL* mysql, unsigned int* pHigh32) { my_ulonglong insert_id = mysql_insert_id (mysql); *pHigh32 = upper_32bits(insert_id); return lower_32bits(insert_id); } /* Accessor functions to hide the differences across MySQL versions */ DLLEXPORT unsigned int clsql_mysql_field_flags (MYSQL_FIELD* field) { return field->flags; } DLLEXPORT unsigned int clsql_mysql_field_type (MYSQL_FIELD* field) { return field->type; } DLLEXPORT char* clsql_mysql_field_name (MYSQL_FIELD* field) { return field->name; } DLLEXPORT unsigned long clsql_mysql_field_length (MYSQL_FIELD* field) { return field->length; } DLLEXPORT unsigned long clsql_mysql_field_max_length (MYSQL_FIELD* field) { return field->max_length; } #if MYSQL_VERSION_ID >= 40102 #include DLLEXPORT MYSQL_BIND* allocate_bind (unsigned int n) { return (MYSQL_BIND*) malloc (n * sizeof(MYSQL_BIND)); } DLLEXPORT void bind_param (MYSQL_BIND bind[], unsigned int n, unsigned long length, unsigned short is_null, void* buffer, unsigned short buffer_type, unsigned long buffer_length) { *bind[n].length = length; *bind[n].is_null = is_null; bind[n].buffer = buffer; bind[n].buffer_type = buffer_type; bind[n].buffer_length = buffer_length; } DLLEXPORT unsigned int clsql_mysql_stmt_affected_rows (MYSQL_STMT* stmt, unsigned int* pHigh32) { my_ulonglong nAffected = mysql_stmt_affected_rows (stmt); *pHigh32 = upper_32bits(nAffected); return lower_32bits(nAffected); } #endif cl-sql-6.4.1/db-mysql/mysql-package.lisp0000644000175000017500000001011111336541306017102 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; FILE IDENTIFICATION ;;;; ;;;; Name: mysql-package.cl ;;;; Purpose: Package definition for low-level MySQL interface ;;;; Programmers: Kevin M. Rosenberg ;;;; Date Started: Feb 2002 ;;;; ;;;; This file, part of CLSQL, is Copyright (c) 2002 by Kevin M. Rosenberg ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* (in-package #:cl-user) (defpackage #:mysql (:use #:common-lisp #:clsql-uffi) (:export #:database-library-loaded #:mysql-socket #:mysql-book #:mysql-byte #:mysql-net-type #:mysql-net-type#tcp-ip #:mysql-net-type#socket #:mysql-net-type#named-pipe #:mysql-net #:mysql-used-mem #:mysql-mem-root #:mysql-field-types #:mysql-field-types#decimal #:mysql-field-types#tiny #:mysql-field-types#short #:mysql-field-types#long #:mysql-field-types#float #:mysql-field-types#double #:mysql-field-types#null #:mysql-field-types#timestamp #:mysql-field-types#longlong #:mysql-field-types#int24 #:mysql-field-types#date #:mysql-field-types#time #:mysql-field-types#datetime #:mysql-field-types#year #:mysql-field-types#newdate #:mysql-field-types#enum #:mysql-field-types#tiny-blob #:mysql-field-types#medium-blob #:mysql-field-types#long-blob #:mysql-field-types#blob #:mysql-field-types#var-string #:mysql-field-types#string #:mysql-field #:mysql-row #:mysql-field-offset #:mysql-row-offset #:mysql-field-vector #:mysql-data #:mysql-options #:mysql-mysql-option #:mysql-mysql-option#connect-timeout #:mysql-mysql-option#compress #:mysql-mysql-option#named-pipe #:mysql-mysql-option#init-command #:mysql-mysql-option#read-default-file #:mysql-mysql-option#read-default-group #:mysql-status #:mysql-status#ready #:mysql-status#get-ready #:mysql-status#use-result #:mysql-mysql #:mysql-mysql-res ;; functions #:mysql-init #:mysql-connect #:mysql-real-connect #:mysql-close #:mysql-select-db #:mysql-query #:mysql-real-query #:mysql-create-db #:mysql-drop-db #:mysql-shutdown #:mysql-dump-debug-info #:mysql-refresh #:mysql-kill #:mysql-ping #:mysql-stat #:mysql-get-server-info #:mysql-get-client-info #:mysql-get-host-info #:mysql-get-proto-info #:mysql-list-dbs #:mysql-list-tables #:mysql-list-fields #:mysql-list-processes #:mysql-store-result #:mysql-use-result #:mysql-options #:mysql-free-result #:mysql-row-seek #:mysql-field-seek #:mysql-fetch-row #:mysql-fetch-lengths #:mysql-fetch-field #:mysql-fetch-fields #:mysql-fetch-field-direct #:mysql-escape-string #:mysql-debug #:mysql-num-rows #:mysql-num-fields #:mysql-affected-rows #:mysql-insert-id #:mysql-eof #:mysql-error #:mysql-error-string #:mysql-errno #:mysql-info #:mysql-info-string #:mysql-data-seek #:mysql-time #:mysql-bind #:mysql-stmt-param-count #:mysql-stmt-prepare #:mysql-stmt-execute #:mysql-stmt-store-result #:mysql-stmt-init #:mysql-stmt-close-result #:mysql-stmt-free-result #:mysql-stmt #:mysql-stmt-result-metadata #:mysql-stmt-fetch #:mysql-stmt-bind-param #:mysql-stmt-bind-result #:mysql-stmt-close #:mysql-stmt-errno #:mysql-stmt-error #:make-64-bit-integer #:clsql-mysql-field-name #:clsql-mysql-field-type #:clsql-mysql-field-flags #:+mysql-option-parameter-map+ ) (:documentation "This is the low-level interface MySQL.")) cl-sql-6.4.1/db-mysql/mysql-api.lisp0000644000175000017500000003423711345753563016311 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; FILE IDENTIFICATION ;;;; ;;;; Name: mysql-api.lisp ;;;; Purpose: Low-level MySQL interface using UFFI ;;;; Programmers: Kevin M. Rosenberg based on ;;;; Original code by Pierre R. Mai ;;;; Date Started: Feb 2002 ;;;; ;;;; This file, part of CLSQL, is Copyright (c) 2002-2009 by Kevin M. Rosenberg ;;;; and Copyright (c) 1999-2001 by Pierre R. Mai ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* (in-package #:mysql) ;;;; Modifications from original code ;;;; - Updated C-structures to conform to structures in MySQL 3.23.46 ;;;; - Changed from CMUCL interface to UFFI ;;;; - Added and call a C-helper file to support 64-bit integers ;;;; that are used in a few routines. ;;;; - Removed all references to interiors of C-structions, this will ;;;; increase robustness when MySQL's internal structures change. ;;;; Type definitions ;;; Basic Types (uffi:def-foreign-type mysql-socket :int) (uffi:def-foreign-type mysql-bool :byte) (uffi:def-foreign-type mysql-byte :unsigned-char) (uffi:def-enum mysql-net-type (:tcp-ip :socket :named-pipe)) (uffi:def-array-pointer mysql-row (* :unsigned-char)) ;;; MYSQL-FIELD (uffi:def-enum mysql-field-types (:decimal :tiny :short :long :float :double :null :timestamp :longlong :int24 :date :time :datetime :year :newdate (:enum 247) (:set 248) (:tiny-blob 249) (:medium-blob 250) (:long-blob 251) (:blob 252) (:var-string 253) (:string 254) (:geometry 255))) (uffi:def-enum mysql-option (:connect-timeout :compress :named-pipe :init-command :read-default-file :read-default-group :set-charset-dir :set-charset-name :local-infile :protocol :shared-memory-base-name :read-timeout :write-timeout :use-result :use-remote-connection :use-embedded-connection :guess-connection :set-client-ip :secure-auth :report-data-truncation :reconnect :ssl-verify-server-cert)) (defvar +mysql-option-parameter-map+ '((:connect-timeout . :uint-ptr) (:compress . :none) (:named-pipe . :none) (:init-command . :char-ptr) (:read-default-file . :char-ptr) (:read-default-group . :char-ptr) (:set-charset-dir . :char-ptr) (:set-charset-name . :char-ptr) (:local-infile . :uint-ptr) (:protocol . :uint-ptr) (:shared-memory-base-name . :char-ptr) (:read-timeout . :uint-ptr) (:write-timeout . :uint-ptr) (:use-result . :none) (:use-remote-connection . :none) (:use-embedded-connection . :none) (:guess-connection . :none) (:set-client-ip . :char-ptr) (:secure-auth . :boolean-ptr) (:report-data-truncation . :boolean-ptr) (:reconnect . :boolean-ptr) (:ssl-verify-server-cert . :boolean-ptr))) (uffi:def-enum mysql-status (:ready :get-result :use-result)) ;;; Opaque pointers to mysql C-defined structures (uffi:def-foreign-type mysql-mysql (* :void)) (uffi:def-foreign-type mysql-mysql-res (* :void)) (uffi:def-foreign-type mysql-field (* :void)) (uffi:def-foreign-type mysql-bind (* :void)) ;;;; The Foreign C routines (declaim (inline mysql-init)) (uffi:def-function "mysql_init" ((mysql mysql-mysql)) :module "mysql" :returning mysql-mysql) ;; Need to comment this out for LW 4.2.6 ;; ? bug in LW version #-lispworks (declaim (inline mysql-real-connect)) (uffi:def-function "mysql_real_connect" ((mysql mysql-mysql) (host :cstring) (user :cstring) (passwd :cstring) (db :cstring) (port :unsigned-int) (unix-socket :cstring) (clientflag :unsigned-long)) :module "mysql" :returning mysql-mysql) (declaim (inline mysql-close)) (uffi:def-function "mysql_close" ((sock mysql-mysql)) :module "mysql" :returning :void) (declaim (inline mysql-select-db)) (uffi:def-function "mysql_select_db" ((mysql mysql-mysql) (db :cstring)) :module "mysql" :returning :int) (declaim (inline mysql-query)) (uffi:def-function "mysql_query" ((mysql mysql-mysql) (query :cstring)) :module "mysql" :returning :int) ;;; I doubt that this function is really useful for direct Lisp usage, ;;; but it is here for completeness... (declaim (inline mysql-real-query)) (uffi:def-function "mysql_real_query" ((mysql mysql-mysql) (query :cstring) (length :unsigned-int)) :module "mysql" :returning :int) (declaim (inline mysql-shutdown)) (uffi:def-function "mysql_shutdown" ((mysql mysql-mysql)) :module "mysql" :returning :int) (declaim (inline mysql-dump-debug-info)) (uffi:def-function "mysql_dump_debug_info" ((mysql mysql-mysql)) :module "mysql" :returning :int) (declaim (inline mysql-refresh)) (uffi:def-function "mysql_refresh" ((mysql mysql-mysql) (refresh-options :unsigned-int)) :module "mysql" :returning :int) (declaim (inline mysql-kill)) (uffi:def-function "mysql_kill" ((mysql mysql-mysql) (pid :unsigned-long)) :module "mysql" :returning :int) (declaim (inline mysql-ping)) (uffi:def-function "mysql_ping" ((mysql mysql-mysql)) :module "mysql" :returning :int) (declaim (inline mysql-stat)) (uffi:def-function "mysql_stat" ((mysql mysql-mysql)) :module "mysql" :returning :cstring) (declaim (inline mysql-get-server-info)) (uffi:def-function "mysql_get_server_info" ((mysql mysql-mysql)) :module "mysql" :returning :cstring) (declaim (inline mysql-get-host-info)) (uffi:def-function "mysql_get_host_info" ((mysql mysql-mysql)) :module "mysql" :returning :cstring) (declaim (inline mysql-get-proto-info)) (uffi:def-function "mysql_get_proto_info" ((mysql mysql-mysql)) :module "mysql" :returning :unsigned-int) (declaim (inline mysql-list-dbs)) (uffi:def-function "mysql_list_dbs" ((mysql mysql-mysql) (wild :cstring)) :module "mysql" :returning mysql-mysql-res) (declaim (inline mysql-list-tables)) (uffi:def-function "mysql_list_tables" ((mysql mysql-mysql) (wild :cstring)) :module "mysql" :returning mysql-mysql-res) (declaim (inline mysql-list-fields)) (uffi:def-function "mysql_list_fields" ((mysql mysql-mysql) (table :cstring) (wild :cstring)) :module "mysql" :returning mysql-mysql-res) (declaim (inline mysql-list-processes)) (uffi:def-function "mysql_list_processes" ((mysql mysql-mysql)) :module "mysql" :returning mysql-mysql-res) (declaim (inline mysql-store-result)) (uffi:def-function "mysql_store_result" ((mysql mysql-mysql)) :module "mysql" :returning mysql-mysql-res) (declaim (inline mysql-use-result)) (uffi:def-function "mysql_use_result" ((mysql mysql-mysql)) :module "mysql" :returning mysql-mysql-res) (declaim (inline mysql-options)) (uffi:def-function "mysql_options" ((mysql mysql-mysql) (option mysql-option) (arg :pointer-void)) :module "mysql" :returning :int) (declaim (inline mysql-free-result)) (uffi:def-function "mysql_free_result" ((res mysql-mysql-res)) :module "mysql" :returning :void) (declaim (inline mysql-fetch-row)) (uffi:def-function "mysql_fetch_row" ((res mysql-mysql-res)) :module "mysql" :returning (* (* :unsigned-char))) (declaim (inline mysql-fetch-lengths)) (uffi:def-function "mysql_fetch_lengths" ((res mysql-mysql-res)) :module "mysql" :returning (* :unsigned-long)) (declaim (inline mysql-fetch-field)) (uffi:def-function "mysql_fetch_field" ((res mysql-mysql-res)) :module "mysql" :returning mysql-field) (declaim (inline mysql-field-seek)) (uffi:def-function "mysql_field_seek" ((res mysql-mysql-res) (offset :unsigned-int)) :module "mysql" :returning :unsigned-int) (declaim (inline mysql-fetch-fields)) (uffi:def-function "mysql_fetch_fields" ((res mysql-mysql-res)) :module "mysql" :returning mysql-field) (declaim (inline mysql-fetch-field-direct)) (uffi:def-function "mysql_fetch_field_direct" ((res mysql-mysql-res) (field-num :unsigned-int)) :module "mysql" :returning mysql-field) (declaim (inline mysql-escape-string)) (uffi:def-function "mysql_escape_string" ((to (* :unsigned-char)) (from (* :unsigned-char)) (length :unsigned-int)) :module "mysql" :returning :unsigned-int) (declaim (inline mysql-debug)) (uffi:def-function "mysql_debug" ((debug :cstring)) :module "mysql" :returning :void) (declaim (inline clsql-mysql-num-rows)) (uffi:def-function "clsql_mysql_num_rows" ((res mysql-mysql-res) (p-high32 (* :unsigned-int))) :module "clsql-mysql" :returning :unsigned-int) #+(or mysql-client-v4.1 mysql-client-v5) (uffi:def-foreign-type mysql-stmt-ptr :pointer-void) #+(or mysql-client-v4.1 mysql-client-v5) (uffi:def-function "mysql_stmt_init" ((res mysql-mysql-res)) :module "clsql-mysql" :returning mysql-stmt-ptr) #+(or mysql-client-v4.1 mysql-client-v5) (uffi:def-function "mysql_stmt_prepare" ((stmt mysql-stmt-ptr) (query :cstring) (length :unsigned-long)) :module "clsql-mysql" :returning :int) #+(or mysql-client-v4.1 mysql-client-v5) (uffi:def-function "mysql_stmt_param_count" ((stmt mysql-stmt-ptr)) :module "clsql-mysql" :returning :unsigned-int) #+(or mysql-client-v4.1 mysql-client-v5) (uffi:def-function "mysql_stmt_bind_param" ((stmt mysql-stmt-ptr) (bind mysql-bind)) :module "clsql-mysql" :returning :short) #+(or mysql-client-v4.1 mysql-client-v5) (uffi:def-function "mysql_stmt_bind_result" ((stmt mysql-stmt-ptr) (bind mysql-bind)) :module "clsql-mysql" :returning :short) #+(or mysql-client-v4.1 mysql-client-v5) (uffi:def-function "mysql_stmt_result_metadata" ((stmt mysql-stmt-ptr)) :module "clsql-mysql" :returning mysql-mysql-res) #+(or mysql-client-v4.1 mysql-client-v5) (uffi:def-function "mysql_stmt_execute" ((stmt mysql-stmt-ptr)) :module "clsql-mysql" :returning :int) #+(or mysql-client-v4.1 mysql-client-v5) (uffi:def-function "mysql_stmt_store_result" ((stmt mysql-stmt-ptr)) :module "clsql-mysql" :returning :int) #+(or mysql-client-v4.1 mysql-client-v5) (uffi:def-function "mysql_stmt_fetch" ((stmt mysql-stmt-ptr)) :module "clsql-mysql" :returning :int) #+(or mysql-client-v4.1 mysql-client-v5) (uffi:def-function "mysql_stmt_free_result" ((stmt mysql-stmt-ptr)) :module "clsql-mysql" :returning :short) #+(or mysql-client-v4.1 mysql-client-v5) (uffi:def-function "mysql_stmt_close" ((stmt mysql-stmt-ptr)) :module "clsql-mysql" :returning :short) #+(or mysql-client-v4.1 mysql-client-v5) (uffi:def-function "mysql_stmt_errno" ((stmt mysql-stmt-ptr)) :module "clsql-mysql" :returning :unsigned-int) #+(or mysql-client-v4.1 mysql-client-v5) (uffi:def-function "mysql_stmt_error" ((stmt mysql-stmt-ptr)) :module "clsql-mysql" :returning :cstring) ;;;; Equivalents of C Macro definitions for accessing various fields ;;;; in the internal MySQL Datastructures (declaim (inline mysql-num-rows)) (defun mysql-num-rows (res) (uffi:with-foreign-object (p-high32 :unsigned-int) (let ((low32 (clsql-mysql-num-rows res p-high32)) (high32 (uffi:deref-pointer p-high32 :unsigned-int))) (if (zerop high32) low32 (make-64-bit-integer high32 low32))))) (uffi:def-function "clsql_mysql_affected_rows" ((mysql mysql-mysql) (p-high32 (* :unsigned-int))) :returning :unsigned-int :module "clsql-mysql") (defun mysql-affected-rows (mysql) (uffi:with-foreign-object (p-high32 :unsigned-int) (let ((low32 (clsql-mysql-affected-rows mysql p-high32)) (high32 (uffi:deref-pointer p-high32 :unsigned-int))) (if (zerop high32) low32 (make-64-bit-integer high32 low32))))) (uffi:def-function "clsql_mysql_insert_id" ((res mysql-mysql) (p-high32 (* :unsigned-int))) :returning :unsigned-int :module "clsql-mysql") (defun mysql-insert-id (mysql) (uffi:with-foreign-object (p-high32 :unsigned-int) (let ((low32 (clsql-mysql-insert-id mysql p-high32)) (high32 (uffi:deref-pointer p-high32 :unsigned-int))) (if (zerop high32) low32 (make-64-bit-integer high32 low32))))) (declaim (inline mysql-num-fields)) (uffi:def-function "mysql_num_fields" ((res mysql-mysql-res)) :returning :unsigned-int :module "mysql") (declaim (inline clsql-mysql-eof)) (uffi:def-function ("mysql_eof" clsql-mysql-eof) ((res mysql-mysql-res)) :returning :char :module "mysql") (declaim (inline mysql-eof)) (defun mysql-eof (res) (if (zerop (clsql-mysql-eof res)) nil t)) (declaim (inline mysql-error)) (uffi:def-function ("mysql_error" mysql-error) ((mysql mysql-mysql)) :returning :cstring :module "mysql") (declaim (inline mysql-error-string)) (defun mysql-error-string (mysql) (uffi:convert-from-cstring (mysql-error mysql))) (declaim (inline mysql-errno)) (uffi:def-function "mysql_errno" ((mysql mysql-mysql)) :returning :unsigned-int :module "mysql") (declaim (inline mysql-info)) (uffi:def-function ("mysql_info" mysql-info) ((mysql mysql-mysql)) :returning :cstring :module "mysql") (declaim (inline mysql-info-string)) (defun mysql-info-string (mysql) (uffi:convert-from-cstring (mysql-info mysql))) (declaim (inline clsql-mysql-data-seek)) (uffi:def-function "clsql_mysql_data_seek" ((res mysql-mysql-res) (offset-high32 :unsigned-int) (offset-low32 :unsigned-int)) :module "clsql-mysql" :returning :void) (declaim (inline clsql-mysql-field-name)) (uffi:def-function "clsql_mysql_field_name" ((res mysql-field)) :module "clsql-mysql" :returning :cstring) (declaim (inline clsql-mysql-field-flags)) (uffi:def-function "clsql_mysql_field_flags" ((res mysql-field)) :module "clsql-mysql" :returning :unsigned-int) (declaim (inline clsql-mysql-field-type)) (uffi:def-function "clsql_mysql_field_type" ((res mysql-field)) :module "clsql-mysql" :returning :unsigned-int) (defun mysql-data-seek (res offset) (multiple-value-bind (high32 low32) (split-64-bit-integer offset) (clsql-mysql-data-seek res high32 low32))) cl-sql-6.4.1/db-mysql/Makefile.msvc0000755000175000017500000000222111335067642016075 0ustar kevinkevin# -*- Mode: Makefile -*- ########################################################################### # FILE IDENTIFICATION # # Name: Makefile.msvc # Purpose: Makefile for the CLSQL UFFI helper package (MSVC) # Author: Kevin M. Rosenberg # Created: Mar 2002 # # This file, part of CLSQL, is Copyright (c) 2002-2010 by Kevin M. Rosenberg # # CLSQL users are granted the rights to distribute and use this software # as governed by the terms of the Lisp Lesser GNU Public License # (http://opensource.franz.com/preamble.html), also known as the LLGPL. ########################################################################### BASE=clsql_mysql # Set to the directory where you have installed mysql's library MYSQL_DIR=c:/Program Files/MySQL/MySQL Server 5.1/ MYSQL_LIB_FILE=$(MYSQL_DIR)lib\opt\mysqlclient.lib MYSQL_INCLUDE=$(MYSQL_DIR)include # Nothing to configure beyond here SRC=$(BASE).c OBJ=$(BASE).obj DLL=$(BASE).dll LIB=$(BASE).lib $(DLL): $(SRC) $(MYSQL_LIB_FILE) echo "LD" echo $(MYSQL_LIB_FILE) cl /MD /LD -D_MT /DWIN32=1 /D__LCC__=1 /I"$(MYSQL_INCLUDE)" $(SRC) $(MYSQL_LIB_FILE) del $(OBJ) $(BASE).exp clean: del /q $(DLL) cl-sql-6.4.1/db-mysql/mysql-loader.lisp0000644000175000017500000000430211746263021016762 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; FILE IDENTIFICATION ;;;; ;;;; Name: mysql-loader.sql ;;;; Purpose: MySQL library loader using UFFI ;;;; Author: Kevin M. Rosenberg ;;;; Created: Feb 2002 ;;;; ;;;; This file, part of CLSQL, is Copyright (c) 2002-2010 by Kevin M. Rosenberg ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* (in-package #:mysql) ;; searches clsql_mysql64 to accomodate both 32-bit and 64-bit libraries on same system (defparameter *clsql-mysql-library-candidate-names* `(,@(when (> most-positive-fixnum (expt 2 32)) (list "clsql_mysql64")) "clsql_mysql")) (defvar *mysql-library-candidate-names* '("libmysqlclient" "libmysql")) (defvar *mysql-supporting-libraries* '("c") "Used only by CMU. List of library flags needed to be passed to ld to load the MySQL client library succesfully. If this differs at your site, set to the right path before compiling or loading the system.") (defvar *mysql-library-loaded* nil "T if foreign library was able to be loaded successfully") (defmethod clsql-sys:database-type-library-loaded ((database-type (eql :mysql))) *mysql-library-loaded*) (defmethod clsql-sys:database-type-load-foreign ((database-type (eql :mysql))) (unless *mysql-library-loaded* (clsql:push-library-path clsql-mysql-system::*library-file-dir*) (clsql-uffi:find-and-load-foreign-library *mysql-library-candidate-names* :module "mysql" :supporting-libraries *mysql-supporting-libraries*) (clsql-uffi:find-and-load-foreign-library *clsql-mysql-library-candidate-names* :module "clsql-mysql" :supporting-libraries *mysql-supporting-libraries*) (setq *mysql-library-loaded* t))) (clsql-sys:database-type-load-foreign :mysql) cl-sql-6.4.1/db-mysql/mysql-sql.lisp0000644000175000017500000010571211636413404016322 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; FILE IDENTIFICATION ;;;; ;;;; Name: mysql-sql.lisp ;;;; Purpose: High-level MySQL interface using UFFI ;;;; Date Started: Feb 2002 ;;;; ;;;; This file, part of CLSQL, is Copyright (c) 2002-2010 by Kevin M. Rosenberg ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* (defpackage #:clsql-mysql (:use #:common-lisp #:clsql-sys #:mysql #:clsql-uffi) (:export #:mysql-database) (:import-from :clsql-sys :escaped :unescaped :combine-database-identifiers :escaped-database-identifier :unescaped-database-identifier :database-identifier :%sequence-name-to-table :%table-name-to-sequence-name) (:documentation "This is the CLSQL interface to MySQL.")) (in-package #:clsql-mysql) ;;; Field conversion functions (defun result-field-names (res-ptr) (let ((names '())) (mysql-field-seek res-ptr 0) (loop (let ((field (mysql-fetch-field res-ptr))) (when (uffi:null-pointer-p field) (return)) (push (uffi:convert-from-cstring (clsql-mysql-field-name field)) names))) (nreverse names))) (defun make-type-list-for-auto (res-ptr) (let ((new-types '())) (mysql-field-seek res-ptr 0) (loop (let ((field (mysql-fetch-field res-ptr))) (when (uffi:null-pointer-p field) (return)) (let* ((flags (clsql-mysql-field-flags field)) (unsigned (plusp (logand flags 32))) (type (clsql-mysql-field-type field))) (push (case type ((#.mysql-field-types#tiny #.mysql-field-types#short #.mysql-field-types#int24) (if unsigned :uint32 :int32)) (#.mysql-field-types#long (if unsigned :uint :int)) (#.mysql-field-types#longlong (if unsigned :uint64 :int64)) ((#.mysql-field-types#double #.mysql-field-types#float #.mysql-field-types#decimal) :double) (otherwise t)) new-types)))) (nreverse new-types))) (defun canonicalize-types (types res-ptr) (when types (let ((auto-list (make-type-list-for-auto res-ptr))) (cond ((listp types) (canonicalize-type-list types auto-list)) ((eq types :auto) auto-list) (t nil))))) (defmethod database-initialize-database-type ((database-type (eql :mysql))) t) ;;(uffi:def-type mysql-mysql-ptr-def (* mysql-mysql)) ;;(uffi:def-type mysql-mysql-res-ptr-def (* mysql-mysql-res)) (uffi:def-type mysql-mysql-ptr-def mysql-mysql) (uffi:def-type mysql-mysql-res-ptr-def mysql-mysql-res) (uffi:def-type mysql-row-def mysql-row) (defclass mysql-database (database) ((mysql-ptr :accessor database-mysql-ptr :initarg :mysql-ptr :type mysql-mysql-ptr-def) (server-info :accessor database-server-info :initarg :server-info :type string))) (defmethod database-type ((database mysql-database)) :mysql) (defmethod database-name-from-spec (connection-spec (database-type (eql :mysql))) (check-connection-spec connection-spec database-type (host db user password &optional port options)) (destructuring-bind (host db user password &optional port options) connection-spec (declare (ignore password options)) (concatenate 'string (etypecase host (null "localhost") (pathname (namestring host)) (string host)) (if port (concatenate 'string ":" (etypecase port (integer (write-to-string port)) (string port))) "") "/" db "/" user))) (defun lookup-option-code (option) (if (assoc option +mysql-option-parameter-map+) (symbol-value (intern (concatenate 'string (symbol-name-default-case "mysql-option#") (symbol-name option)) (symbol-name '#:mysql))) (progn (warn "Unknown mysql option name ~A - ignoring.~%" option) nil))) (defun set-mysql-options (mysql-ptr options) (flet ((lookup-option-type (option) (cdr (assoc option +mysql-option-parameter-map+)))) (dolist (option options) (if (atom option) (let ((option-code (lookup-option-code option))) (when option-code (mysql-options mysql-ptr option-code uffi:+null-cstring-pointer+))) (destructuring-bind (name . value) option (let ((option-code (lookup-option-code name))) (when option-code (case (lookup-option-type name) (:none (mysql-options mysql-ptr option-code uffi:+null-cstring-pointer+)) (:char-ptr (if (stringp value) (uffi:with-foreign-string (fs value) (mysql-options mysql-ptr option-code fs)) (warn "Expecting string argument for mysql option ~A, got ~A ~ - ignoring.~%" name value))) (:uint-ptr (if (integerp value) (uffi:with-foreign-object (fo :unsigned-int) (setf (uffi:deref-pointer fo :unsigned-int) value) (mysql-options mysql-ptr option-code fo)) (warn "Expecting integer argument for mysql option ~A, got ~A ~ - ignoring.~%" name value))) (:boolean-ptr (uffi:with-foreign-object (fo :byte) (setf (uffi:deref-pointer fo :byte) (if (or (zerop value) (null value)) 0 1)) (mysql-options mysql-ptr option-code fo))))))))))) (defmethod database-connect (connection-spec (database-type (eql :mysql))) (check-connection-spec connection-spec database-type (host db user password &optional port options)) (destructuring-bind (host db user password &optional port options) connection-spec (let ((mysql-ptr (mysql-init (uffi:make-null-pointer 'mysql-mysql))) (socket nil)) (if (uffi:null-pointer-p mysql-ptr) (error 'sql-connection-error :database-type database-type :connection-spec connection-spec :error-id (mysql-errno mysql-ptr) :message (mysql-error-string mysql-ptr)) (uffi:with-cstrings ((host-native host) (user-native user) (password-native password) (db-native db) (socket-native socket)) (when options (set-mysql-options mysql-ptr options)) (let ((error-occurred nil)) (unwind-protect (if (uffi:null-pointer-p (mysql-real-connect mysql-ptr host-native user-native password-native db-native (etypecase port (null 0) (integer port) (string (parse-integer port))) socket-native 0)) (progn (setq error-occurred t) (error 'sql-connection-error :database-type database-type :connection-spec connection-spec :error-id (mysql-errno mysql-ptr) :message (mysql-error-string mysql-ptr))) (let* ((db (make-instance 'mysql-database :name (database-name-from-spec connection-spec database-type) :database-type :mysql :connection-spec connection-spec :server-info (uffi:convert-from-cstring (mysql:mysql-get-server-info mysql-ptr)) :mysql-ptr mysql-ptr)) (cmd "SET SESSION sql_mode='ANSI'")) (uffi:with-cstring (cmd-cs cmd) (if (zerop (mysql-real-query mysql-ptr cmd-cs (uffi:foreign-encoded-octet-count cmd :encoding (encoding db)))) db (progn (warn "Error setting ANSI mode for MySQL.") db))))) (when error-occurred (mysql-close mysql-ptr))))))))) (defmethod database-disconnect ((database mysql-database)) (mysql-close (database-mysql-ptr database)) (setf (database-mysql-ptr database) nil) t) (defmethod database-execute-command (sql-expression (database mysql-database)) (uffi:with-cstring (sql-native sql-expression) (let ((mysql-ptr (database-mysql-ptr database))) (declare (type mysql-mysql-ptr-def mysql-ptr)) (if (zerop (mysql-real-query mysql-ptr sql-native (uffi:foreign-encoded-octet-count sql-expression :encoding (encoding database)))) t (error 'sql-database-data-error :database database :expression sql-expression :error-id (mysql-errno mysql-ptr) :message (mysql-error-string mysql-ptr)))))) (defmethod database-query (query-expression (database mysql-database) result-types field-names) (declare (optimize (speed 3) (safety 0) (debug 0) (space 0))) (let ((mysql-ptr (database-mysql-ptr database))) (declare (type mysql-mysql-ptr-def mysql-ptr)) (when (database-execute-command query-expression database) (let ((res-ptr (mysql-use-result mysql-ptr))) (declare (type mysql-mysql-res-ptr-def res-ptr)) (if (and res-ptr (not (uffi:null-pointer-p res-ptr))) (unwind-protect (let ((num-fields (mysql-num-fields res-ptr))) (declare (fixnum num-fields)) (setq result-types (canonicalize-types result-types res-ptr)) (values (loop for row = (mysql-fetch-row res-ptr) for lengths = (mysql-fetch-lengths res-ptr) until (uffi:null-pointer-p row) collect (do* ((rlist (make-list num-fields)) (i 0 (1+ i)) (pos rlist (cdr pos))) ((= i num-fields) rlist) (declare (fixnum i)) (setf (car pos) (convert-raw-field (uffi:deref-array row '(:array (* :unsigned-char)) i) (nth i result-types) :length (uffi:deref-array lengths '(:array :unsigned-long) i) :encoding (encoding database))))) (when field-names (result-field-names res-ptr)))) (mysql-free-result res-ptr)) (unless (zerop (mysql-errno mysql-ptr)) ;;from http://dev.mysql.com/doc/refman/5.0/en/mysql-field-count.html ;; if mysql_use_result or mysql_store_result return a null ptr, ;; we use a mysql_errno check to see if it had a problem or just ;; was a query without a result. If no error, just return nil. (error 'sql-database-data-error :database database :expression query-expression :error-id (mysql-errno mysql-ptr) :message (mysql-error-string mysql-ptr)))))))) (defstruct mysql-result-set (res-ptr (uffi:make-null-pointer 'mysql-mysql-res) :type mysql-mysql-res-ptr-def) (types nil :type list) (num-fields 0 :type fixnum) (full-set nil :type boolean)) (defmethod database-query-result-set ((query-expression string) (database mysql-database) &key full-set result-types) (let ((mysql-ptr (database-mysql-ptr database))) (declare (type mysql-mysql-ptr-def mysql-ptr)) (when (database-execute-command query-expression database) (let ((res-ptr (if full-set (mysql-store-result mysql-ptr) (mysql-use-result mysql-ptr)))) (declare (type mysql-mysql-res-ptr-def res-ptr)) (if (not (uffi:null-pointer-p res-ptr)) (let* ((num-fields (mysql-num-fields res-ptr)) (result-set (make-mysql-result-set :res-ptr res-ptr :num-fields num-fields :full-set full-set :types (canonicalize-types result-types res-ptr)))) (if full-set (values result-set num-fields (mysql-num-rows res-ptr)) (values result-set num-fields))) (error 'sql-database-data-error :database database :expression query-expression :error-id (mysql-errno mysql-ptr) :message (mysql-error-string mysql-ptr)))) ))) (defmethod database-dump-result-set (result-set (database mysql-database)) (mysql-free-result (mysql-result-set-res-ptr result-set)) t) (defmethod database-store-next-row (result-set (database mysql-database) list) (let* ((res-ptr (mysql-result-set-res-ptr result-set)) (row (mysql-fetch-row res-ptr)) (lengths (mysql-fetch-lengths res-ptr)) (types (mysql-result-set-types result-set))) (declare (type mysql-mysql-res-ptr-def res-ptr) (type mysql-row-def row)) (unless (uffi:null-pointer-p row) (loop for i from 0 below (mysql-result-set-num-fields result-set) for rest on list do (setf (car rest) (convert-raw-field (uffi:deref-array row '(:array (* :unsigned-char)) i) (nth i types) :length (uffi:deref-array lengths '(:array :unsigned-long) i) :encoding (encoding database)))) list))) ;; Table and attribute introspection (defmethod database-list-tables ((database mysql-database) &key (owner nil)) (declare (ignore owner)) (cond ((eql #\5 (char (database-server-info database) 0)) (loop for (name type) in (database-query "SHOW FULL TABLES" database nil nil) when (and (string-equal type "base table") (not (and (>= (length name) 11) (string-equal (subseq name 0 11) "_CLSQL_SEQ_")))) collect name)) (t (remove-if #'(lambda (s) (and (>= (length s) 11) (string-equal (subseq s 0 11) "_CLSQL_SEQ_"))) (mapcar #'car (database-query "SHOW TABLES" database nil nil)))))) (defmethod database-list-views ((database mysql-database) &key (owner nil)) (declare (ignore owner)) (cond ((eql #\5 (char (database-server-info database) 0)) (loop for (name type) in (database-query "SHOW FULL TABLES" database nil nil) when (string-equal type "view") collect name)) (t nil))) (defmethod database-list-indexes ((database mysql-database) &key (owner nil)) (let ((result '())) (dolist (table (database-list-tables database :owner owner) result) (setq result (append (database-list-table-indexes table database :owner owner) result))))) (defmethod database-list-table-indexes (table (database mysql-database) &key (owner nil)) (declare (ignore owner)) (do ((results nil) (rows (database-query (format nil "SHOW INDEX FROM ~A" (escaped-database-identifier table database)) database nil nil) (cdr rows))) ((null rows) (nreverse results)) (let ((col (nth 2 (car rows)))) (unless (find col results :test #'string-equal) (push col results))))) (defmethod database-list-attributes ((table clsql-sys::%database-identifier) (database mysql-database) &key (owner nil) &aux (table (unescaped-database-identifier table))) (declare (ignore owner)) (mapcar #'car (database-query (format nil "SHOW COLUMNS FROM ~A" (escaped-database-identifier table database)) database nil nil))) (defmethod database-attribute-type ((attribute clsql-sys::%database-identifier) (table clsql-sys::%database-identifier) (database mysql-database) &key (owner nil) &aux (table (unescaped-database-identifier table)) (attribute (unescaped-database-identifier attribute))) (declare (ignore owner)) (let ((row (car (database-query (format nil "SHOW COLUMNS FROM ~A LIKE '~A'" (escaped-database-identifier table database) (unescaped-database-identifier attribute database)) database nil nil)))) (let* ((raw-type (second row)) (null (third row)) (start-length (position #\( raw-type)) (type (if start-length (subseq raw-type 0 start-length) raw-type)) (length (when start-length (parse-integer (subseq raw-type (1+ start-length)) :junk-allowed t)))) (when type (values (ensure-keyword type) length nil (if (string-equal null "YES") 1 0)))))) ;;; Sequence functions (defmethod database-create-sequence (sequence-name (database mysql-database)) (let ((table-name (%sequence-name-to-table sequence-name database))) (database-execute-command (concatenate 'string "CREATE TABLE " table-name " (id int NOT NULL PRIMARY KEY AUTO_INCREMENT)") database) (database-execute-command (concatenate 'string "INSERT INTO " table-name " VALUES (-1)") database))) (defmethod database-drop-sequence (sequence-name (database mysql-database)) (database-execute-command (concatenate 'string "DROP TABLE " (%sequence-name-to-table sequence-name database)) database)) (defmethod database-list-sequences ((database mysql-database) &key (owner nil)) (declare (ignore owner)) (mapcan #'(lambda (s) (let ((sn (%table-name-to-sequence-name (car s)))) (and sn (list (car s) sn)))) (database-query "SHOW TABLES" database nil nil))) (defmethod database-set-sequence-position (sequence-name (position integer) (database mysql-database)) (database-execute-command (format nil "UPDATE ~A SET id=~A" (%sequence-name-to-table sequence-name database) position) database) (mysql:mysql-insert-id (clsql-mysql::database-mysql-ptr database))) (defmethod database-sequence-next (sequence-name (database mysql-database)) (without-interrupts (database-execute-command (concatenate 'string "UPDATE " (%sequence-name-to-table sequence-name database) " SET id=LAST_INSERT_ID(id+1)") database) (mysql:mysql-insert-id (clsql-mysql::database-mysql-ptr database)))) (defmethod database-sequence-last (sequence-name (database mysql-database)) (without-interrupts (caar (database-query (concatenate 'string "SELECT id from " (%sequence-name-to-table sequence-name database)) database :auto nil)))) (defmethod database-last-auto-increment-id ((database mysql-database) table column) (declare (ignore table column)) (car (query "SELECT LAST_INSERT_ID();" :flatp t :field-names nil :database database))) (defmethod database-create (connection-spec (type (eql :mysql))) (destructuring-bind (host name user password) connection-spec (let ((database (database-connect (list host "" user password) type))) (setf (slot-value database 'clsql-sys::state) :open) (unwind-protect (database-execute-command (format nil "create database ~A" name) database) (database-disconnect database))))) (defmethod database-destroy (connection-spec (type (eql :mysql))) (destructuring-bind (host name user password) connection-spec (let ((database (database-connect (list host "" user password) type))) (setf (slot-value database 'clsql-sys::state) :open) (unwind-protect (database-execute-command (format nil "drop database ~A" name) database) (database-disconnect database))))) (defmethod database-probe (connection-spec (type (eql :mysql))) (when (find (second connection-spec) (database-list connection-spec type) :test #'string-equal) t)) (defmethod database-list (connection-spec (type (eql :mysql))) (destructuring-bind (host name user password &optional port options) connection-spec (declare (ignore options)) (let ((database (database-connect (list host (or name "mysql") user password port) type))) (unwind-protect (progn (setf (slot-value database 'clsql-sys::state) :open) (mapcar #'car (database-query "show databases" database :auto nil))) (progn (database-disconnect database) (setf (slot-value database 'clsql-sys::state) :closed)))))) ;;; Prepared statements (defclass mysql-stmt () ((database :initarg :database :reader database) (stmt :initarg :stmt :accessor stmt) (input-bind :initarg :input-bind :reader input-bind) (output-bind :initarg :output-bind :reader output-bind) (types :initarg :types :reader types) (result-set :initarg :result-set :reader result-set) (num-fields :initarg :num-fields :reader num-fields) (field-names :initarg :field-names :accessor stmt-field-names) (length-ptr :initarg :length-ptr :reader length-ptr) (is-null-ptr :initarg :is-null-ptr :reader is-null-ptr) (result-types :initarg :result-types :reader result-types))) (defun clsql-type->mysql-type (type) (cond ((in type :null) mysql-field-types#null) ((in type :int :integer) mysql-field-types#long) ((in type :short) mysql-field-types#short) ((in type :bigint) mysql-field-types#longlong) ((in type :float :double :number) mysql-field-types#double) ((and (consp type) (in (car type) :char :string :varchar)) mysql-field-types#var-string) ((or (eq type :blob) (and (consp type) (in (car type) :blob))) mysql-field-types#var-string) (t (error 'sql-user-error :message (format nil "Unknown clsql type ~A." type))))) #+mysql-client-v4.1 (defmethod database-prepare (sql-stmt types (database mysql-database) result-types field-names) (let* ((mysql-ptr (database-mysql-ptr database)) (stmt (mysql-stmt-init mysql-ptr))) (when (uffi:null-pointer-p stmt) (error 'sql-database-error :error-id (mysql-errno mysql-ptr) :message (mysql-error-string mysql-ptr))) (uffi:with-cstring (native-query sql-stmt) (unless (zerop (mysql-stmt-prepare stmt native-query (uffi:foreign-encoded-octet-count sql-stmt :encoding (encoding database)))) (mysql-stmt-close stmt) (error 'sql-database-error :error-id (mysql-errno mysql-ptr) :message (mysql-error-string mysql-ptr)))) (unless (= (mysql-stmt-param-count stmt) (length types)) (mysql-stmt-close stmt) (error 'sql-database-error :message (format nil "Mysql param count (~D) does not match number of types (~D)" (mysql-stmt-param-count stmt) (length types)))) (let ((rs (mysql-stmt-result-metadata stmt))) (when (uffi:null-pointer-p rs) (warn "mysql_stmt_result_metadata returned NULL") #+nil (mysql-stmt-close stmt) #+nil (error 'sql-database-error :message "mysql_stmt_result_metadata returned NULL")) (let ((input-bind (uffi:allocate-foreign-object 'mysql-bind (length types))) (mysql-types (mapcar 'clsql-type->mysql-type types)) field-vec num-fields is-null-ptr output-bind length-ptr) (print 'a) (dotimes (i (length types)) (let* ((binding (uffi:deref-array input-bind '(:array mysql-bind) i))) (setf (uffi:get-slot-value binding 'mysql-bind 'mysql::buffer-type) (nth i mysql-types)) (setf (uffi:get-slot-value binding 'mysql-bind 'mysql::buffer-length) 0))) (print 'b) (unless (uffi:null-pointer-p rs) (setq field-vec (mysql-fetch-fields rs) num-fields (mysql-num-fields rs) is-null-ptr (uffi:allocate-foreign-object :byte num-fields) output-bind (uffi:allocate-foreign-object 'mysql-bind num-fields) length-ptr (uffi:allocate-foreign-object :unsigned-long num-fields)) (dotimes (i num-fields) (declare (fixnum i)) (let* ((field (uffi:deref-array field-vec '(:array mysql-field) i)) (type (uffi:get-slot-value field 'mysql-field 'type)) (binding (uffi:deref-array output-bind '(:array mysql-bind) i))) (setf (uffi:get-slot-value binding 'mysql-bind 'mysql::buffer-type) type) (setf (uffi:get-slot-value binding 'mysql-bind 'mysql::buffer-length) 0) #+need-to-allocate-foreign-object-for-this (setf (uffi:get-slot-value binding 'mysql-bind 'mysql::is-null) (+ i (uffi:pointer-address is-null-ptr))) #+need-to-allocate-foreign-object-for-this (setf (uffi:get-slot-value binding 'mysql-bind 'length) (+ (* i 8) (uffi:pointer-address length-ptr))) (case type ((#.mysql-field-types#var-string #.mysql-field-types#string #.mysql-field-types#tiny-blob #.mysql-field-types#blob #.mysql-field-types#medium-blob #.mysql-field-types#long-blob) (setf (uffi:get-slot-value binding 'mysql-bind 'mysql::buffer-length) 1024) (setf (uffi:get-slot-value binding 'mysql-bind 'mysql::buffer) (uffi:allocate-foreign-object :unsigned-char 1024))) (#.mysql-field-types#tiny (setf (uffi:get-slot-value binding 'mysql-bind 'mysql::buffer) (uffi:allocate-foreign-object :byte))) (#.mysql-field-types#short (setf (uffi:get-slot-value binding 'mysql-bind 'mysql::buffer) (uffi:allocate-foreign-object :short))) (#.mysql-field-types#long (setf (uffi:get-slot-value binding 'mysql-bind 'mysql::buffer) ;; segfaults if supply :int on amd64 (uffi:allocate-foreign-object :long))) #+64bit (#.mysql-field-types#longlong (setf (uffi:get-slot-value binding 'mysql-bind 'mysql::buffer) (uffi:allocate-foreign-object :long))) (#.mysql-field-types#float (setf (uffi:get-slot-value binding 'mysql-bind 'mysql::buffer) (uffi:allocate-foreign-object :float))) (#.mysql-field-types#double (setf (uffi:get-slot-value binding 'mysql-bind 'mysql::buffer) (uffi:allocate-foreign-object :double))) ((#.mysql-field-types#time #.mysql-field-types#date #.mysql-field-types#datetime #.mysql-field-types#timestamp) (uffi:allocate-foreign-object 'mysql-time)) (t (error "mysql type ~D not supported." type))))) (unless (zerop (mysql-stmt-bind-result stmt output-bind)) (mysql-stmt-close stmt) (error 'sql-database-error :error-id (mysql-stmt-errno stmt) :message (uffi:convert-from-cstring (mysql-stmt-error stmt))))) (make-instance 'mysql-stmt :database database :stmt stmt :num-fields num-fields :input-bind input-bind :output-bind output-bind :result-set rs :result-types result-types :length-ptr length-ptr :is-null-ptr is-null-ptr :types mysql-types :field-names field-names))))) #+mysql-client-v4.1 (defmethod database-bind-parameter ((stmt mysql-stmt) position value) ;; FIXME: will need to allocate bind structure. This should probably be ;; done in C since the API is not mature and may change (let ((binding (uffi:deref-array (input-bind stmt) '(:array mysql-bind) (1- position))) (type (nth (1- position) (types stmt)))) (setf (uffi:get-slot-value binding 'mysql-bind 'length) 0) (cond ((null value) (when (is-null-ptr stmt) (setf (uffi:deref-array (is-null-ptr stmt) '(:array :byte) (1- position)) 1))) (t (when (is-null-ptr stmt) (setf (uffi:deref-array (is-null-ptr stmt) '(:array :byte) (1- position)) 0)) (case type (#.mysql-field-types#long (setf (uffi:get-slot-value binding 'mysql-bind 'mysql::buffer) value)) (t (warn "Unknown input bind type ~D." type)) ))))) #+mysql-client-v4.1 (defmethod database-run-prepared ((stmt mysql-stmt)) (print 'a1) (when (input-bind stmt) (unless (zerop (mysql-stmt-bind-param (stmt stmt) (input-bind stmt))) (error 'sql-database-error :error-id (mysql-stmt-errno (stmt stmt)) :message (uffi:convert-from-cstring (mysql-stmt-error (stmt stmt)))))) (print 'a2) (unless (zerop (mysql-stmt-execute (stmt stmt))) (error 'sql-database-error :error-id (mysql-stmt-errno (stmt stmt)) :message (uffi:convert-from-cstring (mysql-stmt-error (stmt stmt))))) (print 'a3) (unless (zerop (mysql-stmt-store-result (stmt stmt))) (error 'sql-database-error :error-id (mysql-stmt-errno (stmt stmt)) :message (uffi:convert-from-cstring (mysql-stmt-error (stmt stmt))))) (database-fetch-prepared-rows stmt)) #+mysql-client-v4.1 (defun database-fetch-prepared-rows (stmt) (do ((rc (mysql-stmt-fetch (stmt stmt)) (mysql-stmt-fetch (stmt stmt))) (num-fields (num-fields stmt)) (rows '())) ((not (zerop rc)) (nreverse rows)) (push (loop for i from 0 below num-fields collect (let ((is-null (not (zerop (uffi:ensure-char-integer (uffi:deref-array (is-null-ptr stmt) '(:array :byte) i)))))) (unless is-null (let* ((bind (uffi:deref-array (output-bind stmt) '(:array mysql-bind) i)) (type (uffi:get-slot-value bind 'mysql-bind 'mysql::buffer-type)) (buffer (uffi:get-slot-value bind 'mysql-bind 'mysql::buffer))) (case type ((#.mysql-field-types#var-string #.mysql-field-types#string #.mysql-field-types#tiny-blob #.mysql-field-types#blob #.mysql-field-types#medium-blob #.mysql-field-types#long-blob) (uffi:convert-from-foreign-string buffer :encoding (encoding (database stmt)))) (#.mysql-field-types#tiny (uffi:ensure-char-integer (uffi:deref-pointer buffer :byte))) (#.mysql-field-types#short (uffi:deref-pointer buffer :short)) (#.mysql-field-types#long (uffi:deref-pointer buffer :int)) #+64bit (#.mysql-field-types#longlong (uffi:deref-pointer buffer :long)) (#.mysql-field-types#float (uffi:deref-pointer buffer :float)) (#.mysql-field-types#double (uffi:deref-pointer buffer :double)) ((#.mysql-field-types#time #.mysql-field-types#date #.mysql-field-types#datetime #.mysql-field-types#timestamp) (let ((year (uffi:get-slot-value buffer 'mysql-time 'mysql::year)) (month (uffi:get-slot-value buffer 'mysql-time 'mysql::month)) (day (uffi:get-slot-value buffer 'mysql-time 'mysql::day)) (hour (uffi:get-slot-value buffer 'mysql-time 'mysql::hour)) (minute (uffi:get-slot-value buffer 'mysql-time 'mysql::minute)) (second (uffi:get-slot-value buffer 'mysql-time 'mysql::second))) (db-timestring (make-time :year year :month month :day day :hour hour :minute minute :second second)))) (t (list type))))))) rows))) #+mysql-client-v4.1 (defmethod database-free-prepared ((stmt mysql-stmt)) (with-slots (stmt) stmt (mysql-stmt-close stmt)) ) ;;; Database capabilities (defmethod db-type-use-column-on-drop-index? ((db-type (eql :mysql))) t) (defmethod db-type-has-views? ((db-type (eql :mysql))) #+mysql-client-v5 t #-mysql-client-v5 nil) (defmethod db-type-has-subqueries? ((db-type (eql :mysql))) #+(or mysql-client-v4.1 mysql-client-v5) t #-(or mysql-client-v4.1 mysql-client-v5) nil) (defmethod db-type-has-boolean-where? ((db-type (eql :mysql))) #+(or mysql-client-v4.1 mysql-client-v5) t #-(or mysql-client-v4.1 mysql-client-v5) nil) (defmethod db-type-has-union? ((db-type (eql :mysql))) (not (eql (schar mysql::*mysql-client-info* 0) #\3))) (defmethod db-type-transaction-capable? ((db-type (eql :mysql)) database) (let ((tuple (car (database-query "SHOW VARIABLES LIKE 'HAVE_INNODB'" database :auto nil)))) (and tuple (string-equal "YES" (second tuple))))) (defmethod db-type-has-prepared-stmt? ((db-type (eql :mysql))) #+(or mysql-client-v4.1 mysql-client-v5) t #-(or mysql-client-v4.1 mysql-client-v5) nil) (defmethod db-type-has-auto-increment? ((db-type (eql :mysql))) t) (when (clsql-sys:database-type-library-loaded :mysql) (clsql-sys:initialize-database-type :database-type :mysql)) cl-sql-6.4.1/clsql.asd0000644000175000017500000001050112064371376013544 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; FILE IDENTIFICATION ;;;; ;;;; Name: clsql.asd ;;;; Purpose: ASDF System definition for CLSQL ;;;; Authors: Marcus Pearce and Kevin M. Rosenberg ;;;; Created: March 2004 ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* (in-package #:cl-user) (defpackage #:clsql-system (:use #:asdf #:cl)) (in-package #:clsql-system) #+(and clisp (not :clsql-cffi)) (asdf:operate 'asdf:load-op 'clsql-cffi) ;; need to load uffi for below perform :after method (eval-when (:compile-toplevel :load-toplevel :execute) #+:clsql-cffi (unless (find-package 'cffi-uffi-compat) (asdf:operate 'asdf:load-op 'cffi-uffi-compat)) #-:clsql-cffi (unless (find-package 'uffi) (asdf:operate 'asdf:load-op 'uffi))) (defsystem clsql :name "CLSQL" :author "Kevin Rosenberg " :maintainer "Kevin M. Rosenberg " :licence "Lessor Lisp General Public License" :description "Common Lisp SQL Interface library" :long-description "A Common Lisp interface to SQL RDBMS based on the Xanalys CommonSQL interface for Lispworks. It provides low-level database interfaces as well as a functional and an object oriented interface." :version "6.4" :components ((:module sql :components ((:module base :pathname "" :components ((:file "cmucl-compat") (:file "package") (:file "kmr-mop" :depends-on ("package")) (:file "base-classes" :depends-on ("package")) (:file "conditions" :depends-on ("base-classes")) (:file "db-interface" :depends-on ("conditions")) (:file "utils" :depends-on ("package" "db-interface")) (:file "time" :depends-on ("package" "conditions" "utils")) (:file "generics" :depends-on ("package")))) (:module database :pathname "" :components ((:file "initialize") (:file "database" :depends-on ("initialize")) (:file "recording" :depends-on ("database")) (:file "pool" :depends-on ("database"))) :depends-on (base)) (:module syntax :pathname "" :components ((:file "expressions") (:file "operations" :depends-on ("expressions")) (:file "syntax" :depends-on ("operations"))) :depends-on (database)) (:module functional :pathname "" :components ((:file "fdml") (:file "transaction" :depends-on ("fdml")) #+clisp (:file "ansi-loop") (:file "loop-extension" :depends-on ("fdml" #+clisp "ansi-loop")) (:file "fddl" :depends-on ("fdml"))) :depends-on (syntax)) (:module object :pathname "" :components ((:file "metaclasses") (:file "ooddl" :depends-on ("metaclasses")) (:file "oodml" :depends-on ("ooddl"))) :depends-on (functional)) (:module generic :pathname "" :components ((:file "generic-postgresql") (:file "generic-odbc") (:file "sequences") (:file "command-object")) :depends-on (functional)))))) (defmethod perform ((o test-op) (c (eql (find-system 'clsql)))) (operate 'load-op 'clsql-tests) (operate 'test-op 'clsql-tests :force t)) (defmethod perform :after ((o load-op) (c (eql (find-system 'clsql)))) (let* ((init-var (uffi:getenv "CLSQLINIT")) (init-file (or (when init-var (probe-file init-var)) (probe-file (concatenate 'string (namestring (user-homedir-pathname)) ".clsql-init.lisp")) (probe-file "/etc/clsql-init.lisp") #+(or mswin windows win32 win64 mswindows) (probe-file "c:\\etc\\clsql-init.lisp")))) (when init-file (load init-file)))) cl-sql-6.4.1/db-db2/0000755000175000017500000000000012134026703012757 5ustar kevinkevincl-sql-6.4.1/db-db2/foreign-resources.lisp0000644000175000017500000000346311335067642017330 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; FILE IDENTIFICATION ;;;; ;;;; This file is part of CLSQL. ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* (in-package #:clsql-db2) (defparameter *foreign-resource-hash* (make-hash-table :test #'equal)) (defstruct (foreign-resource) (type (error "Missing TYPE.") :read-only t) (sizeof (error "Missing SIZEOF.") :read-only t) (buffer (error "Missing BUFFER.") :read-only t) (in-use nil :type boolean)) (defun %get-resource (type sizeof) (let ((resources (gethash type *foreign-resource-hash*))) (car (member-if #'(lambda (res) (and (= (foreign-resource-sizeof res) sizeof) (not (foreign-resource-in-use res)))) resources)))) (defun %insert-foreign-resource (type res) (let ((resource (gethash type *foreign-resource-hash*))) (setf (gethash type *foreign-resource-hash*) (cons res resource)))) (defmacro acquire-foreign-resource (type &optional size) `(let ((res (%get-resource ,type ,size))) (unless res (setf res (make-foreign-resource :type ,type :sizeof ,size :buffer (uffi:allocate-foreign-object ,type ,size))) (%insert-foreign-resource ',type res)) (claim-foreign-resource res))) (defun free-foreign-resource (ares) (setf (foreign-resource-in-use ares) nil) ares) (defun claim-foreign-resource (ares) (setf (foreign-resource-in-use ares) t) ares) cl-sql-6.4.1/db-db2/db2-constants.lisp0000644000175000017500000000155611335067642016351 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; FILE IDENTIFICATION ;;;; ;;;; Name: db2-constants.lisp ;;;; Purpose: Constants for CLSQL Db2 interface ;;;; ;;;; This file is part of CLSQL. ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* (in-package #:clsql-db2) (defconstant SQL_NULL_HANDLE nil) (defconstant SQL_HANDLE_ENV 1) (defconstant SQL_HANDLE_DBC 2) (defconstant SQL_HANDLE_STMT 3) (defconstant SQL_NTS -3) (defconstant SQL_ERROR -1) (defconstant SQL_SUCCESS 0) (defconstant SQL_SUCCESS_WITH_INFO 1) cl-sql-6.4.1/db-db2/db2-sql.lisp0000644000175000017500000000524711335067642015135 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; FILE IDENTIFICATION ;;;; ;;;; Name: db2-sql.lisp ;;;; ;;;; This file is part of CLSQL. ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* (in-package #:clsql-db2) (defmethod database-initialize-database-type ((database-type (eql :db2))) t) (defclass db2-database (database) ((henv :initform nil :allocation :class :initarg :henv :accessor henv) (hdbc :initform nil :initarg :hdbc :accessor hdbc))) (defmethod database-name-from-spec (connection-spec (database-type (eql :db2))) (check-connection-spec connection-spec database-type (dsn user password)) (destructuring-bind (dsn user password) connection-spec (declare (ignore password)) (concatenate 'string dsn "/" user))) (defmethod database-connect (connection-spec (database-type (eql :db2))) (check-connection-spec connection-spec database-type (dsn user password)) (destructuring-bind (server user password) connection-spec (handler-case (let ((db (make-instance 'db2-database :name (database-name-from-spec connection-spec :db2) :database-type :db2))) (db2-connect db server user password) db) (error () ;; Init or Connect failed (error 'sql-connection-error :database-type database-type :connection-spec connection-spec :message "Connection failed"))))) ;; API Functions (uffi:def-type handle-type cli-handle) (uffi:def-type handle-ptr-type (* cli-handle)) (defmacro deref-vp (foreign-object) `(the handle-type (uffi:deref-pointer (the handle-ptr-type ,foreign-object) cli-handle))) (defun db2-connect (db server user password) (let ((henv (uffi:allocate-foreign-object 'cli-handle)) (hdbc (uffi:allocate-foreign-object 'cli-handle))) (sql-alloc-handle SQL_HANDLE_ENV SQL_NULL_HANDLE henv) (setf (slot-value db 'henv) henv) (setf (slot-value db 'hdbc) hdbc) (sql-alloc-handle SQL_HANDLE_DBC (deref-vp henv) hdbc) (uffi:with-cstrings ((native-server server) (native-user user) (native-password password)) (sql-connect (deref-vp hdbc) native-server SQL_NTS native-user SQL_NTS native-password SQL_NTS))) db) cl-sql-6.4.1/db-db2/db2-package.lisp0000644000175000017500000000157011335067642015724 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; FILE IDENTIFICATION ;;;; ;;;; Name: db2-package.cl ;;;; Purpose: Package definition for CLSQL Db2 interface ;;;; ;;;; This file is part of CLSQL. ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* (in-package #:cl-user) (defpackage #:clsql-db2 (:use #:common-lisp #:clsql-sys #:clsql-uffi) (:export #:db2-database #:*db2-server-version* #:*db2-so-load-path* #:*db2-so-libraries*) (:documentation "This is the CLSQL interface to Db2.")) cl-sql-6.4.1/db-db2/Makefile0000644000175000017500000000123511335067642014431 0ustar kevinkevin#!/usr/bin/make ########################################################################## # FILE IDENTIFICATION # # Name: Makefile # Purpose: Makefile for CLSQL Db2 interface # Author: Kevin M. Rosenberg # Created: May 2004 # # This file, part of CLSQL, is Copyright (c) 2004 by Kevin M. Rosenberg # # CLSQL users are granted the rights to distribute and use this software # as governed by the terms of the Lisp Lesser GNU Public License # (http://opensource.franz.com/preamble.html), also known as the LLGPL. ########################################################################## SUBDIRS= include ../Makefile.common .PHONY: distclean distclean: clean cl-sql-6.4.1/db-db2/db2-objects.lisp0000644000175000017500000000106511335067642015761 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; FILE IDENTIFICATION ;;;; ;;;; Name: db2-objects.lisp ;;;; ;;;; This file is part of CLSQL. ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* (in-package #:clsql-db2) cl-sql-6.4.1/db-db2/db2-api.lisp0000644000175000017500000000727511335067642015112 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; FILE IDENTIFICATION ;;;; ;;;; Name: db2.lisp ;;;; Purpose: Package definition for CLSQL Db2 interface ;;;; ;;;; This file is part of CLSQL. ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* (in-package #:clsql-db2) ;; ;; Opaque pointer types ;; (uffi:def-foreign-type cli-handle :pointer-void) (uffi:def-foreign-type cli-pointer :pointer-void) (uffi:def-foreign-type cli-char :byte) (uffi:def-foreign-type cli-ulen :unsigned-int) (uffi:def-foreign-type cli-len :int) (uffi:def-foreign-type cli-smallint :short) (uffi:def-foreign-type cli-usmallint :unsigned-short) (defvar +null-void-pointer+ (uffi:make-null-pointer :void)) (defvar +null-void-pointer-pointer+ (uffi:make-null-pointer :pointer-void)) ;;; Check an CLI return code for erroricity and signal a reasonably ;;; informative condition if so. ;;; ;;; ERRHP provides an error handle which can be used to find ;;; subconditions; if it's not provided, subcodes won't be checked. ;;; ;;; NULLS-OK says that a NULL-VALUE-RETURNED subcondition condition is ;;; normal and needn't cause any signal. An error handle is required ;;; to detect this subcondition, so it doesn't make sense to set ERRHP ;;; unless NULLS-OK is set. (defmacro def-cli-routine ((c-cli-symbol lisp-cli-fn) c-return &rest c-parms) (let ((ll (mapcar (lambda (x) (declare (ignore x)) (gensym)) c-parms))) `(let ((%lisp-cli-fn (uffi:def-function (,c-cli-symbol ,(intern (concatenate 'string "%" (symbol-name lisp-cli-fn)))) ,c-parms :returning ,c-return))) (defun ,lisp-cli-fn (,@ll &key database nulls-ok) (let ((result (funcall %lisp-cli-fn ,@ll))) (case result (#.SQL_SUCCESS SQL_SUCCESS) (#.SQL_SUCCESS_WITH_INFO (format *standard-output* "sucess with info") SQL_SUCCESS) (#.SQL_ERROR (error 'sql-database-error :error-id result :message (format nil "DB2 error" result))) (t (error 'sql-database-error :message (format nil "DB2 unknown error, code=~A" result))))))))) (defmacro def-raw-cli-routine ((c-cli-symbol lisp-cli-fn) c-return &rest c-parms) (let ((ll (mapcar (lambda (x) (declare (ignore x)) (gensym)) c-parms))) `(let ((%lisp-cli-fn (uffi:def-function (,c-cli-symbol ,(intern (concatenate 'string "%" (symbol-name lisp-cli-fn)))) ,c-parms :returning ,c-return))) (defun ,lisp-cli-fn (,@ll &key database nulls-ok) (funcall %lisp-cli-fn ,@ll))))) (def-cli-routine ("SQLAllocHandle" sql-alloc-handle) :int (fHandleType cli-smallint) (hInput cli-handle) (phOuput (* cli-handle))) (def-cli-routine ("SQLConnect" sql-connect) :int (hDb cli-handle) (server :cstring) (server-len cli-smallint) (user :cstring) (user-len cli-smallint) (password :cstring) (passwd-len cli-smallint)) ;;; CLI Functions needed ;;; SQLBindParameter ;;; SQLExecDirect ;;; SQLNumResultCols ;;; SQLDescribeCol ;;; SQLColAttribute ;;; SQLRowCount ;;; SQLBindCol ;;; SQLFetch ;;; SQLGetData ;;; SQLEndTran ;;; SQLFreeHandle ;;; SQLDisconnect ;;; SQLSetConnectAttr cl-sql-6.4.1/db-db2/db2-loader.lisp0000644000175000017500000000366611335067642015607 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; FILE IDENTIFICATION ;;;; ;;;; Name: db2-loader.lisp ;;;; Purpose: Foreign library loader for CLSQL Db2 interface ;;;; ;;;; This file is part of CLSQL. ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* (in-package #:clsql-db2) (defparameter *db2-lib-path* (let ((db2-home (getenv "DB2_HOME"))) (when db2-home (make-pathname :directory (append (pathname-directory (parse-namestring (concatenate 'string db2-home "/"))) (list "lib")))))) (defparameter *db2-library-filenames* (if *db2-lib-path* (list (merge-pathnames "libdb2" *db2-lib-path*) "libdb2") "libdb2")) (defvar *db2-supporting-libraries* '("c") "Used only by CMU. List of library flags needed to be passed to ld to load the Db2 client library succesfully. If this differs at your site, set to the right path before compiling or loading the system.") (defvar *db2-library-loaded* nil "T if foreign library was able to be loaded successfully") (defmethod clsql-sys:database-type-library-loaded ((database-type (eql :db2))) *db2-library-loaded*) (defmethod clsql-sys:database-type-load-foreign ((database-type (eql :db2))) (clsql-uffi:find-and-load-foreign-library *db2-library-filenames* :module "clsql-db2" :supporting-libraries *db2-supporting-libraries*) (setq *db2-library-loaded* t)) (clsql-sys:database-type-load-foreign :db2) cl-sql-6.4.1/db-postgresql-socket3/0000755000175000017500000000000012134026703016064 5ustar kevinkevincl-sql-6.4.1/db-postgresql-socket3/sql.lisp0000644000175000017500000003202211616055736017567 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; FILE IDENTIFICATION ;;;; ;;;; Name: postgresql-socket-sql.sql ;;;; Purpose: High-level PostgreSQL interface using socket ;;;; Authors: Kevin M. Rosenberg based on original code by Pierre R. Mai ;;;; Created: Feb 2002 ;;;; ;;;; $Id$ ;;;; ;;;; This file, part of CLSQL, is Copyright (c) 2002-2007 by Kevin M. Rosenberg ;;;; and Copyright (c) 1999-2001 by Pierre R. Mai ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* (in-package #:cl-user) (defpackage :clsql-postgresql-socket3 (:use #:common-lisp #:clsql-sys #:postgresql-socket3) (:export #:postgresql-socket3-database) (:documentation "This is the CLSQL socket interface (protocol version 3) to PostgreSQL.")) (in-package #:clsql-postgresql-socket3) (defvar *sqlreader* (cl-postgres:copy-sql-readtable)) (let ((dt-fn (lambda (useconds-since-2000) (let ((sec (truncate (/ useconds-since-2000 1000000))) (usec (mod useconds-since-2000 1000000))) (clsql:make-time :year 2000 :second sec :usec usec))))) (cl-postgres:set-sql-datetime-readers :table *sqlreader* :date (lambda (days-since-2000) (clsql:make-date :year 2000 :day (+ 1 days-since-2000))) :timestamp dt-fn :timestamp-with-timezone dt-fn)) ;; interface foreign library loading routines (clsql-sys:database-type-load-foreign :postgresql-socket3) (defmethod database-initialize-database-type ((database-type (eql :postgresql-socket3))) t) ;; Field type conversion (defun convert-to-clsql-warning (database condition) (ecase *backend-warning-behavior* (:warn (warn 'sql-database-warning :database database :message (cl-postgres:database-error-message condition))) (:error (error 'sql-database-error :database database :message (format nil "Warning upgraded to error: ~A" (cl-postgres:database-error-message condition)))) ((:ignore nil) ;; do nothing ))) (defun convert-to-clsql-error (database expression condition) (error 'sql-database-data-error :database database :expression expression :error-id (type-of condition) :message (cl-postgres:database-error-message condition))) (defmacro with-postgresql-handlers ((database &optional expression) &body body) (let ((database-var (gensym)) (expression-var (gensym))) `(let ((,database-var ,database) (,expression-var ,expression)) (handler-bind ((postgresql-warning (lambda (c) (convert-to-clsql-warning ,database-var c))) (cl-postgres:database-error (lambda (c) (convert-to-clsql-error ,database-var ,expression-var c)))) ,@body)))) (defclass postgresql-socket3-database (generic-postgresql-database) ((connection :accessor database-connection :initarg :connection :type cl-postgres:database-connection))) (defmethod database-type ((database postgresql-socket3-database)) :postgresql-socket3) (defmethod database-name-from-spec (connection-spec (database-type (eql :postgresql-socket3))) (check-connection-spec connection-spec database-type (host db user password &optional port options tty)) (destructuring-bind (host db user password &optional port options tty) connection-spec (declare (ignore password options tty)) (concatenate 'string (etypecase host (null "localhost") (pathname (namestring host)) (string host)) (when port (concatenate 'string ":" (etypecase port (integer (write-to-string port)) (string port)))) "/" db "/" user))) (defmethod database-connect (connection-spec (database-type (eql :postgresql-socket3))) (check-connection-spec connection-spec database-type (host db user password &optional port options tty)) (destructuring-bind (host db user password &optional (port +postgresql-server-default-port+) (options "") (tty "")) connection-spec (declare (ignore options tty)) (handler-case (handler-bind ((warning (lambda (c) (warn 'sql-warning :format-control "~A" :format-arguments (list (princ-to-string c)))))) (cl-postgres:open-database db user password host port)) (cl-postgres:database-error (c) ;; Connect failed (error 'sql-connection-error :database-type database-type :connection-spec connection-spec :error-id (type-of c) :message (cl-postgres:database-error-message c))) (:no-error (connection) ;; Success, make instance (make-instance 'postgresql-socket3-database :name (database-name-from-spec connection-spec database-type) :database-type :postgresql-socket3 :connection-spec connection-spec :connection connection))))) (defmethod database-disconnect ((database postgresql-socket3-database)) (cl-postgres:close-database (database-connection database)) t) (defvar *include-field-names* nil) ;; THE FOLLOWING MACRO EXPANDS TO THE FUNCTION BELOW IT, ;; BUT TO GET null CONVENTIONS CORRECT I NEEDED TO TWEAK THE EXPANSION ;; ;; (cl-postgres:def-row-reader clsql-default-row-reader (fields) ;; (values (loop :while (cl-postgres:next-row) ;; :collect (loop :for field :across fields ;; :collect (cl-postgres:next-field field))) ;; (when *include-field-names* ;; (loop :for field :across fields ;; :collect (cl-postgres:field-name field))))) (defun clsql-default-row-reader (stream fields) (declare (type stream stream) (type (simple-array cl-postgres::field-description) fields)) (flet ((cl-postgres:next-row () (cl-postgres::look-for-row stream)) (cl-postgres:next-field (cl-postgres::field) (declare (type cl-postgres::field-description cl-postgres::field)) (let ((cl-postgres::size (cl-postgres::read-int4 stream))) (declare (type (signed-byte 32) cl-postgres::size)) (if (eq cl-postgres::size -1) nil (funcall (cl-postgres::field-interpreter cl-postgres::field) stream cl-postgres::size))))) (let ((results (loop :while (cl-postgres:next-row) :collect (loop :for field :across fields :collect (cl-postgres:next-field field)))) (col-names (when *include-field-names* (loop :for field :across fields :collect (cl-postgres:field-name field))))) ;;multiple return values were not working here (list results col-names)))) (defmethod database-query ((expression string) (database postgresql-socket3-database) result-types field-names) (let ((connection (database-connection database)) (cl-postgres:*sql-readtable* *sqlreader*)) (with-postgresql-handlers (database expression) (let ((*include-field-names* field-names)) (apply #'values (cl-postgres:exec-query connection expression #'clsql-default-row-reader))) ))) (defmethod query ((obj command-object) &key (database *default-database*) (result-types :auto) (flatp nil) (field-names t)) (clsql-sys::record-sql-command (format nil "~&~A~&{Params: ~{~A~^, ~}}" (expression obj) (parameters obj)) database) (multiple-value-bind (rows names) (database-query obj database result-types field-names) (let ((result (if (and flatp (= 1 (length (car rows)))) (mapcar #'car rows) rows))) (clsql-sys::record-sql-result result database) (if field-names (values result names) result)))) (defmethod database-query ((obj command-object) (database postgresql-socket3-database) result-types field-names) (let ((connection (database-connection database)) (cl-postgres:*sql-readtable* *sqlreader*)) (with-postgresql-handlers (database obj) (let ((*include-field-names* field-names)) (unless (has-been-prepared obj) (cl-postgres:prepare-query connection (prepared-name obj) (expression obj)) (setf (has-been-prepared obj) T)) (apply #'values (cl-postgres:exec-prepared connection (prepared-name obj) (parameters obj) #'clsql-default-row-reader)))))) (defmethod database-execute-command ((expression string) (database postgresql-socket3-database)) (let ((connection (database-connection database))) (with-postgresql-handlers (database expression) ;; return row count? (second (multiple-value-list (cl-postgres:exec-query connection expression)))))) (defmethod execute-command ((obj command-object) &key (database *default-database*)) (clsql-sys::record-sql-command (expression obj) database) (let ((res (database-execute-command obj database))) (clsql-sys::record-sql-result res database) ;; return row count? res)) (defmethod database-execute-command ((obj command-object) (database postgresql-socket3-database)) (let ((connection (database-connection database))) (with-postgresql-handlers (database obj) (unless (has-been-prepared obj) (cl-postgres:prepare-query connection (prepared-name obj) (expression obj)) (setf (has-been-prepared obj) T)) (second (multiple-value-list (cl-postgres:exec-prepared connection (prepared-name obj) (parameters obj))))))) ;;;; Cursoring interface (defmethod database-query-result-set ((expression string) (database postgresql-socket3-database) &key full-set result-types) (declare (ignore result-types)) (declare (ignore full-set)) (error "Cursoring interface is not supported for postgresql-socket3-database try cl-postgres:exec-query with a custom row-reader")) (defmethod database-dump-result-set (result-set (database postgresql-socket3-database)) (error "Cursoring interface is not supported for postgresql-socket3-database try cl-postgres:exec-query with a custom row-reader") T) (defmethod database-store-next-row (result-set (database postgresql-socket3-database) list) (error "Cursoring interface is not supported for postgresql-socket3-database try cl-postgres:exec-query with a custom row-reader")) ;;;;;;;;;;;;;;;;;;;;;;;;;; (defmethod database-create (connection-spec (type (eql :postgresql-socket3))) (destructuring-bind (host name user password &optional port options tty) connection-spec (declare (ignore port options tty)) (let ((database (database-connect (list host "postgres" user password) type))) (setf (slot-value database 'clsql-sys::state) :open) (unwind-protect (database-execute-command (format nil "create database ~A" name) database) (database-disconnect database))))) (defmethod database-destroy (connection-spec (type (eql :postgresql-socket3))) (destructuring-bind (host name user password &optional port options tty) connection-spec (declare (ignore port options tty)) (let ((database (database-connect (list host "postgres" user password) type))) (setf (slot-value database 'clsql-sys::state) :open) (unwind-protect (database-execute-command (format nil "drop database ~A" name) database) (database-disconnect database))))) (defmethod database-probe (connection-spec (type (eql :postgresql-socket3))) (when (find (second connection-spec) (database-list connection-spec type) :test #'string-equal) t)) ;; Database capabilities (defmethod db-backend-has-create/destroy-db? ((db-type (eql :postgresql-socket3))) nil) (defmethod db-type-has-fancy-math? ((db-type (eql :postgresql-socket3))) t) (defmethod db-type-default-case ((db-type (eql :postgresql-socket3))) :lower) (defmethod database-underlying-type ((database postgresql-socket3-database)) :postgresql) (when (clsql-sys:database-type-library-loaded :postgresql-socket3) (clsql-sys:initialize-database-type :database-type :postgresql-socket3)) ;; Type munging functions (defmethod read-sql-value (val (type (eql 'boolean)) (database postgresql-socket3-database) db-type) (declare (ignore database db-type)) val) (defmethod read-sql-value (val (type (eql 'generalized-boolean)) (database postgresql-socket3-database) db-type) (declare (ignore database db-type)) val) cl-sql-6.4.1/db-postgresql-socket3/api.lisp0000644000175000017500000000440311616055736017543 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; FILE IDENTIFICATION ;;;; ;;;; Name: postgresql-socket-api.lisp ;;;; Purpose: Low-level PostgreSQL interface using sockets ;;;; Authors: Kevin M. Rosenberg based on original code by Pierre R. Mai ;;;; Created: Feb 2002 ;;;; ;;;; $Id$ ;;;; ;;;; This file, part of CLSQL, is Copyright (c) 2002-2004 by Kevin M. Rosenberg ;;;; and Copyright (c) 1999-2001 by Pierre R. Mai ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* (in-package #:postgresql-socket3) (defmethod clsql-sys:database-type-load-foreign ((database-type (eql :postgresql-socket3))) t) (defmethod clsql-sys:database-type-library-loaded ((database-type (eql :postgresql-socket3))) "T if foreign library was able to be loaded successfully. Always true for socket interface" t) (defparameter +postgresql-server-default-port+ 5432 "Default port of PostgreSQL server.") ;;;; Condition hierarchy (define-condition postgresql-condition (condition) ((connection :initarg :connection :reader postgresql-condition-connection) (message :initarg :message :reader postgresql-condition-message)) (:report (lambda (c stream) (format stream "~@<~A occurred on connection ~A. ~:@_Reason: ~A~:@>" (type-of c) (postgresql-condition-connection c) (postgresql-condition-message c))))) (define-condition postgresql-error (error postgresql-condition) ()) (define-condition postgresql-fatal-error (postgresql-error) ()) (define-condition postgresql-login-error (postgresql-fatal-error) ()) (define-condition postgresql-warning (warning postgresql-condition) ()) (define-condition postgresql-notification (postgresql-condition) () (:report (lambda (c stream) (format stream "~@" (postgresql-condition-connection c) (postgresql-condition-message c)))))cl-sql-6.4.1/db-postgresql-socket3/package.lisp0000644000175000017500000000231412021503403020340 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; FILE IDENTIFICATION ;;;; ;;;; Name: postgresql-socket-package.lisp ;;;; Purpose: Package definition for PostgreSQL interface using sockets ;;;; Programmers: Kevin M. Rosenberg ;;;; Date Started: Feb 2002 ;;;; ;;;; $Id$ ;;;; ;;;; This file, part of CLSQL, is Copyright (c) 2002 by Kevin M. Rosenberg ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* (in-package #:cl-user) #+lispworks (require "comm") (defpackage #:postgresql-socket3 (:use #:cl md5 #:cl-postgres) (:shadow #:postgresql-warning #:postgresql-notification) (:export #:+postgresql-server-default-port+ #:postgresql-condition #:postgresql-error #:postgresql-fatal-error #:postgresql-login-error #:postgresql-warning #:postgresql-notification #:postgresql-condition-message #:postgresql-condition-connection)) cl-sql-6.4.1/clsql-cffi.asd0000644000175000017500000000204011332141035014430 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; FILE IDENTIFICATION ;;;; ;;;; Name: clsql-cffi.asd ;;;; Purpose: ASDF System definition for CLSQL using CFFI-UFFI-COMPAT ;;;; Author: Kevin M. Rosenberg ;;;; Created: Jan 2010 ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* (push :clsql-cffi cl:*features*) (defpackage #:clsql-cffi-system (:use #:asdf #:cl)) (in-package #:clsql-cffi-system) (defsystem clsql-cffi :name "CLSQL-CFFI" :author "Kevin Rosenberg " :maintainer "Kevin M. Rosenberg " :licence "Lessor Lisp General Public License" :description "CLSQL using CFFI-UFFI-COMPAT interface" :depends-on (clsql) :components nil) cl-sql-6.4.1/clsql-postgresql-socket.asd0000644000175000017500000000317211332141035017221 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; FILE IDENTIFICATION ;;;; ;;;; Name: clsql-postgresql-socket.asd ;;;; Purpose: ASDF file for CLSQL PostgresSQL socket backend ;;;; Programmer: Kevin M. Rosenberg ;;;; Date Started: Aug 2002 ;;;; ;;;; This file, part of CLSQL, is Copyright (c) 2002 by Kevin M. Rosenberg ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* (defpackage #:clsql-postgresql-socket-system (:use #:asdf #:cl)) (in-package #:clsql-postgresql-socket-system) ;;; System definition (defsystem clsql-postgresql-socket :name "cl-sql-postgresql-socket" :author "Kevin M. Rosenberg " :maintainer "Kevin M. Rosenberg " :licence "Lessor Lisp General Public License" :description "Common Lisp SQL PostgreSQL Socket Driver" :long-description "cl-sql-postgresql-socket package provides a database driver to the PostgreSQL database via a socket interface." :depends-on (clsql md5 #-:clsql-cffi uffi #+:clsql-cffi cffi-uffi-compat #+sbcl sb-bsd-sockets) :components ((:module :db-postgresql-socket :components ((:file "postgresql-socket-package") (:file "postgresql-socket-api" :depends-on ("postgresql-socket-package")) (:file "postgresql-socket-sql" :depends-on ("postgresql-socket-api")))))) cl-sql-6.4.1/Makefile.common0000644000175000017500000000202211336541306014654 0ustar kevinkevinUNAME=$(shell uname) UNAME_A=$(shell uname -a) DARWIN_LIBC=$(shell file /usr/lib/libc.dylib) OS_AIX=$(shell expr "$(UNAME)" : '.*AIX.*') OS_SUNOS=$(shell expr "$(UNAME)" : '.*SunOS.*') OS_DARWIN=$(shell expr "$(UNAME)" : '.*Darwin.*') ifneq ($(OS_DARWIN),0) OS_DARWIN64=$(shell expr "$(DARWIN_LIBC)" : '.*x86_64.*') else OS_DARWIN64=0 endif OS_CYGWIN=$(shell expr "$(UNAME)" : '.*CYGWIN.*') OS_LINUX=$(shell expr "$(UNAME)" : '.*Linux.*') OS_LINUX64=$(shell expr "$(UNAME_A)" : '.*Linux.*x86_64.*') all: .PHONY: clean clean: @rm -rf .bin @rm -f *.ufsl *.fsl *.fas *.x86f *.sparcf *.fasl *.pfsl *.dfsl @rm -f *.fasla8 *.fasla16 *.faslm8 *.faslm16 *.faslmt @rm -f *~ *.bak *.orig *.err \#*\# .#* @rm -f *.so *.a @rm -rf debian/cl-sql ifneq ($(SUBDIRS)$(DOCSUBDIRS),) @set -e; for i in $(SUBDIRS) $(DOCSUBDIRS); do \ $(MAKE) -C $$i $@; done endif distclean: clean ifneq ($(SUBDIRS)$(DOCSUBDIRS),) @set -e; for i in $(SUBDIRS) $(DOCSUBDIRS); do \ $(MAKE) -C $$i $@; done endif .SUFFIXES: # No default suffixes cl-sql-6.4.1/COPYING.USQL0000644000175000017500000000260310667176647013572 0ustar kevinkevinCopyright (c) 1999 - 2003 onShore Development, Inc. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. cl-sql-6.4.1/NEWS0000644000175000017500000000303110672770675012444 0ustar kevinkevinSep 14 2006 ----------- Version 4.0.0 release with incompatible backward change: - using ANSI mode for MySQL backend - reducing case changes in SQL output for symbols which will have an effect for users of mlisp (Allegro "Modern" Lisp) . - Add support for generating quoted strings in SQL output when specifying table names as strings rather than symbols. This may have an effect on applications that use strings as table names and use inconsistent case in the table names. Previously, those varying case strings would be mapped to a canonical case unquoted SQL output. But to accomodate users which need to specify case in table names, this mapping has been removed. See ChangeLog entry for details. Dec 30 2006 ----------- Version 3.8.0 released with incompatible backward change. See the ChangeLog entry for details. Aug 3 2006 ---------- CLSQL 3.0 has been released. The 3.0 release of CLSQL is a major rewrite compared to version 2.0. New features include: - Full CommonSQL backward compatibility with native documentation while retaining and adding many improvements beyond the CommonSQL standard. - Extensive (233 tests) regression suite - Addition of ODBC and Oracle backends I wish to acknowledge Marcus Pearce's significant contribution to this release. He has performed the initial port of Uncommonsql to CLSQL as well as the initial regression suite and most of the new documentation. He has contributed to many of the re-design decisions and new code for CLSQL. CLSQL's home is http://clsql.b9.com Enjoy! Kevin Rosenberg cl-sql-6.4.1/clsql-odbc.asd0000644000175000017500000000310111332141035014427 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; FILE IDENTIFICATION ;;;; ;;;; Name: clsql-odbc.asd ;;;; Purpose: ASDF definition file for CLSQL ODBC backend ;;;; Author: Kevin M. Rosenberg ;;;; Created: April 2004 ;;;; ;;;; This file, part of CLSQL, is Copyright (c) 200d42 by Kevin M. Rosenberg ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* (defpackage #:clsql-odbc-system (:use #:asdf #:cl)) (in-package #:clsql-odbc-system) (defsystem clsql-odbc :name "clsql-odbc" :author "Kevin M. Rosenberg " :maintainer "Kevin M. Rosenberg " :licence "Lessor Lisp General Public License" :description "Common Lisp SQL ODBC Driver" :long-description "cl-sql-odbc package provides a database driver to the ODBC database system." :depends-on (clsql clsql-uffi) :components ((:module :db-odbc :components ((:file "odbc-package") (:file "odbc-loader" :depends-on ("odbc-package")) (:file "odbc-constants" :depends-on ("odbc-loader")) (:file "odbc-ff-interface" :depends-on ("odbc-constants")) (:file "odbc-api" :depends-on ("odbc-ff-interface" "odbc-constants")) (:file "odbc-dbi" :depends-on ("odbc-api")) (:file "odbc-sql" :depends-on ("odbc-dbi")))))) cl-sql-6.4.1/BUGS0000644000175000017500000000241111746263021012412 0ustar kevinkevin1. SBCL/Postgresql Interaction Gabor Melis reported an interaction with SBCL and the postgresql database backend using a multithreaded program and Portable AllegroServe. It appears that libpg installs its own SIGPIPE handler. When a multithreaded program servicing socket requests has SIGPIPE conditions thrown, the running SBCL instance is killed. The web page http://linux.com.hk/docs/postgresql/libpq-threading.html has more information about libpq's SIGPIPE handler. 2. Object joining Aleksandar Bakic reported the documentation says that :home-key and :foreign-key properties of the :db-info property may contain lists of symbols. However, update-objects-joins fails in such cases. 2. configure file Automatically generate makefiles based on the configuration of an end-users system 3. SBCL/MySQL interaction Similar to the postgres interaction noted above SBCL installs its own SIGPIPE handler but the mysql library disables it breaking thread interrupts. See also http://ccl.clozure.com/irc-logs/lisp/2012-02/lisp-2012.02.22.txt Look for the conversation starting at 20:03:32 between bobbysmith007 and pkhuong. 4. Thread safety issues. While clsql attempts to be threadsafe there are some significant issues with some backends. See doc/threading-warnings.txt for more info. cl-sql-6.4.1/COPYING.MaiSQL0000644000175000017500000000242510667176647014076 0ustar kevinkevin Copyright (C) 1999-2001 Pierre R. Mai Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Except as contained in this notice, the name of the author shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from the author. cl-sql-6.4.1/sql/0000755000175000017500000000000012134026703012524 5ustar kevinkevincl-sql-6.4.1/sql/recording.lisp0000644000175000017500000001647511577723403015421 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; ;;;; CLSQL broadcast streams which can be used to monitor the ;;;; flow of commands to, and results from, a database. ;;;; ;;;; This file is part of CLSQL. ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* (in-package #:clsql-sys) (defun start-sql-recording (&key (type :commands) (database *default-database*)) "Starts recording of SQL commands sent to and/or results returned from DATABASE which defaults to *DEFAULT-DATABASE*. The SQL is output on one or more broadcast streams, initially just *STANDARD-OUTPUT*, and the functions ADD-SQL-STREAM and DELETE-SQL-STREAM may be used to add or delete command or result recording streams. The default value of TYPE is :commands which means that SQL commands sent to DATABASE are recorded. If TYPE is :results then SQL results returned from DATABASE are recorded. Both commands and results may be recorded by passing TYPE value of :both." (when (or (eq type :both) (eq type :commands)) (setf (command-recording-stream database) (make-broadcast-stream *standard-output*))) (when (or (eq type :both) (eq type :results)) (setf (result-recording-stream database) (make-broadcast-stream *standard-output*))) (values)) (defun stop-sql-recording (&key (type :commands) (database *default-database*)) "Stops recording of SQL commands sent to and/or results returned from DATABASE which defaults to *DEFAULT-DATABASE*. The default value of TYPE is :commands which means that SQL commands sent to DATABASE will no longer be recorded. If TYPE is :results then SQL results returned from DATABASE will no longer be recorded. Recording may be stopped for both commands and results by passing TYPE value of :both." (when (or (eq type :both) (eq type :commands)) (setf (command-recording-stream database) nil)) (when (or (eq type :both) (eq type :results)) (setf (result-recording-stream database) nil)) (values)) (defun sql-recording-p (&key (type :commands) (database *default-database*)) "Predicate to test whether the SQL recording specified by TYPE is currently enabled for DATABASE which defaults to *DEFAULT-DATABASE*. TYPE may be one of :commands, :results, :both or :either, defaulting to :commands, otherwise nil is returned." (when (or (and (eq type :commands) (command-recording-stream database)) (and (eq type :results) (result-recording-stream database)) (and (eq type :both) (result-recording-stream database) (command-recording-stream database)) (and (eq type :either) (or (result-recording-stream database) (command-recording-stream database)))) t)) (defun add-sql-stream (stream &key (type :commands) (database *default-database*)) "Adds the supplied stream STREAM (or T for *standard-output*) as a component of the recording broadcast stream for the SQL recording type specified by TYPE on DATABASE which defaults to *DEFAULT-DATABASE*. TYPE must be one of :commands, :results, or :both, defaulting to :commands, depending on whether the stream is to be added for recording SQL commands, results or both." (when (or (eq type :both) (eq type :commands)) (unless (member stream (list-sql-streams :type :commands :database database)) (setf (command-recording-stream database) (apply #'make-broadcast-stream (cons stream (list-sql-streams :type :commands :database database)))))) (when (or (eq type :both) (eq type :results)) (unless (member stream (list-sql-streams :type :results :database database)) (setf (result-recording-stream database) (apply #'make-broadcast-stream (cons stream (list-sql-streams :type :results :database database)))))) stream) (defun delete-sql-stream (stream &key (type :commands) (database *default-database*)) "Removes the supplied stream STREAM from the recording broadcast stream for the SQL recording type specified by TYPE on DATABASE which defaults to *DEFAULT-DATABASE*. TYPE must be one of :commands, :results, or :both, defaulting to :commands, depending on whether the stream is to be added for recording SQL commands, results or both." (when (or (eq type :both) (eq type :commands)) (setf (command-recording-stream database) (apply #'make-broadcast-stream (remove stream (list-sql-streams :type :commands :database database))))) (when (or (eq type :both) (eq type :results)) (setf (result-recording-stream database) (apply #'make-broadcast-stream (remove stream (list-sql-streams :type :results :database database))))) stream) (defun list-sql-streams (&key (type :commands) (database *default-database*)) "Returns the list of component streams for the broadcast stream recording SQL commands sent to and/or results returned from DATABASE which defaults to *DEFAULT-DATABASE*. TYPE must be one of :commands, :results, or :both, defaulting to :commands, and determines whether the listed streams contain those recording SQL commands, results or both." (let ((crs (command-recording-stream database)) (rrs (result-recording-stream database))) (cond ((eq type :commands) (when crs (broadcast-stream-streams crs))) ((eq type :results) (when rrs (broadcast-stream-streams rrs))) ((eq type :both) (append (when crs (broadcast-stream-streams crs)) (when rrs (broadcast-stream-streams rrs)))) (t (error "Unknown recording type. ~A" type))))) (defun sql-stream (&key (type :commands) (database *default-database*)) "Returns the broadcast stream used for recording SQL commands sent to or results returned from DATABASE which defaults to *DEFAULT-DATABASE*. TYPE must be one of :commands or :results, defaulting to :commands, and determines whether the stream returned is that used for recording SQL commands or results." (cond ((eq type :commands) (command-recording-stream database)) ((eq type :results) (result-recording-stream database)) (t (error "Unknown recording type. ~A" type)))) (defun record-sql-command (expr database) (when database (with-slots (command-recording-stream) database (when command-recording-stream (format command-recording-stream "~&;; ~A ~A => ~A~%" (iso-timestring (get-time)) (database-name database) expr))))) (defun record-sql-result (res database) (when database (with-slots (result-recording-stream) database (when result-recording-stream (format result-recording-stream "~&;; ~A ~A <= ~A~%" (iso-timestring (get-time)) (database-name database) res))))) cl-sql-6.4.1/sql/db-interface.lisp0000644000175000017500000005117411577723152015764 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; FILE IDENTIFICATION ;;;; ;;;; Name: db-interface.lisp ;;;; Purpose: Generic function definitions for DB interfaces ;;;; Programmers: Kevin M. Rosenberg based on ;;;; Original code by Pierre R. Mai. Additions from ;;;; onShoreD to support UncommonSQL front-end ;;;; Date Started: Feb 2002 ;;;; ;;;; This file, part of CLSQL, is Copyright (c) 2002-2010 by Kevin M. Rosenberg ;;;; and Copyright (c) 1999-2001 by Pierre R. Mai, and onShoreD ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* (in-package #:clsql-sys) (defgeneric database-type-load-foreign (database-type) (:documentation "The internal generic implementation of reload-database-types.")) (defgeneric database-type-library-loaded (database-type) (:documentation "The internal generic implementation for checking if database type library loaded successfully.")) (defgeneric database-initialize-database-type (database-type) (:documentation "The internal generic implementation of initialize-database-type.")) (defgeneric database-name-from-spec (connection-spec database-type) (:documentation "Returns the name of the database that would be created if connect was called with the connection-spec.")) (defgeneric database-connect (connection-spec database-type) (:documentation "Internal generic implementation of connect.")) (defgeneric database-reconnect (database) (:method ((database t)) (signal-no-database-error database)) (:documentation "Internal generic implementation of reconnect.")) (defgeneric database-disconnect (database) (:method ((database t)) (signal-no-database-error database)) (:documentation "Internal generic implementation of disconnect.")) (defgeneric database-query (query-expression database result-types field-names) (:method (query-expression (database t) result-types field-names) (declare (ignore query-expression result-types field-names)) (signal-no-database-error database)) (:method (query-expression (database database) result-types field-names) (declare (ignore query-expression result-types field-names)) (warn "database-query not implemented for database type ~A." (database-type database))) (:documentation "Internal generic implementation of query.")) (defgeneric database-execute-command (sql-expression database) (:method (sql-expression (database t)) (declare (ignore sql-expression)) (signal-no-database-error database)) (:method (sql-expression (database database)) (declare (ignore sql-expression)) (warn "database-execute-command not implemented for database type ~A." (database-type database))) (:documentation "Internal generic implementation of execute-command.")) ;;; Mapping and iteration (defgeneric database-query-result-set (query-expression database &key full-set result-types) (:method (query-expression (database t) &key full-set result-types) (declare (ignore query-expression full-set result-types)) (signal-no-database-error database) (values nil nil nil)) (:method (query-expression (database database) &key full-set result-types) (declare (ignore query-expression full-set result-types)) (warn "database-query-result-set not implemented for database type ~A." (database-type database)) (values nil nil nil)) (:documentation "Internal generic implementation of query mapping. Starts the query specified by query-expression on the given database and returns a result-set to be used with database-store-next-row and database-dump-result-set to access the returned data. The second value is the number of columns in the result-set, if there are any. If full-set is true, the number of rows in the result-set is returned as a third value, if this is possible (otherwise nil is returned for the third value). This might have memory and resource usage implications, since many databases will require the query to be executed in full to answer this question. If the query produced no results then nil is returned for all values that would have been returned otherwise. If an error occurs during query execution, the function should signal a sql-database-data-error.")) (defgeneric database-dump-result-set (result-set database) (:method (result-set (database t)) (declare (ignore result-set)) (signal-no-database-error database)) (:method (result-set (database database)) (declare (ignore result-set)) (warn "database-dump-result-set not implemented for database type ~A." (database-type database))) (:documentation "Dumps the received result-set.")) (defgeneric database-store-next-row (result-set database list) (:method (result-set (database t) list) (declare (ignore result-set list)) (signal-no-database-error database)) (:method (result-set (database database) list) (declare (ignore result-set list)) (warn "database-store-next-row not implemented for database type ~A." (database-type database))) (:documentation "Returns t and stores the next row in the result set in list or returns nil when result-set is finished.")) (defgeneric database-create (connection-spec type) (:documentation "Creates a database, returns T if successfull or signals an error.")) (defgeneric database-probe (connection-spec type) (:method (spec type) (declare (ignore spec)) (warn "database-probe not support for database-type ~A." type)) (:documentation "Probes for the existence of a database, returns T if database found or NIL if not found. May signal an error if unable to communicate with database server.")) (defgeneric database-list (connection-spec type) (:method (spec type) (declare (ignore spec)) (warn "database-list not support for database-type ~A." type)) (:documentation "Lists all databases found for TYPE. May signal an error if unable to communicate with database server.")) (defgeneric database-truncate (database) (:method ((database t)) (signal-no-database-error database)) (:documentation "Remove all data from database.")) (defgeneric database-destroy (connection-spec type) (:documentation "Destroys (drops) a database, returns T if successfull or signals an error if unable to destory.")) (defgeneric database-create-sequence (name database) (:documentation "Create a sequence in DATABASE.")) (defgeneric database-drop-sequence (name database) (:documentation "Drop a sequence from DATABASE.")) (defgeneric database-sequence-next (name database) (:documentation "Increment a sequence in DATABASE.")) (defgeneric database-list-sequences (database &key owner) (:documentation "List all sequences in DATABASE.")) (defgeneric database-set-sequence-position (name position database) (:documentation "Set the position of the sequence called NAME in DATABASE.")) (defgeneric database-sequence-last (name database) (:documentation "Select the last value in sequence NAME in DATABASE.")) (defgeneric database-last-autoincrement-id (database table column) (:documentation "Many databases have the notion of an auto-increment id; i.e. a sequence implicitly on a table. This function should return that ID." )) (defgeneric database-start-transaction (database) (:documentation "Start a transaction in DATABASE.") (:method ((database t)) (signal-no-database-error database))) (defgeneric database-commit-transaction (database) (:documentation "Commit current transaction in DATABASE.") (:method ((database t)) (signal-no-database-error database))) (defgeneric database-abort-transaction (database) (:documentation "Abort current transaction in DATABASE.") (:method ((database t)) (signal-no-database-error database))) (defgeneric database-get-type-specifier (type args database db-underlying-type) (:documentation "Return the type SQL type specifier as a string, for the given lisp type and parameters.")) (defgeneric database-list-tables (database &key owner) (:documentation "List all tables in the given database") (:method ((database database) &key owner) (declare (ignore owner)) (warn "database-list-tables not implemented for database type ~A." (database-type database))) (:method ((database t) &key owner) (declare (ignore owner)) (signal-no-database-error database))) (defgeneric database-list-tables-and-sequences (database &key owner) (:documentation "List all tables in the given database, may include seqeneces") (:method ((database t) &key owner) (declare (ignore owner)) (signal-no-database-error database)) (:method ((database database) &key owner) (database-list-tables database :owner owner))) (defgeneric database-list-views (database &key owner) (:documentation "List all views in the DATABASE.") (:method ((database database) &key owner) (declare (ignore owner)) (warn "database-list-views not implemented for database type ~A." (database-type database))) (:method ((database t) &key owner) (declare (ignore owner)) (signal-no-database-error database))) (defgeneric database-list-indexes (database &key owner) (:documentation "List all indexes in the DATABASE.") (:method ((database database) &key owner) (declare (ignore owner)) (warn "database-list-indexes not implemented for database type ~A." (database-type database))) (:method ((database t) &key owner) (declare (ignore owner)) (signal-no-database-error database))) (defgeneric database-list-table-indexes (table database &key owner) (:documentation "List all indexes for a table in the DATABASE.") (:method (table (database database) &key owner) (declare (ignore table owner)) (warn "database-list-table-indexes not implemented for database type ~A." (database-type database))) (:method (table (database t) &key owner) (declare (ignore table owner)) (signal-no-database-error database))) (defgeneric database-list-attributes (table database &key owner) (:documentation "List all attributes in TABLE.") (:method (table (database database) &key owner) (declare (ignore table owner)) (warn "database-list-attributes not implemented for database type ~A." (database-type database))) (:method (table (database t) &key owner) (declare (ignore table owner)) (signal-no-database-error database))) (defgeneric database-attribute-type (attribute table database &key owner) (:documentation "Return the type of ATTRIBUTE in TABLE. Returns multiple values of TYPE_NAME (keyword) PRECISION SCALE NULLABLE.") (:method (attribute table (database database) &key owner) (declare (ignore attribute table owner)) (warn "database-list-attribute-type not implemented for database type ~A." (database-type database))) (:method (attribute table (database t) &key owner) (declare (ignore attribute table owner)) (signal-no-database-error database))) (defgeneric database-add-attribute (table attribute database) (:documentation "Add the attribute to the table.") (:method (table attribute (database database)) (declare (ignore table attribute)) (warn "database-add-attribute not implemented for database type ~A." (database-type database))) (:method (table attribute (database t)) (declare (ignore table attribute)) (signal-no-database-error database))) (defgeneric database-rename-attribute (table oldatt newname database) (:documentation "Rename the attribute in the table to NEWNAME.") (:method (table oldatt newname (database database)) (declare (ignore table oldatt newname)) (warn "database-rename-attribute not implemented for database type ~A." (database-type database))) (:method (table oldatt newname (database t)) (declare (ignore table oldatt newname)) (signal-no-database-error database))) (defgeneric oid (object) (:documentation "Return the unique ID of a database object.")) ;;; Database backend capabilities (defgeneric database-underlying-type (database) (:method (database) (database-type database)) (:documentation "Returns the type of the underlying database. For ODBC, needs to query ODBC driver.")) (defgeneric db-type-use-column-on-drop-index? (db-type) (:method (db-type) (declare (ignore db-type)) nil) (:documentation "NIL [default] if database-type does not use column name on DROP INDEX.")) (defgeneric db-type-use-fully-qualified-column-on-drop-index? (db-type) (:method (db-type) (declare (ignore db-type)) nil) (:documentation "NIL [default] if database-type does not require fully qualified column name on DROP INDEX.")) (defgeneric db-type-has-views? (db-type) (:method (db-type) (declare (ignore db-type)) ;; SQL92 has views t) (:documentation "T [default] if database-type supports views.")) (defgeneric db-type-has-bigint? (db-type) (:method (db-type) (declare (ignore db-type)) ;; SQL92 has bigint t) (:documentation "T [default] if database-type supports bigint.")) (defgeneric db-type-default-case (db-type) (:method (db-type) (declare (ignore db-type)) ;; By default, CommonSQL converts identifiers to UPPER case. :upper) (:documentation ":upper [default] if means identifiers mapped to UPPER case SQL like CommonSQL API. However, Postgresql maps identifiers to lower case, so PostgreSQL uses a value of :lower for this result.")) (defgeneric db-type-has-fancy-math? (db-type) (:method (db-type) (declare (ignore db-type)) nil) (:documentation "NIL [default] if database-type does not have fancy math.")) (defgeneric db-type-has-subqueries? (db-type) (:method (db-type) (declare (ignore db-type)) t) (:documentation "T [default] if database-type supports views.")) (defgeneric db-type-has-boolean-where? (db-type) (:method (db-type) (declare (ignore db-type)) ;; SQL99 has boolean where t) (:documentation "T [default] if database-type supports boolean WHERE clause, such as 'WHERE MARRIED'.")) (defgeneric db-type-has-union? (db-type) (:method (db-type) (declare (ignore db-type)) t) (:documentation "T [default] if database-type supports boolean UNION.")) (defgeneric db-backend-has-create/destroy-db? (db-type) (:method (db-type) (declare (ignore db-type)) t) (:documentation "T [default] if backend can destroy and create databases.")) (defgeneric db-type-transaction-capable? (db database) (:method (db database) (declare (ignore db database)) t) (:documentation "T [default] if database can supports transactions.")) (defgeneric db-type-has-prepared-stmt? (db-type) (:method ((db-type t)) nil) (:documentation "T if database backend supports prepared statements.")) (defgeneric db-type-has-intersect? (db-type) (:method (db-type) (declare (ignore db-type)) t) (:documentation "T [default] if database-type supports INTERSECT.")) (defgeneric db-type-has-except? (db-type) (:method (db-type) (declare (ignore db-type)) t) (:documentation "T [default] if database-type supports EXCEPT.")) (defgeneric db-type-has-auto-increment? (db-type) (:method (db-type) (declare (ignore db-type) nil)) (:documentation "NIL [default] if database-type supports auto-incrementing columns.")) ;;; Large objects support (Marc Battyani) (defgeneric database-create-large-object (database) (:documentation "Creates a new large object in the database and returns the object identifier")) (defgeneric database-write-large-object (object-id data database) (:documentation "Writes data to the large object")) (defgeneric database-read-large-object (object-id database) (:documentation "Reads the large object content")) (defgeneric database-delete-large-object (object-id database) (:documentation "Deletes the large object in the database")) ;; Prepared statements (defgeneric database-prepare (stmt types database result-types field-names) (:method (stmt types (database t) result-types field-names) (declare (ignore stmt types result-types field-names)) (signal-no-database-error database)) (:method (stmt types (database database) result-types field-names) (declare (ignore stmt types result-types field-names)) (error 'sql-database-error :message (format nil "DATABASE-PREPARE not implemented for ~S" database))) (:documentation "Prepare a statement for later execution.")) (defgeneric database-bind-parameter (prepared-stmt position value) (:method ((pstmt t) position value) (declare (ignore position value)) (error 'sql-database-error :message (format nil "database-bind-paremeter not implemented for ~S" pstmt))) (:documentation "Bind a parameter for a prepared statement.")) (defgeneric database-run-prepared (prepared-stmt) (:method ((pstmt t)) (error 'sql-database-error :message (format nil "database-run-prepared not specialized for ~S" pstmt))) (:documentation "Execute a prepared statement.")) (defgeneric database-free-prepared (prepared-stmt) (:method ((pstmt t)) ;; nothing to do by default nil) (:documentation "Free the resources of a prepared statement.")) (defgeneric database-acquire-from-conn-pool (database) (:documentation "Acquire a database connection from the pool. This is a chance to test the connection for validity before returning it to the user. If this function returns NIL or throws an error that database connection is considered bad and we make a new one. Database objects have a chance to specialize, otherwise the default method uses the database-underlying-type and tries to do something appropriate.")) (defgeneric database-release-to-conn-pool (database) (:documentation "Chance for the database to cleanup before it is returned to the connection pool.")) ;; Checks for closed database (defmethod database-disconnect :before ((database database)) (unless (is-database-open database) (signal-closed-database-error database))) (defmethod database-query :before (query-expression (database database) result-set field-names) (declare (ignore query-expression result-set field-names)) (unless (is-database-open database) (signal-closed-database-error database))) (defmethod database-execute-command :before (sql-expression (database database)) (declare (ignore sql-expression)) (unless (is-database-open database) (signal-closed-database-error database))) (defmethod database-query-result-set :before (expr (database database) &key full-set result-types) (declare (ignore expr full-set result-types)) (unless (is-database-open database) (signal-closed-database-error database))) (defmethod database-dump-result-set :before (result-set (database database)) (declare (ignore result-set)) (unless (is-database-open database) (signal-closed-database-error database))) (defmethod database-store-next-row :before (result-set (database database) list) (declare (ignore result-set list)) (unless (is-database-open database) (signal-closed-database-error database))) (defmethod database-commit-transaction :before ((database database)) (unless (is-database-open database) (signal-closed-database-error database))) (defmethod database-start-transaction :before ((database database)) (unless (is-database-open database) (signal-closed-database-error database))) (defmethod database-abort-transaction :before ((database database)) (unless (is-database-open database) (signal-closed-database-error database))) (defvar *foreign-library-search-paths* nil "A list of pathnames denoting directories where CLSQL will look for foreign libraries \(in addition to the default places).") (defun push-library-path (path) "Adds the pathspec PATH \(which should denote a directory) to the list *FOREIGN-LIBRARY-SEARCH-PATHS*." (pushnew path *foreign-library-search-paths* :test #'equal)) cl-sql-6.4.1/sql/generic-odbc.lisp0000644000175000017500000002537011636413404015751 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; ;;;; Generic ODBC layer, used by db-odbc and db-aodbc backends ;;;; ;;;; This file is part of CLSQL. ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* (in-package #:clsql-sys) (defclass generic-odbc-database (database) ((dbi-package :initarg :dbi-package :reader dbi-package) (odbc-conn :initarg :odbc-conn :initform nil :accessor odbc-conn) (disconnect-fn :reader disconnect-fn) (sql-fn :reader sql-fn) (close-query-fn :reader close-query-fn) (fetch-row :reader fetch-row-fn) (list-all-database-tables-fn :reader list-all-database-tables-fn) (list-all-table-columns-fn :reader list-all-table-columns-fn)) (:documentation "Encapsulate same behavior across odbc and aodbc backends.")) (defmethod initialize-instance :after ((db generic-odbc-database) &rest all-keys) (declare (ignore all-keys)) (unless (slot-boundp db 'dbi-package) (error "dbi-package not specified.")) (let ((pkg (slot-value db 'dbi-package))) (unless pkg (error "dbi-package is nil.")) (setf (slot-value db 'disconnect-fn) (intern (symbol-name '#:disconnect) pkg) (slot-value db 'sql-fn) (intern (symbol-name '#:sql) pkg) (slot-value db 'close-query-fn) (intern (symbol-name '#:close-query) pkg) (slot-value db 'fetch-row) (intern (symbol-name '#:fetch-row) pkg) (slot-value db 'list-all-database-tables-fn) (intern (symbol-name '#:list-all-database-tables) pkg) (slot-value db 'list-all-table-columns-fn) (intern (symbol-name '#:list-all-table-columns) pkg)))) ;;; Object methods (defmethod read-sql-value (val (type (eql 'boolean)) (database generic-odbc-database) (db-type (eql :postgresql))) (if (string= "0" val) nil t)) (defmethod read-sql-value (val (type (eql 'generalized-boolean)) (database generic-odbc-database) (db-type (eql :postgresql))) (if (string= "0" val) nil t)) (defmethod read-sql-value (val (type (eql 'boolean)) database (db-type (eql :mssql))) (declare (ignore database)) (etypecase val (string (if (string= "0" val) nil t)) (integer (if (zerop val) nil t)))) (defmethod read-sql-value (val (type (eql 'generalized-boolean)) database (db-type (eql :mssql))) (declare (ignore database)) (etypecase val (string (if (string= "0" val) nil t)) (integer (if (zerop val) nil t)))) ;;; Type methods (defmethod database-get-type-specifier ((type (eql 'wall-time)) args database (db-type (eql :mssql))) (declare (ignore args database)) "DATETIME") (defmethod database-get-type-specifier ((type (eql 'date)) args database (db-type (eql :mssql))) (declare (ignore args database)) "SMALLDATETIME") (defmethod database-get-type-specifier ((type (eql 'boolean)) args database (db-type (eql :mssql))) (declare (ignore args database)) "BIT") (defmethod database-get-type-specifier ((type (eql 'generalized-boolean)) args database (db-type (eql :mssql))) (declare (ignore args database)) "BIT") ;;; Generation of SQL strings from lisp expressions (defmethod database-output-sql ((tee (eql t)) (database generic-odbc-database)) (case (database-underlying-type database) (:mssql "1") (t "'Y'"))) (defmethod database-output-sql-as-type ((type (eql 'boolean)) val database (db-type (eql :mssql))) (declare (ignore database)) (if val 1 0)) (defmethod database-output-sql-as-type ((type (eql 'generalized-boolean)) val database (db-type (eql :mssql))) (declare (ignore database)) (if val 1 0)) ;;; Database backend capabilities (defmethod db-type-use-fully-qualified-column-on-drop-index? ((db-type (eql :mssql))) t) (defmethod db-type-has-boolean-where? ((db-type (eql :mssql))) nil) (defmethod db-type-has-intersect? ((db-type (eql :mssql))) nil) (defmethod db-type-has-except? ((db-type (eql :mssql))) nil) ;;; Backend methods (defmethod database-disconnect ((database generic-odbc-database)) (funcall (disconnect-fn database) (odbc-conn database)) (setf (odbc-conn database) nil) t) (defmethod database-query (query-expression (database generic-odbc-database) result-types field-names) (handler-case (funcall (sql-fn database) query-expression :db (odbc-conn database) :result-types result-types :column-names field-names) #+ignore (error () (error 'sql-database-data-error :database database :expression query-expression :message "Query failed")))) (defmethod database-execute-command (sql-expression (database generic-odbc-database)) (handler-case (funcall (sql-fn database) sql-expression :db (odbc-conn database)) #+ignore (sql-error (e) (error e)) #+ignore (error () (error 'sql-database-data-error :database database :expression sql-expression :message "Execute command failed")))) (defstruct odbc-result-set (query nil) (types nil) (full-set nil :type boolean)) (defmethod database-query-result-set ((query-expression string) (database generic-odbc-database) &key full-set result-types) (handler-case (multiple-value-bind (query column-names) (funcall (sql-fn database) query-expression :db (odbc-conn database) :row-count nil :column-names t :query t :result-types result-types) (values (make-odbc-result-set :query query :full-set full-set :types result-types) (length column-names) nil ;; not able to return number of rows with odbc )) (error () (error 'sql-database-data-error :database database :expression query-expression :message "Query result set failed")))) (defmethod database-dump-result-set (result-set (database generic-odbc-database)) (funcall (close-query-fn database) (odbc-result-set-query result-set)) t) (defmethod database-store-next-row (result-set (database generic-odbc-database) list) (let ((row (funcall (fetch-row-fn database) (odbc-result-set-query result-set) nil 'eof))) (if (eq row 'eof) nil (progn (loop for elem in row for rest on list do (setf (car rest) elem)) list)))) (defun %database-list-* (database type owner) "Internal function used by database-list-tables and database-list-views" (multiple-value-bind (rows col-names) (funcall (list-all-database-tables-fn database) :db (odbc-conn database)) (declare (ignore col-names)) ;; http://msdn.microsoft.com/en-us/library/ms711831%28VS.85%29.aspx ;; TABLE_SCHEM is hard-coded in second column by ODBC Driver Manager ;; TABLE_NAME in third column, TABLE_TYPE in fourth column (loop for (category schema name ttype . rest) in rows when (and (string-equal type ttype) (or (null owner) (string-equal owner schema)) ;; unless requesting by name, skip system schema (not (and (null owner) (member schema '("information_schema" "sys") :test #'string-equal))) ;; skip system specific tables in mssql2000 (not (and (eql :mssql (database-underlying-type database)) (member name '("dtproperties" "sysconstraints" "syssegments") :test #'string-equal)))) collect name))) (defmethod database-list-tables ((database generic-odbc-database) &key (owner nil)) "Since ODBC doesn't expose the owner we use that parameter to filter on schema since that's what tends to be exposed. Some DBs like mssql 2000 conflate the two so at least there it works nicely." (%database-list-* database "TABLE" owner)) (defmethod database-list-views ((database generic-odbc-database) &key (owner nil)) "Since ODBC doesn't expose the owner we use that parameter to filter on schema since that's what tends to be exposed. Some DBs like mssql 2000 conflate the two so at least there it works nicely." (%database-list-* database "VIEW" owner)) (defmethod database-list-attributes ((table %database-identifier) (database generic-odbc-database) &key (owner nil) &aux (table (unescaped-database-identifier table))) (declare (ignore owner)) (multiple-value-bind (rows col-names) (funcall (list-all-table-columns-fn database) table :db (odbc-conn database)) (declare (ignore col-names)) ;; COLUMN_NAME is hard-coded by odbc spec as fourth position (loop for row in rows collect (fourth row)))) (defmethod database-attribute-type ((attribute %database-identifier) (table %database-identifier) (database generic-odbc-database) &key (owner nil) &aux (table (unescaped-database-identifier table)) (attribute (unescaped-database-identifier attribute))) (declare (ignore owner)) (multiple-value-bind (rows col-names) (funcall (list-all-table-columns-fn database) table :db (odbc-conn database)) (declare (ignore col-names)) ;; COLUMN_NAME is hard-coded by odbc spec as fourth position ;; TYPE_NAME is the sixth column ;; PRECISION/COLUMN_SIZE is the seventh column ;; SCALE/DECIMAL_DIGITS is the ninth column ;; NULLABLE is the eleventh column (loop for row in rows when (string-equal attribute (fourth row)) do (let ((size (seventh row)) (precision (ninth row)) (scale (nth 10 row))) (return (values (ensure-keyword (sixth row)) (when size (parse-integer size)) (when precision (parse-integer precision)) (when scale (parse-integer scale)))))))) cl-sql-6.4.1/sql/loop-extension.lisp0000644000175000017500000002160311335067642016413 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; FILE IDENTIFICATION ;;;; ;;;; Name: loop-extension.lisp ;;;; Purpose: Extensions to the Loop macro for CLSQL ;;;; ;;;; Copyright (c) 2001-2006 Kevin Rosenberg and (c) 1999-2001 Pierre R. Mai ;;;; ;;;; ************************************************************************* (in-package #:clsql-sys) #+(or allegro sbcl) (eval-when (:compile-toplevel :load-toplevel :execute) (defpackage #:ansi-loop (:import-from #+sbcl #:sb-loop #+allegro #:excl #:*loop-epilogue* #:*loop-ansi-universe* #:add-loop-path))) #+(or allegro sbcl) (defun ansi-loop::loop-gentemp (&optional (pref 'loopva-)) (gensym (string pref))) #+clisp (eval-when (:compile-toplevel :load-toplevel :execute) (when (find-package "ANSI-LOOP") (push :clisp-aloop cl:*features*))) #+(or allegro clisp-aloop cmu openmcl sbcl scl) (defun loop-record-iteration-path (variable data-type prep-phrases) (let ((in-phrase nil) (from-phrase nil)) (loop for (prep . rest) in prep-phrases do (case prep ((:in :of) (when in-phrase (error 'clsql:sql-user-error :message (format nil "Duplicate OF or IN iteration path: ~S." (cons prep rest)))) (setq in-phrase rest)) ((:from) (when from-phrase (error 'clsql:sql-user-error :message (format nil "Duplicate FROM iteration path: ~S." (cons prep rest)))) (setq from-phrase rest)) (t (error 'clsql:sql-user-error :message (format nil"Unknown preposition: ~S." prep))))) (unless in-phrase (error 'clsql:sql-user-error :message "Missing OF or IN iteration path.")) (unless from-phrase (setq from-phrase '(*default-database*))) (unless (consp variable) (setq variable (list variable))) (cond ;; object query ((and (consp (first in-phrase)) (string-equal "sql-query" (symbol-name (caar in-phrase))) (consp (second (first in-phrase))) (eq 'quote (first (second (first in-phrase)))) (symbolp (second (second (first in-phrase))))) (let ((result-var (ansi-loop::loop-gentemp 'loop-record-result-)) (step-var (ansi-loop::loop-gentemp 'loop-record-step-))) `(((,variable nil ,@(and data-type (list data-type))) (,result-var (query ,(first in-phrase))) (,step-var nil)) () () () (if (null ,result-var) t (progn (setq ,step-var (first ,result-var)) (setq ,result-var (rest ,result-var)) nil)) (,variable ,step-var) (null ,result-var) () (if (null ,result-var) t (progn (setq ,step-var (first ,result-var)) (setq ,result-var (rest ,result-var)) nil)) (,variable ,step-var)))) ((consp variable) (let ((query-var (ansi-loop::loop-gentemp 'loop-record-)) (db-var (ansi-loop::loop-gentemp 'loop-record-database-)) (result-set-var (ansi-loop::loop-gentemp 'loop-record-result-set-)) (step-var (ansi-loop::loop-gentemp 'loop-record-step-))) (push `(when ,result-set-var (database-dump-result-set ,result-set-var ,db-var)) ansi-loop::*loop-epilogue*) `(((,variable nil ,@(and data-type (list data-type))) (,query-var ,(first in-phrase)) (,db-var ,(first from-phrase)) (,result-set-var t) (,step-var nil)) ((multiple-value-bind (%rs %cols) (database-query-result-set ,query-var ,db-var :result-types :auto) (setq ,result-set-var %rs ,step-var (make-list %cols)))) () () (not (database-store-next-row ,result-set-var ,db-var ,step-var)) (,variable ,step-var) (not ,result-set-var) () (not (database-store-next-row ,result-set-var ,db-var ,step-var)) (,variable ,step-var))))))) #+(or allegro clisp-aloop cmu openmcl sbcl scl) (ansi-loop::add-loop-path '(record records tuple tuples) 'loop-record-iteration-path ansi-loop::*loop-ansi-universe* :preposition-groups '((:of :in) (:from)) :inclusive-permitted nil) #+lispworks (cl-user::define-loop-method (loop::record loop::records loop::tuple loop::tuples) clsql-loop-method (loop::in loop::of loop::from)) #+lispworks (defun clsql-loop-method (method-name iter-var iter-var-data-type prep-phrases inclusive? allowed-preps method-specific-data) (declare (ignore method-name iter-var-data-type inclusive? allowed-preps method-specific-data)) (let ((in-phrase nil) (from-phrase nil)) (loop for (prep . rest) in prep-phrases do (cond ((or (eq prep 'loop::in) (eq prep 'loop::of)) (when in-phrase (error 'clsql:sql-user-error :message (format nil "Duplicate OF or IN iteration path: ~S." (cons prep rest)))) (setq in-phrase rest)) ((eq prep 'loop::from) (when from-phrase (error 'clsql:sql-user-error :message (format nil "Duplicate FROM iteration path: ~S." (cons prep rest)))) (setq from-phrase rest)) (t (error 'clsql:sql-user-error :message (format nil "Unknown preposition: ~S." prep))))) (unless in-phrase (error 'clsql:sql-user-error :message "Missing OF or IN iteration path.")) (unless from-phrase (setq from-phrase '(clsql:*default-database*))) (unless (consp iter-var) (setq iter-var (list iter-var))) (cond ;; object query ((and (consp in-phrase) (string-equal "sql-query" (symbol-name (car in-phrase))) (consp (second in-phrase)) (eq 'quote (first (second in-phrase))) (symbolp (second (second in-phrase)))) (let ((result-var (gensym "LOOP-RECORD-RESULT-")) (step-var (gensym "LOOP-RECORD-STEP-"))) (values t nil `(,@(mapcar (lambda (v) `(,v nil)) iter-var) (,result-var (clsql:query ,in-phrase)) (,step-var nil)) () () () `((if (null ,result-var) t (progn (setq ,step-var (first ,result-var)) (setq ,result-var (rest ,result-var)) nil))) `(,iter-var ,step-var) `((if (null ,result-var) t (progn (setq ,step-var (first ,result-var)) (setq ,result-var (rest ,result-var)) nil))) `(,iter-var ,step-var) () () ))) ((consp iter-var) (let ((query-var (gensym "LOOP-RECORD-")) (db-var (gensym "LOOP-RECORD-DATABASE-")) (result-set-var (gensym "LOOP-RECORD-RESULT-SET-")) (step-var (gensym "LOOP-RECORD-STEP-"))) (values t nil `(,@(mapcar (lambda (v) `(,v nil)) iter-var) (,query-var ,in-phrase) (,db-var ,(first from-phrase)) (,result-set-var nil) (,step-var nil)) `((multiple-value-bind (%rs %cols) (clsql-sys:database-query-result-set ,query-var ,db-var :result-types :auto) (setq ,result-set-var %rs ,step-var (make-list %cols)))) () () `((unless (clsql-sys:database-store-next-row ,result-set-var ,db-var ,step-var) (when ,result-set-var (clsql-sys:database-dump-result-set ,result-set-var ,db-var)) t)) `(,iter-var ,step-var) `((unless (clsql-sys:database-store-next-row ,result-set-var ,db-var ,step-var) (when ,result-set-var (clsql-sys:database-dump-result-set ,result-set-var ,db-var)) t)) `(,iter-var ,step-var) () ())))))) #+clisp-aloop (eval-when (:compile-toplevel :load-toplevel :execute) (setq cl:*features* (delete :clisp-aloop cl:*features*))) cl-sql-6.4.1/sql/oodml.lisp0000644000175000017500000017146412134025332014541 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; ;;;; The CLSQL Object Oriented Data Manipulation Language (OODML). ;;;; ;;;; This file is part of CLSQL. ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* (in-package #:clsql-sys) (defun find-normalized-key (obj) "Find the first / primary key of a normalized object" (find-slot-if obj #'key-slot-p T T)) (defun normalized-key-value (obj) "Normalized classes share a single key for all their key slots" (when (normalizedp (class-of obj)) (easy-slot-value obj (find-normalized-key obj)))) (defun key-qualifier-for-instance (obj &key (database *default-database*) this-class) "Generate a boolean sql-expression that identifies an object by its keys" (let* ((obj-class (or this-class (class-of obj))) (keys (keyslots-for-class obj-class)) (normal-db-value (normalized-key-value obj))) (when keys (labels ((db-value (k) (or normal-db-value (db-value-from-slot k (easy-slot-value obj k) database))) (key-equal-exp (k) (sql-operation '== (generate-attribute-reference obj-class k database) (db-value k)))) (clsql-ands (mapcar #'key-equal-exp keys)))))) (defun generate-attribute-reference (vclass slotdef &optional (database *default-database*)) "Turns key class and slot-def into a sql-expression representing the table and column it comes from used by things like make-select-list, update-slot-from-record" (when (key-or-base-slot-p slotdef) (sql-expression :attribute (database-identifier slotdef database) :table (database-identifier vclass database)))) (defun get-join-slots (class &optional retrieval-method) "Returns list of join slots for a class. if a retrieval method is specified only return slots of that type if the retrieval method is T, nil or :all return all join slots" (assert (member retrieval-method '(nil t :all :immediate :deferred))) (setf class (to-class class)) (let ((all? (member retrieval-method '(nil t :all)))) (loop for slot in (ordered-class-slots class) when (and (join-slot-p slot) (or all? (eql (join-slot-retrieval-method slot) retrieval-method))) collect slot))) (defun immediate-join-slots (class) (get-join-slots class :immediate)) (defmethod choose-database-for-instance ((obj standard-db-object) &optional database) "Determine which database connection to use for a standard-db-object. Errs if none is available." (or (find-if #'(lambda (db) (and db (is-database-open db))) (list (view-database obj) database *default-database*)) (signal-no-database-error nil))) (defmethod update-slot-with-null ((object standard-db-object) slotdef) "sets a slot to the void value of the slot-def (usually nil)" (setf (easy-slot-value object slotdef) (slot-value slotdef 'void-value))) (defmethod update-slot-from-db-value ((instance standard-db-object) slotdef value) "This gets a value from the database and turns it itno a lisp value based on the slot's slot-db-reader or baring that read-sql-value" (declare (optimize (speed 3) #+cmu (extensions:inhibit-warnings 3))) (let* ((slot-reader (view-class-slot-db-reader slotdef)) (slot-type (specified-type slotdef))) (cond ((null value) (update-slot-with-null instance slotdef)) ((null slot-reader) (setf (easy-slot-value instance slotdef) (read-sql-value value (delistify slot-type) (choose-database-for-instance instance) (database-underlying-type (choose-database-for-instance instance))))) (t (etypecase slot-reader ((or symbol function) (setf (easy-slot-value instance slotdef) (apply slot-reader (list value)))) (string (setf (easy-slot-value instance slotdef) (format nil slot-reader value)))))))) (defmethod key-value-from-db (slotdef value database) "TODO: is this deprecated? there are no uses anywhere in clsql" (declare (optimize (speed 3) #+cmu (extensions:inhibit-warnings 3))) (let ((slot-reader (view-class-slot-db-reader slotdef)) (slot-type (specified-type slotdef))) (cond ((and value (null slot-reader)) (read-sql-value value (delistify slot-type) database (database-underlying-type database))) ((null value) nil) ((typep slot-reader 'string) (format nil slot-reader value)) ((typep slot-reader '(or symbol function)) (apply slot-reader (list value))) (t (error "Slot reader is of an unusual type."))))) (defun db-value-from-slot (slotdef val database) (let ((dbwriter (view-class-slot-db-writer slotdef)) (dbtype (specified-type slotdef))) (typecase dbwriter (string (format nil dbwriter val)) ((and (or symbol function) (not null)) (apply dbwriter (list val))) (t (database-output-sql-as-type (typecase dbtype (cons (car dbtype)) (t dbtype)) val database (database-underlying-type database)))))) (defun check-slot-type (slotdef val) (let* ((slot-type (specified-type slotdef)) (basetype (if (listp slot-type) (car slot-type) slot-type))) (when (and slot-type val) (unless (typep val basetype) (error 'sql-user-error :message (format nil "Invalid value ~A in slot ~A, not of type ~A." val (slot-definition-name slotdef) slot-type)))))) (defmethod get-slot-values-from-view (obj slotdeflist values) "Used to copy values from the database into the object used by things like find-all and select" (loop for slot in slotdeflist for value in values do (update-slot-from-db-value obj slot value)) obj) (defclass class-and-slots () ((view-class :accessor view-class :initarg :view-class :initform nil) (slot-defs :accessor slot-defs :initarg :slot-defs :initform nil)) (:documentation "A helper class to keep track of which slot-defs from a table need to be updated, a normalized class might have many of these because each of its parent classes might represent some other table and we need to match which slots came from which parent class/table")) (defun make-class-and-slots (c &optional s) "Create a new class-and-slots object" (make-instance 'class-and-slots :view-class c :slot-defs (listify s) )) (defmethod view-table ((o class-and-slots)) "get the view-table of the view-class of o" (view-table (view-class o))) (defmethod view-table-exp ((o class-and-slots)) (sql-expression :table (view-table o))) (defmethod view-table-exp ((o standard-db-class)) (sql-expression :table (view-table o))) (defmethod attribute-references ((o class-and-slots)) "build sql-ident-attributes for a given class-and-slots" (loop with class = (view-class o) for sd in (slot-defs o) collect (generate-attribute-reference class sd))) (defmethod attribute-value-pairs ((def class-and-slots) (o standard-db-object) database) "for a given class-and-slots and object, create the sql-expression & value pairs that need to be sent to the database" (loop for s in (slot-defs def) for n = (to-slot-name s) when (slot-boundp o n) collect (make-attribute-value-pair s (slot-value o n) database))) (defmethod view-classes-and-slots-by-name ((obj standard-db-object) slots-to-match) "If it's normalized, find the class that actually contains the slot that's tied to the db, otherwise just search the current class " (let* ((view-class (class-of obj)) (normalizedp (normalizedp view-class)) rtns) (labels ((get-c&s-obj (class) (or (find class rtns :key #'view-class) (first (push (make-class-and-slots class) rtns)))) (associate-slot-with-class (class slot) "Find the best class to associate with the slot. If it is normalized then it needs to be a direct slot otherwise it just needs to be on the class." (let ((sd (find-slot-by-name class slot normalizedp nil))) (if sd ;;we found it directly or it's (not normalized) (pushnew sd (slot-defs (get-c&s-obj class))) (when normalizedp (loop for parent in (class-direct-superclasses class) until (associate-slot-with-class parent slot)))) sd))) (loop for in-slot in (listify slots-to-match) do (associate-slot-with-class view-class in-slot))) rtns)) (defun update-auto-increments-keys (class obj database) " handle pulling any autoincrement values into the object if normalized and we now that all the " (let ((pk-slots (keyslots-for-class class)) (table (view-table class)) new-pk-value) (labels ((do-update (slot) (when (and (null (easy-slot-value obj slot)) (auto-increment-column-p slot database)) (update-slot-from-db-value obj slot (or new-pk-value (setf new-pk-value (database-last-auto-increment-id database table slot)))))) (chain-primary-keys (in-class) "This seems kindof wrong, but this is mostly how it was working, so its here to keep the normalized code path working" (when (typep in-class 'standard-db-class) (loop for slot in (ordered-class-slots in-class) when (key-slot-p slot) do (do-update slot))))) (loop for slot in pk-slots do (do-update slot)) (let ((direct-class (to-class obj))) (when (and new-pk-value (normalizedp direct-class)) (chain-primary-keys direct-class))) new-pk-value))) (defmethod %update-instance-helper (class-and-slots obj database &aux (avps (attribute-value-pairs class-and-slots obj database))) "A function to help us update a given table (based on class-and-slots) with values from an object" ;; we dont actually need to update anything on this particular ;; class / parent class (unless avps (return-from %update-instance-helper)) (let* ((view-class (view-class class-and-slots)) (table (view-table view-class)) (table-sql (sql-expression :table table))) ;; view database is the flag we use to tell it was pulled from a database ;; and thus probably needs an update instead of an insert (cond ((view-database obj) (let ((where (key-qualifier-for-instance obj :database database :this-class view-class))) (unless where (error "update-record-from-*: could not generate a where clause for ~a using ~A" obj view-class)) (update-records table-sql :av-pairs avps :where where :database database))) (T ;; was not pulled from the db so insert it ;; avps MUST contain any primary key slots set ;; by previous inserts of the same object into different ;; tables (ie: normalized stuff) (insert-records :into table-sql :av-pairs avps :database database) (update-auto-increments-keys view-class obj database) ;; we dont set view database here, because there could be ;; N of these for each call to update-record-from-* because ;; of normalized classes )) (update-slot-default-values obj class-and-slots))) (defmethod update-record-from-slots ((obj standard-db-object) slots &key (database *default-database*)) "For a given list of slots, update all records associated with those slots and classes. Generally this will update the single record associated with this object, but for normalized classes might update as many records as there are inheritances " (setf slots (listify slots)) (let* ((classes-and-slots (view-classes-and-slots-by-name obj slots)) (database (choose-database-for-instance obj database))) (loop for class-and-slots in classes-and-slots do (%update-instance-helper class-and-slots obj database)) (setf (slot-value obj 'view-database) database)) (values)) (defmethod update-record-from-slot ((obj standard-db-object) slot &key (database *default-database*)) "just call update-records-from-slots which now handles this. This function is only here to maintain backwards compatibility in the public api" (update-record-from-slots obj slot :database database)) (defmethod view-classes-and-storable-slots (class) "Get a list of all the tables we need to update and the slots on them for non normalized classes we return the class and all its storable slots for normalized classes we return a list of direct slots and the class they came from for each normalized view class " (setf class (to-class class)) (let* (rtns) (labels ((storable-slots (class) (loop for sd in (slots-for-possibly-normalized-class class) when (key-or-base-slot-p sd) collect sd)) (get-classes-and-slots (class &aux (normalizedp (normalizedp class))) (let ((slots (storable-slots class))) (when slots (push (make-class-and-slots class slots) rtns))) (when normalizedp (loop for new-class in (class-direct-superclasses class) do (when (typep new-class 'standard-db-class) (get-classes-and-slots new-class)))))) (get-classes-and-slots class)) rtns)) (defmethod primary-key-slot-values ((obj standard-db-object) &key class slots ) "Returns the values of all key-slots for a given class" (defaulting class (class-of obj) slots (keyslots-for-class class)) (loop for slot in slots collect (easy-slot-value obj slot))) (defmethod update-slot-default-values ((obj standard-db-object) classes-and-slots) "Makes sure that if a class has unfilled slots that claim to have a default, that we retrieve those defaults from the database TODO: use update-slots-from-record (doesnt exist) instead to batch this!" (loop for class-and-slots in (listify classes-and-slots) do (loop for slot in (slot-defs class-and-slots) do (when (and (slot-has-default-p slot) (not (easy-slot-value obj slot))) (update-slot-from-record obj (to-slot-name slot)))))) (defmethod update-records-from-instance ((obj standard-db-object) &key (database *default-database*)) "Updates the records in the database associated with this object if view-database slot on the object is nil then the object is assumed to be new and is inserted" (let ((database (choose-database-for-instance obj database)) (classes-and-slots (view-classes-and-storable-slots obj))) (loop for class-and-slots in classes-and-slots do (%update-instance-helper class-and-slots obj database)) (setf (slot-value obj 'view-database) database) (primary-key-slot-values obj))) (defmethod delete-instance-records ((instance standard-db-object) &key database) "Removes the records associated with a given instance (as determined by key-qualifier-for-instance) TODO: Doesnt handle normalized classes at all afaict" (let ((database (choose-database-for-instance instance database)) (vt (sql-expression :table (view-table (class-of instance))))) (if database (let ((qualifier (key-qualifier-for-instance instance :database database))) (delete-records :from vt :where qualifier :database database) (setf (record-caches database) nil) (setf (slot-value instance 'view-database) nil) (values)) (signal-no-database-error database)))) (defmethod update-instance-from-records ((instance standard-db-object) &key (database *default-database*)) "Updates a database object with the current values stored in the database TODO: Should this update immediate join slots similar to build-objects? Can we just call build-objects?, update-objects-joins? " (let* ((classes-and-slots (view-classes-and-storable-slots instance)) (vd (choose-database-for-instance instance database))) (labels ((do-update (class-and-slots) (let* ((select-list (make-select-list class-and-slots :do-joins-p nil)) (view-table (sql-table select-list)) (view-qual (key-qualifier-for-instance instance :database vd :this-class (view-class select-list))) (res (when view-qual (first (apply #'select (append (full-select-list select-list) (list :from view-table :where view-qual :result-types nil :database vd))))))) (when res (setf (slot-value instance 'view-database) vd) (get-slot-values-from-view instance (slot-list select-list) res)) ))) (loop for class-and-slots in classes-and-slots do (do-update class-and-slots))))) (defmethod get-slot-value-from-record ((instance standard-db-object) slot &key (database *default-database*)) (let* ((class-and-slot (first (view-classes-and-slots-by-name instance slot))) (view-class (view-class class-and-slot)) (slot-def (first (slot-defs class-and-slot))) (vd (choose-database-for-instance instance database)) (att-ref (first (attribute-references class-and-slot))) (res (first (select att-ref :from (view-table-exp class-and-slot) :where (key-qualifier-for-instance instance :database vd :this-class view-class) :result-types nil :flatp T)))) (values res slot-def))) (defmethod update-slot-from-record ((instance standard-db-object) slot &key (database *default-database*)) "Pulls the value of a given slot form the database and stores that in the appropriate slot on instance" (multiple-value-bind (res slot-def) (get-slot-value-from-record instance slot :database database) (let ((vd (choose-database-for-instance instance database))) (setf (slot-value instance 'view-database) vd) (update-slot-from-db-value instance slot-def res)))) (defvar +no-slot-value+ '+no-slot-value+) (defsql sql-slot-value (:symbol "slot-value") (classname slot &optional (value +no-slot-value+) (database *default-database*)) (let* ((class (find-class classname)) (sld (slotdef-for-slot-with-class slot class))) (if sld (if (eq value +no-slot-value+) (sql-expression :attribute (database-identifier sld database) :table (view-table class)) (db-value-from-slot sld value database)) (error "Unknown slot ~A for class ~A" slot classname)))) (defsql sql-view-class (:symbol "view-class") (classname &optional (database *default-database*)) (declare (ignore database)) (let* ((class (find-class classname))) (unless (view-table class) (error "No view-table for class ~A" classname)) (sql-expression :table (view-table class)))) (defmethod database-get-type-specifier (type args database db-type) (declare (ignore type args database db-type)) (format nil "VARCHAR(~D)" *default-string-length*)) (defmethod database-get-type-specifier ((type (eql 'integer)) args database db-type) (declare (ignore database db-type)) (if args (format nil "INT(~A)" (car args)) "INT")) (deftype tinyint () "An 8-bit integer, this width may vary by SQL implementation." 'integer) (defmethod database-get-type-specifier ((type (eql 'tinyint)) args database db-type) (declare (ignore args database db-type)) "INT") (deftype smallint () "An integer smaller than a 32-bit integer. this width may vary by SQL implementation." 'integer) (defmethod database-get-type-specifier ((type (eql 'smallint)) args database db-type) (declare (ignore args database db-type)) "INT") (deftype mediumint () "An integer smaller than a 32-bit integer, but may be larger than a smallint. This width may vary by SQL implementation." 'integer) (defmethod database-get-type-specifier ((type (eql 'mediumint)) args database db-type) (declare (ignore args database db-type)) "INT") (deftype bigint () "An integer larger than a 32-bit integer, this width may vary by SQL implementation." 'integer) (defmethod database-get-type-specifier ((type (eql 'bigint)) args database db-type) (declare (ignore args database db-type)) "BIGINT") (deftype varchar (&optional size) "A variable length string for the SQL varchar type." (declare (ignore size)) 'string) (defmethod database-get-type-specifier ((type (eql 'varchar)) args database db-type) (declare (ignore database db-type)) (if args (format nil "VARCHAR(~A)" (car args)) (format nil "VARCHAR(~D)" *default-string-length*))) (defmethod database-get-type-specifier ((type (eql 'string)) args database db-type) (declare (ignore database db-type)) (if args (format nil "CHAR(~A)" (car args)) (format nil "VARCHAR(~D)" *default-string-length*))) (deftype universal-time () "A positive integer as returned by GET-UNIVERSAL-TIME." '(integer 1 *)) (defmethod database-get-type-specifier ((type (eql 'universal-time)) args database db-type) (declare (ignore args database db-type)) "BIGINT") (defmethod database-get-type-specifier ((type (eql 'wall-time)) args database db-type) (declare (ignore args database db-type)) "TIMESTAMP") (defmethod database-get-type-specifier ((type (eql 'date)) args database db-type) (declare (ignore args database db-type)) "DATE") (defmethod database-get-type-specifier ((type (eql 'duration)) args database db-type) (declare (ignore database args db-type)) "VARCHAR") (defmethod database-get-type-specifier ((type (eql 'money)) args database db-type) (declare (ignore database args db-type)) "INT8") #+ignore (deftype char (&optional len) "A lisp type for the SQL CHAR type." `(string ,len)) (defmethod database-get-type-specifier ((type (eql 'float)) args database db-type) (declare (ignore database db-type)) (if args (format nil "FLOAT(~A)" (car args)) "FLOAT")) (defmethod database-get-type-specifier ((type (eql 'long-float)) args database db-type) (declare (ignore database db-type)) (if args (format nil "FLOAT(~A)" (car args)) "FLOAT")) (deftype generalized-boolean () "A type which outputs a SQL boolean value, though any lisp type can be stored in the slot." t) (defmethod database-get-type-specifier ((type (eql 'boolean)) args database db-type) (declare (ignore args database db-type)) "BOOL") (defmethod database-get-type-specifier ((type (eql 'generalized-boolean)) args database db-type) (declare (ignore args database db-type)) "BOOL") (defmethod database-get-type-specifier ((type (eql 'number)) args database db-type) (declare (ignore database db-type)) (cond ((and (consp args) (= (length args) 2)) (format nil "NUMBER(~D,~D)" (first args) (second args))) ((and (consp args) (= (length args) 1)) (format nil "NUMBER(~D)" (first args))) (t "NUMBER"))) (defmethod database-get-type-specifier ((type (eql 'char)) args database db-type) (declare (ignore database db-type)) (if args (format nil "CHAR(~D)" (first args)) "CHAR(1)")) (defmethod database-output-sql-as-type (type val database db-type) (declare (ignore type database db-type)) val) (defmethod database-output-sql-as-type ((type (eql 'list)) val database db-type) (declare (ignore database db-type)) (progv '(*print-circle* *print-array*) '(t t) (let ((escaped (prin1-to-string val))) (substitute-char-string escaped #\Null " ")))) (defmethod database-output-sql-as-type ((type (eql 'symbol)) val database db-type) (declare (ignore database db-type)) (if val (concatenate 'string (package-name (symbol-package val)) "::" (symbol-name val)) "")) (defmethod database-output-sql-as-type ((type (eql 'keyword)) val database db-type) (declare (ignore database db-type)) (if val (symbol-name val) "")) (defmethod database-output-sql-as-type ((type (eql 'vector)) val database db-type) (declare (ignore database db-type)) (progv '(*print-circle* *print-array*) '(t t) (prin1-to-string val))) (defmethod database-output-sql-as-type ((type (eql 'array)) val database db-type) (declare (ignore database db-type)) (progv '(*print-circle* *print-array*) '(t t) (prin1-to-string val))) (defmethod database-output-sql-as-type ((type (eql 'boolean)) val database db-type) (declare (ignore database db-type)) (if val "t" "f")) (defmethod database-output-sql-as-type ((type (eql 'generalized-boolean)) val database db-type) (declare (ignore database db-type)) (if val "t" "f")) (defmethod database-output-sql-as-type ((type (eql 'string)) val database db-type) (declare (ignore database db-type)) val) (defmethod database-output-sql-as-type ((type (eql 'char)) val database db-type) (declare (ignore database db-type)) (etypecase val (character (write-to-string val)) (string val))) (defmethod database-output-sql-as-type ((type (eql 'float)) val database db-type) (declare (ignore database db-type)) (if (eq (type-of val) 'null) nil (let ((*read-default-float-format* (type-of val))) (format nil "~F" val)))) (defmethod read-sql-value (val type database db-type) (declare (ignore database db-type)) (cond ((null type) val) ;;we have no desired type, just give the value ((typep val type) val) ;;check that it hasn't already been converted. ((typep val 'string) (read-from-string val)) ;;maybe read will just take care of it? (T (error "Unable to read-sql-value ~a as type ~a" val type)))) (defmethod read-sql-value (val (type (eql 'string)) database db-type) (declare (ignore database db-type)) val) (defmethod read-sql-value (val (type (eql 'varchar)) database db-type) (declare (ignore database db-type)) val) (defmethod read-sql-value (val (type (eql 'char)) database db-type) (declare (ignore database db-type)) (schar val 0)) (defmethod read-sql-value (val (type (eql 'keyword)) database db-type) (declare (ignore database db-type)) (when (< 0 (length val)) (intern (symbol-name-default-case val) (find-package '#:keyword)))) (defmethod read-sql-value (val (type (eql 'symbol)) database db-type) (declare (ignore database db-type)) (when (< 0 (length val)) (unless (string= val (symbol-name-default-case "NIL")) (read-from-string val)))) (defmethod read-sql-value (val (type (eql 'integer)) database db-type) (declare (ignore database db-type)) (etypecase val (string (unless (string-equal "NIL" val) (parse-integer val))) (number val))) (defmethod read-sql-value (val (type (eql 'smallint)) database db-type) (declare (ignore database db-type)) (etypecase val (string (unless (string-equal "NIL" val) (parse-integer val))) (number val))) (defmethod read-sql-value (val (type (eql 'bigint)) database db-type) (declare (ignore database db-type)) (etypecase val (string (unless (string-equal "NIL" val) (parse-integer val))) (number val))) (defmethod read-sql-value (val (type (eql 'float)) database db-type) (declare (ignore database db-type)) ;; writing 1.0 writes 1, so we we *really* want a float, must do (float ...) (etypecase val (string (float (read-from-string val))) (float val))) (defmethod read-sql-value (val (type (eql 'double-float)) database db-type) (declare (ignore database db-type)) ;; writing 1.0 writes 1, so if we *really* want a float, must do (float ...) (etypecase val (string (float (let ((*read-default-float-format* 'double-float)) (read-from-string val)) 1.0d0)) (double-float val) (float (coerce val 'double-float)))) (defmethod read-sql-value (val (type (eql 'boolean)) database db-type) (declare (ignore database db-type)) (equal "t" val)) (defmethod read-sql-value (val (type (eql 'generalized-boolean)) database db-type) (declare (ignore database db-type)) (equal "t" val)) (defmethod read-sql-value (val (type (eql 'number)) database db-type) (declare (ignore database db-type)) (etypecase val (string (unless (string-equal "NIL" val) (read-from-string val))) (number val))) (defmethod read-sql-value (val (type (eql 'universal-time)) database db-type) (declare (ignore database db-type)) (unless (eq 'NULL val) (etypecase val (string (parse-integer val)) (number val)))) (defmethod read-sql-value (val (type (eql 'wall-time)) database db-type) (declare (ignore database db-type)) (unless (eq 'NULL val) (parse-timestring val))) (defmethod read-sql-value (val (type (eql 'date)) database db-type) (declare (ignore database db-type)) (unless (eq 'NULL val) (parse-datestring val))) (defmethod read-sql-value (val (type (eql 'duration)) database db-type) (declare (ignore database db-type)) (unless (or (eq 'NULL val) (equal "NIL" val)) (parse-timestring val))) ;; ------------------------------------------------------------ ;; Logic for 'faulting in' :join slots ;; this works, but is inefficient requiring (+ 1 n-rows) ;; SQL queries #+ignore (defun fault-join-target-slot (class object slot-def) (let* ((res (fault-join-slot-raw class object slot-def)) (dbi (view-class-slot-db-info slot-def)) (target-name (gethash :target-slot dbi)) (target-class (find-class target-name))) (when res (mapcar (lambda (obj) (list (car (fault-join-slot-raw target-class obj (find target-name (class-slots (class-of obj)) :key #'slot-definition-name))) obj)) res) #+ignore ;; this doesn't work when attempting to call slot-value (mapcar (lambda (obj) (cons obj (slot-value obj ts))) res)))) (defun fault-join-target-slot (class object slot-def) (let* ((dbi (view-class-slot-db-info slot-def)) (ts (gethash :target-slot dbi)) (jc (gethash :join-class dbi)) (jc-view-table (view-table (find-class jc))) (tdbi (view-class-slot-db-info (find ts (class-slots (find-class jc)) :key #'slot-definition-name))) (retrieval (gethash :retrieval tdbi)) (tsc (gethash :join-class tdbi)) (ts-view-table (view-table (find-class tsc))) (jq (join-qualifier class object slot-def)) (key (slot-value object (gethash :home-key dbi)))) (when jq (ecase retrieval (:immediate (let ((res (find-all (list tsc) :inner-join (sql-expression :table jc-view-table) :on (sql-operation '== (sql-expression :attribute (gethash :foreign-key tdbi) :table ts-view-table) (sql-expression :attribute (gethash :home-key tdbi) :table jc-view-table)) :where jq :result-types :auto :database (choose-database-for-instance object)))) (mapcar #'(lambda (i) (let* ((instance (car i)) (jcc (make-instance jc :view-database (choose-database-for-instance instance)))) (setf (slot-value jcc (gethash :foreign-key dbi)) key) (setf (slot-value jcc (gethash :home-key tdbi)) (slot-value instance (gethash :foreign-key tdbi))) (list instance jcc))) res))) (:deferred ;; just fill in minimal slots (mapcar #'(lambda (k) (let ((instance (make-instance tsc :view-database (choose-database-for-instance object))) (jcc (make-instance jc :view-database (choose-database-for-instance object))) (fk (car k))) (setf (slot-value instance (gethash :home-key tdbi)) fk) (setf (slot-value jcc (gethash :foreign-key dbi)) key) (setf (slot-value jcc (gethash :home-key tdbi)) fk) (list instance jcc))) (select (sql-expression :attribute (gethash :foreign-key tdbi) :table jc-view-table) :from (sql-expression :table jc-view-table) :where jq :database (choose-database-for-instance object)))))))) ;;; Remote Joins (defvar *default-update-objects-max-len* nil "The default value to use for the MAX-LEN keyword argument to UPDATE-OBJECT-JOINS.") (defun %update-objects-joins-slot-defs (class slot-names) "Get the slot definitions for the joins slots specified as slot-names if slot-names is :immediate, :deferred or (or :all t) return all of that type of slot definitions" (setf class (to-class class)) (when (eq t slot-names) (setf slot-names :all)) (etypecase slot-names (null nil) (keyword ;; slot-names is the retrieval type of the join-slot or :all (get-join-slots class slot-names)) ((or symbol list) (loop for slot in (listify slot-names) for def = (find-slot-by-name class slot) when (and def (join-slot-p def)) collecting def unless (and def (join-slot-p def)) do (warn "Unable to find join slot named ~S in class ~S." slot class))))) (defun get-joined-objects (objects slotdef &key force-p (batch-size *default-update-objects-max-len*)) "Given a list of objects and a join slot-def get the objects that need to be joined to the input objects we will query in batches as large as batch-size" (when (join-slot-p slotdef) (let* ((slot-name (to-slot-name slotdef)) (join-class (join-slot-class-name slotdef)) (home-key (join-slot-info-value slotdef :home-key)) (foreign-key (join-slot-info-value slotdef :foreign-key)) (foreign-key-values (remove-duplicates (loop for object in (listify objects) for hk = (slot-value object home-key) when (or force-p (not (slot-boundp object slot-name))) collect hk) :test #'equal))) ;; we want to retrieve at most batch-size objects per query (flet ((fetch (keys) (find-all (list join-class) :where (make-instance 'sql-relational-exp :operator 'in :sub-expressions (list (sql-expression :attribute foreign-key) keys)) :result-types :auto :flatp t))) (if (null batch-size) (fetch foreign-key-values) (loop for keys = (pop-n foreign-key-values batch-size) while keys nconcing (fetch keys))))))) (defun %object-joins-from-list (object slot joins force-p ) "Given a list of objects that we are trying to join to, pull the correct ones for this object" (when (or force-p (not (slot-boundp object (to-slot-name slot)))) (let ((home-key (join-slot-info-value slot :home-key)) (foreign-key (join-slot-info-value slot :foreign-key))) (loop for join in joins when (equal (slot-value join foreign-key) (slot-value object home-key)) collect join)))) (defun update-objects-joins (objects &key (slots :immediate) (force-p t) class-name (max-len *default-update-objects-max-len*)) "Updates from the records of the appropriate database tables the join slots specified by SLOTS in the supplied list of View Class instances OBJECTS. A simpler method of causing a join-slot to be requeried is to set it to unbound, then request it again. This function has efficiency gains where join-objects are shared among the `objects` (querying all join-objects, then attaching them appropriately to each of the `objects`) SLOTS can be one of: * :immediate (DEFAULT) - refresh join slots created with :retrieval :immediate * :deferred - refresh join slots created with :retrieval :deferred * :all,t - refresh all join slots regardless of :retrieval * list of symbols - which explicit slots to refresh * a single symobl - what slot to refresh CLASS-NAME is used to specify the View Class of all instance in OBJECTS and default to nil which means that the class of the first instance in OBJECTS is used. FORCE-P is t by default which means that all join slots are updated whereas a value of nil means that only unbound join slots are updated. MAX-LEN defaults to *DEFAULT-UPDATE-OBJECTS-MAX-LEN* When non-nil this is essentially a batch size for the max number of objects to query from the database at a time. If we need more than max-len we loop till we have all the objects" (assert (or (null max-len) (plusp max-len))) (when objects (defaulting class-name (class-name (class-of (first objects)))) (let* ((class (find-class class-name)) (slotdefs (%update-objects-joins-slot-defs class slots))) (loop for slotdef in slotdefs ;; all the joins we will need for *all* the objects ;; which then get filtered below for each object for joins = (unless (join-slot-info-value slotdef :target-slot) (get-joined-objects objects slotdef :force-p force-p :batch-size max-len)) do (loop for object in objects for these-joins = ;; the joins just for this object (filtered from above) ;; or retrieved via fault-join-target-slot (or (%object-joins-from-list object slotdef joins force-p) (when (join-slot-info-value slotdef :target-slot) (fault-join-target-slot class object slotdef))) ;; when this object has joined-objects copy them in to the correct slot do (when these-joins (setf (easy-slot-value object slotdef) (if (join-slot-info-value slotdef :set) these-joins (first these-joins)))))))) (values)) (defun fault-join-slot-raw (class object slot-def) (let* ((dbi (view-class-slot-db-info slot-def)) (jc (gethash :join-class dbi))) (let ((jq (join-qualifier class object slot-def))) (when jq (select jc :where jq :flatp t :result-types nil :database (choose-database-for-instance object)))))) (defun fault-join-slot (class object slot-def) (let* ((dbi (view-class-slot-db-info slot-def)) (ts (gethash :target-slot dbi)) (dbi-set (gethash :set dbi))) (if (and ts dbi-set) (fault-join-target-slot class object slot-def) (let ((res (fault-join-slot-raw class object slot-def))) (when res (cond ((and ts (not dbi-set)) (mapcar (lambda (obj) (slot-value obj ts)) res)) ((and (not ts) (not dbi-set)) (car res)) ((and (not ts) dbi-set) res))))))) (defun update-fault-join-normalized-slot (class object slot-def) (if (and (normalizedp class) (key-slot-p slot-def)) (setf (easy-slot-value object slot-def) (normalized-key-value object)) (update-slot-from-record object slot-def))) (defun all-home-keys-have-values-p (object slot-def) "Do all of the home-keys have values ?" (let ((home-keys (join-slot-info-value slot-def :home-key))) (loop for key in (listify home-keys) always (easy-slot-value object key)))) (defun join-qualifier (class object slot-def) "Builds the join where clause based on the keys of the join slot and values of the object" (declare (ignore class)) (let* ((jc (join-slot-class slot-def)) ;;(ts (gethash :target-slot dbi)) ;;(tsdef (if ts (slotdef-for-slot-with-class ts jc))) (foreign-keys (listify (join-slot-info-value slot-def :foreign-key))) (home-keys (listify (join-slot-info-value slot-def :home-key)))) (when (all-home-keys-have-values-p object slot-def) (clsql-ands (loop for hk in home-keys for fk in foreign-keys for fksd = (slotdef-for-slot-with-class fk jc) for fk-sql = (typecase fk (symbol (sql-expression :attribute (database-identifier fksd nil) :table (database-identifier jc nil))) (t fk)) for hk-val = (typecase hk ((or symbol view-class-effective-slot-definition view-class-direct-slot-definition) (easy-slot-value object hk)) (t hk)) collect (sql-operation '== fk-sql hk-val)))))) (defmethod select-table-sql-expr ((table T)) "Turns an object representing a table into the :from part of the sql expression that will be executed " (sql-expression :table (view-table table))) (defun select-reference-equal (r1 r2) "determines if two sql select references are equal using database identifier equal" (flet ((id-of (r) (etypecase r (cons (cdr r)) (sql-ident-attribute r)))) (database-identifier-equal (id-of r1) (id-of r2)))) (defun join-slot-qualifier (class join-slot) "Creates a sql-expression expressing the join between the home-key on the table and its respective key on the joined-to-table" (sql-operation '== (sql-expression :attribute (join-slot-info-value join-slot :foreign-key) :table (view-table (join-slot-class join-slot))) (sql-expression :attribute (join-slot-info-value join-slot :home-key) :table (view-table class)))) (defun all-immediate-join-classes-for (classes) "returns a list of all join-classes needed for a list of classes" (loop for class in (listify classes) appending (loop for slot in (immediate-join-slots class) collect (join-slot-class slot)))) (defun %tables-for-query (classes from where inner-joins) "Given lists of classes froms wheres and inner-join compile a list of tables that should appear in the FROM section of the query. This includes any immediate join classes from each of the classes" (let ((inner-join-tables (collect-table-refs (listify inner-joins)))) (loop for tbl in (append (mapcar #'select-table-sql-expr classes) (mapcar #'select-table-sql-expr (all-immediate-join-classes-for classes)) (collect-table-refs (listify where)) (collect-table-refs (listify from))) when (and tbl (not (find tbl rtn :test #'database-identifier-equal)) ;; TODO: inner-join is currently hacky as can be (not (find tbl inner-join-tables :test #'database-identifier-equal))) collect tbl into rtn finally (return rtn)))) (defclass select-list () ((view-class :accessor view-class :initarg :view-class :initform nil) (select-list :accessor select-list :initarg :select-list :initform nil) (slot-list :accessor slot-list :initarg :slot-list :initform nil) (joins :accessor joins :initarg :joins :initform nil) (join-slots :accessor join-slots :initarg :join-slots :initform nil)) (:documentation "Collects the classes, slots and their respective sql representations so that update-instance-from-recors, find-all, build-objects can share this info and calculate it once. Joins are select-lists for each immediate join-slot but only if make-select-list is called with do-joins-p")) (defmethod view-table ((o select-list)) (view-table (view-class o))) (defmethod sql-table ((o select-list)) (sql-expression :table (view-table o))) (defun make-select-list (class-and-slots &key (do-joins-p nil)) "Make a select-list for the current class (or class-and-slots) object." (let* ((class-and-slots (etypecase class-and-slots (class-and-slots class-and-slots) ((or symbol standard-db-class) ;; find the first class with slots for us to select (this should be) ;; the first of its classes / parent-classes with slots (first (reverse (view-classes-and-storable-slots (to-class class-and-slots))))))) (class (view-class class-and-slots)) (join-slots (when do-joins-p (immediate-join-slots class)))) (multiple-value-bind (slots sqls) (loop for slot in (slot-defs class-and-slots) for sql = (generate-attribute-reference class slot) collect slot into slots collect sql into sqls finally (return (values slots sqls))) (unless slots (error "No slots of type :base in view-class ~A" (class-name class))) (make-instance 'select-list :view-class class :select-list sqls :slot-list slots :join-slots join-slots ;; only do a single layer of join objects :joins (when do-joins-p (loop for js in join-slots collect (make-select-list (join-slot-class js) :do-joins-p nil))))))) (defun full-select-list ( select-lists ) "Returns a list of sql-ref of things to select for the given classes THIS NEEDS TO MATCH THE ORDER OF build-objects " (loop for s in (listify select-lists) appending (select-list s) appending (loop for join in (joins s) appending (select-list join)))) (defun build-objects (select-lists row database &optional existing-instances) "Used by find-all to build objects. THIS NEEDS TO MATCH THE ORDER OF FULL-SELECT-LIST TODO: this caching scheme seems bad for a number of reasons * order is not guaranteed so references being held by one object might change to represent a different database row (seems HIGHLY suspect) * also join objects are overwritten rather than refreshed TODO: the way we handle immediate joins seems only valid if it is a single object. I suspect that making a :set :immediate join column would result in an invalid number of objects returned from the database, because there would be multiple rows per object, but we would return an object per row " (setf existing-instances (listify existing-instances)) (loop for select-list in select-lists for class = (view-class select-list) for existing = (pop existing-instances) for object = (or existing (make-instance class :view-database database)) do (loop for slot in (slot-list select-list) do (update-slot-from-db-value object slot (pop row))) do (loop for join-slot in (join-slots select-list) for join in (joins select-list) for join-class = (view-class join) for join-object = (setf (easy-slot-value object join-slot) (make-instance join-class)) do (loop for slot in (slot-list join) do (update-slot-from-db-value join-object slot (pop row)))) do (when existing (instance-refreshed object)) collect object)) (defun find-all (view-classes &rest args &key all set-operation distinct from where group-by having order-by offset limit refresh flatp result-types inner-join on (database *default-database*) instances parameters) "Called by SELECT to generate object query results when the View Classes VIEW-CLASSES are passed as arguments to SELECT. TODO: the caching scheme of passing in instances and overwriting their values seems bad for a number of reasons * order is not guaranteed so references being held by one object might change to represent a different database row (seems HIGHLY suspect) TODO: the way we handle immediate joins seems only valid if it is a single object. I suspect that making a :set :immediate join column would result in an invalid number of objects returned from the database, because there would be multiple objects returned from the database " (declare (ignore all set-operation group-by having offset limit on parameters distinct order-by) (dynamic-extent args)) (let* ((args (filter-plist args :from :where :flatp :additional-fields :result-types :instances)) (*db-deserializing* t) (sclasses (mapcar #'to-class view-classes)) (tables (%tables-for-query sclasses from where inner-join)) (join-where (loop for class in sclasses appending (loop for slot in (immediate-join-slots class) collect (join-slot-qualifier class slot)))) (select-lists (loop for class in sclasses collect (make-select-list class :do-joins-p t))) (full-select-list (full-select-list select-lists)) (where (clsql-ands (append (listify where) (listify join-where)))) #| (_ (format t "~&sclasses: ~W~%ijc: ~W~%tables: ~W~%" sclasses immediate-join-classes tables)) |# (rows (apply #'select (append full-select-list (list :from tables :result-types result-types :where where) args))) (return-objects (loop for row in rows for old-objs = (pop instances) for objs = (build-objects select-lists row database (when refresh old-objs)) collecting (if flatp (delist-if-single objs) objs)))) return-objects)) (defmethod instance-refreshed ((instance standard-db-object))) (defvar *default-caching* t "Controls whether SELECT caches objects by default. The CommonSQL specification states caching is on by default.") (defun select (&rest select-all-args) "Executes a query on DATABASE, which has a default value of *DEFAULT-DATABASE*, specified by the SQL expressions supplied using the remaining arguments in SELECT-ALL-ARGS. The SELECT argument can be used to generate queries in both functional and object oriented contexts. In the functional case, the required arguments specify the columns selected by the query and may be symbolic SQL expressions or strings representing attribute identifiers. Type modified identifiers indicate that the values selected from the specified column are converted to the specified lisp type. The keyword arguments ALL, DISTINCT, FROM, GROUP-by, HAVING, ORDER-BY, SET-OPERATION and WHERE are used to specify, using the symbolic SQL syntax, the corresponding components of the SQL query generated by the call to SELECT. RESULT-TYPES is a list of symbols which specifies the lisp type for each field returned by the query. If RESULT-TYPES is nil all results are returned as strings whereas the default value of :auto means that the lisp types are automatically computed for each field. FIELD-NAMES is t by default which means that the second value returned is a list of strings representing the columns selected by the query. If FIELD-NAMES is nil, the list of column names is not returned as a second value. In the object oriented case, the required arguments to SELECT are symbols denoting View Classes which specify the database tables to query. In this case, SELECT returns a list of View Class instances whose slots are set from the attribute values of the records in the specified table. Slot-value is a legal operator which can be employed as part of the symbolic SQL syntax used in the WHERE keyword argument to SELECT. REFRESH is nil by default which means that the View Class instances returned are retrieved from a cache if an equivalent call to SELECT has previously been issued. If REFRESH is true, the View Class instances returned are updated as necessary from the database and the generic function INSTANCE-REFRESHED is called to perform any necessary operations on the updated instances. In both object oriented and functional contexts, FLATP has a default value of nil which means that the results are returned as a list of lists. If FLATP is t and only one result is returned for each record selected in the query, the results are returned as elements of a list." (multiple-value-bind (target-args qualifier-args) (query-get-selections select-all-args) (unless (or *default-database* (getf qualifier-args :database)) (signal-no-database-error nil)) (let ((caching (getf qualifier-args :caching *default-caching*)) (result-types (getf qualifier-args :result-types :auto)) (refresh (getf qualifier-args :refresh nil)) (database (getf qualifier-args :database *default-database*))) (cond ((and target-args (every #'(lambda (arg) (and (symbolp arg) (find-class arg nil))) target-args)) (setf qualifier-args (filter-plist qualifier-args :caching :refresh :result-types)) ;; Add explicity table name to order-by if not specified and only ;; one selected table. This is required so FIND-ALL won't duplicate ;; the field (let ((order-by (getf qualifier-args :order-by))) (when (and order-by (= 1 (length target-args))) (let ((table-name (view-table (find-class (car target-args)))) (order-by-list (copy-seq (listify order-by)))) (labels ((sv (val name) (ignore-errors (slot-value val name))) (set-table-if-needed (val) (typecase val (sql-ident-attribute (handler-case (if (sv val 'qualifier) val (make-instance 'sql-ident-attribute :name (sv val 'name) :qualifier table-name)) (simple-error () ;; TODO: Check for a specific error we expect ))) (cons (cons (set-table-if-needed (car val)) (cdr val))) (t val)))) (setf order-by-list (loop for i from 0 below (length order-by-list) for id in order-by-list collect (set-table-if-needed id)))) (setf (getf qualifier-args :order-by) order-by-list)))) (cond ((null caching) (apply #'find-all target-args :result-types result-types :refresh refresh qualifier-args)) (t (let ((cached (records-cache-results target-args qualifier-args database))) (if (and cached (not refresh)) cached (let ((results (apply #'find-all target-args :result-types :auto :refresh refresh :instances cached qualifier-args))) (setf (records-cache-results target-args qualifier-args database) results) results)))))) (t (let* ((expr (apply #'make-query select-all-args)) (parameters (second (member :parameters select-all-args))) (specified-types (mapcar #'(lambda (attrib) (if (typep attrib 'sql-ident-attribute) (let ((type (slot-value attrib 'type))) (if type type t)) t)) (slot-value expr 'selections))) (flatp (getf qualifier-args :flatp)) (field-names (getf qualifier-args :field-names t))) (when parameters (setf expr (command-object (sql-output expr database) parameters))) (query expr :flatp flatp :result-types ;; specifying a type for an attribute overrides result-types (if (some #'(lambda (x) (not (eq t x))) specified-types) specified-types result-types) :field-names field-names :database database))))))) (defun compute-records-cache-key (targets qualifiers) (list targets (do ((args *select-arguments* (cdr args)) (results nil)) ((null args) results) (let* ((arg (car args)) (value (getf qualifiers arg))) (when value (push (list arg (typecase value (cons (cons (sql (car value)) (cdr value))) (%sql-expression (sql value)) (t value))) results)))))) (defun records-cache-results (targets qualifiers database) (when (record-caches database) (gethash (compute-records-cache-key targets qualifiers) (record-caches database)))) (defun (setf records-cache-results) (results targets qualifiers database) (unless (record-caches database) (setf (record-caches database) (make-weak-hash-table :test 'equal))) (setf (gethash (compute-records-cache-key (copy-list targets) qualifiers) (record-caches database)) results) results) ;;; Serialization functions (defun write-instance-to-stream (obj stream) "Writes an instance to a stream where it can be later be read. NOTE: an error will occur if a slot holds a value which can not be written readably." (let* ((class (class-of obj)) (alist '())) (dolist (slot (ordered-class-slots (class-of obj))) (let ((name (slot-definition-name slot))) (when (and (not (eq 'view-database name)) (slot-boundp obj name)) (push (cons name (slot-value obj name)) alist)))) (setq alist (reverse alist)) (write (cons (class-name class) alist) :stream stream :readably t)) obj) (defun read-instance-from-stream (stream) (let ((raw (read stream nil nil))) (when raw (let ((obj (make-instance (car raw)))) (dolist (pair (cdr raw)) (setf (slot-value obj (car pair)) (cdr pair))) obj)))) cl-sql-6.4.1/sql/fddl.lisp0000644000175000017500000004760511636413404014346 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; ;;;; The CLSQL Functional Data Definition Language (FDDL) ;;;; including functions for schema manipulation. Currently supported ;;;; SQL objects include tables, views, indexes, attributes and ;;;; sequences. ;;;; ;;;; This file is part of CLSQL. ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* (in-package #:clsql-sys) ;; Truncate database (defun truncate-database (&key (database *default-database*)) "Drops all tables, views, indexes and sequences in DATABASE which defaults to *DEFAULT-DATABASE*." (unless (typep database 'database) (signal-no-database-error database)) (unless (is-database-open database) (database-reconnect database)) (when (eq :oracle (database-type database)) (ignore-errors (execute-command "PURGE RECYCLEBIN" :database database))) (when (db-type-has-views? (database-underlying-type database)) (dolist (view (list-views :database database)) (drop-view view :database database))) (dolist (table (list-tables :database database)) (drop-table table :database database)) (dolist (index (list-indexes :database database)) (drop-index index :database database)) (dolist (seq (list-sequences :database database)) (drop-sequence seq :database database)) (when (eq :oracle (database-type database)) (ignore-errors (execute-command "PURGE RECYCLEBIN" :database database))) (values)) ;; Tables (defun create-table (name description &key (database *default-database*) (constraints nil) (transactions t)) "Creates a table called NAME, which may be a string, symbol or SQL table identifier, in DATABASE which defaults to *DEFAULT-DATABASE*. DESCRIPTION is a list whose elements are lists containing the attribute names, types, and other constraints such as not-null or primary-key for each column in the table. CONSTRAINTS is a string representing an SQL table constraint expression or a list of such strings. With MySQL databases, if TRANSACTIONS is t an InnoDB table is created which supports transactions." (execute-command (make-instance 'sql-create-table :name name :columns description :modifiers constraints :transactions transactions) :database database)) (defun drop-table (name &key (if-does-not-exist :error) (database *default-database*) (owner nil)) "Drops the table called NAME from DATABASE which defaults to *DEFAULT-DATABASE*. If the table does not exist and IF-DOES-NOT-EXIST is :ignore then DROP-TABLE returns nil whereas an error is signalled if IF-DOES-NOT-EXIST is :error." (ecase if-does-not-exist (:ignore (unless (table-exists-p name :database database :owner owner) (return-from drop-table nil))) (:error t)) (let ((expr (concatenate 'string "DROP TABLE " (escaped-database-identifier name database)))) ;; Fixme: move to clsql-oracle (when (and (find-package 'clsql-oracle) (eq :oracle (database-type database)) (eql 10 (slot-value database (intern (symbol-name '#:major-server-version) (symbol-name '#:clsql-oracle))))) (setq expr (concatenate 'string expr " PURGE"))) (execute-command expr :database database))) (defun list-tables (&key (owner nil) (database *default-database*)) "Returns a list of strings representing table names in DATABASE which defaults to *DEFAULT-DATABASE*. OWNER is nil by default which means that only tables owned by users are listed. If OWNER is a string denoting a user name, only tables owned by OWNER are listed. If OWNER is :all then all tables are listed." (database-list-tables database :owner owner)) (defmethod %table-exists-p (name (database T) &key owner ) (unless database (setf database *default-database*)) (let ((name (database-identifier name database)) (tables (list-tables :owner owner :database database))) (when (member name tables :test #'database-identifier-equal) t))) (defun table-exists-p (name &key (owner nil) (database *default-database*)) "Tests for the existence of an SQL table called NAME in DATABASE which defaults to *DEFAULT-DATABASE*. OWNER is nil by default which means that only tables owned by users are examined. If OWNER is a string denoting a user name, only tables owned by OWNER are examined. If OWNER is :all then all tables are examined." (%table-exists-p name database :owner owner)) ;; Views (defun create-view (name &key as column-list (with-check-option nil) (database *default-database*)) "Creates a view called NAME in DATABASE which defaults to *DEFAULT-DATABASE*. The view is created using the query AS and the columns of the view may be specified using the COLUMN-LIST parameter. The WITH-CHECK-OPTION is nil by default but if it has a non-nil value, then all insert/update commands on the view are checked to ensure that the new data satisfy the query AS." (let* ((view-name (database-identifier name)) (stmt (make-instance 'sql-create-view :name view-name :column-list column-list :query as :with-check-option with-check-option))) (execute-command stmt :database database))) (defun drop-view (name &key (if-does-not-exist :error) (database *default-database*)) "Drops the view called NAME from DATABASE which defaults to *DEFAULT-DATABASE*. If the view does not exist and IF-DOES-NOT-EXIST is :ignore then DROP-VIEW returns nil whereas an error is signalled if IF-DOES-NOT-EXIST is :error." (ecase if-does-not-exist (:ignore (unless (view-exists-p name :database database) (return-from drop-view))) (:error t)) (let ((expr (concatenate 'string "DROP VIEW " (escaped-database-identifier name database)))) (execute-command expr :database database))) (defun list-views (&key (owner nil) (database *default-database*)) "Returns a list of strings representing view names in DATABASE which defaults to *DEFAULT-DATABASE*. OWNER is nil by default which means that only views owned by users are listed. If OWNER is a string denoting a user name, only views owned by OWNER are listed. If OWNER is :all then all views are listed." (database-list-views database :owner owner)) (defun view-exists-p (name &key (owner nil) (database *default-database*)) "Tests for the existence of an SQL view called NAME in DATABASE which defaults to *DEFAULT-DATABASE*. OWNER is nil by default which means that only views owned by users are examined. If OWNER is a string denoting a user name, only views owned by OWNER are examined. If OWNER is :all then all views are examined." (when (member (database-identifier name database) (list-views :owner owner :database database) :test #'database-identifier-equal) t)) ;; Indexes (defun create-index (name &key on (unique nil) attributes (database *default-database*)) "Creates an index called NAME on the table specified by ON in DATABASE which default to *DEFAULT-DATABASE*. The table attributes to use in constructing the index NAME are specified by ATTRIBUTES. The UNIQUE argument is nil by default but if it has a non-nil value then the indexed attributes must have unique values." (let* ((index-name (escaped-database-identifier name database)) (table-name (escaped-database-identifier on database)) (attributes (mapcar #'(lambda (a) (escaped-database-identifier a database)) (listify attributes))) (stmt (format nil "CREATE ~A INDEX ~A ON ~A (~{~A~^, ~})" (if unique "UNIQUE" "") index-name table-name attributes))) (execute-command stmt :database database))) (defun drop-index (name &key (if-does-not-exist :error) (on nil) (database *default-database*)) "Drops the index called NAME in DATABASE which defaults to *DEFAULT-DATABASE*. If the index does not exist and IF-DOES-NOT-EXIST is :ignore then DROP-INDEX returns nil whereas an error is signalled if IF-DOES-NOT-EXIST is :error. The argument ON allows the optional specification of a table to drop the index from." (ecase if-does-not-exist (:ignore (unless (index-exists-p name :database database) (return-from drop-index))) (:error t)) (let* ((db-type (database-underlying-type database)) (on (when on (escaped-database-identifier on database))) (index-name (escaped-database-identifier name database)) (index-identifier (cond ((db-type-use-fully-qualified-column-on-drop-index? db-type) (format nil "~A.~A" on index-name)) ((db-type-use-column-on-drop-index? db-type) (format nil "~A ON ~A" index-name on)) (t index-name)))) (execute-command (format nil "DROP INDEX ~A" index-identifier) :database database))) (defun list-indexes (&key (owner nil) (database *default-database*) (on nil)) "Returns a list of strings representing index names in DATABASE which defaults to *DEFAULT-DATABASE*. OWNER is nil by default which means that only indexes owned by users are listed. If OWNER is a string denoting a user name, only indexes owned by OWNER are listed. If OWNER is :all then all indexes are listed. The keyword argument ON limits the results to indexes on the specified tables. Meaningful values for ON are nil (the default) which means that all tables are considered, a string, symbol or SQL expression representing a table name in DATABASE or a list of such table identifiers." (if (null on) (database-list-indexes database :owner owner) (let ((tables (typecase on (cons on) (t (list on))))) (reduce #'append (mapcar #'(lambda (table) (database-list-table-indexes table database :owner owner)) tables))))) (defun index-exists-p (name &key (owner nil) (database *default-database*)) "Tests for the existence of an SQL index called NAME in DATABASE which defaults to *DEFAULT-DATABASE*. OWNER is nil by default which means that only indexes owned by users are examined. If OWNER is a string denoting a user name, only indexes owned by OWNER are examined. If OWNER is :all then all indexes are examined." (when (member (database-identifier name database) (list-indexes :owner owner :database database) :test #'database-identifier-equal) t)) ;; Attributes (defvar *cache-table-queries-default* nil "Specifies the default behaivour for caching of attribute types. Meaningful values are t, nil and :flush as described for the action argument to CACHE-TABLE-QUERIES.") (defun cache-table-queries (table &key (action nil) (database *default-database*)) "Controls the caching of attribute type information on the table specified by TABLE in DATABASE which defaults to *DEFAULT-DATABASE*. ACTION specifies the caching behaviour to adopt. If its value is t then attribute type information is cached whereas if its value is nil then attribute type information is not cached. If ACTION is :flush then all existing type information in the cache for TABLE is removed, but caching is still enabled. TABLE may be a string representing a table for which the caching action is to be taken while the caching action is applied to all tables if TABLE is t. Alternativly, when TABLE is :default, the default caching action specified by *CACHE-TABLE-QUERIES-DEFAULT* is applied to all table for which a caching action has not been explicitly set." (with-slots (attribute-cache) database (cond ((stringp table) (multiple-value-bind (val found) (gethash table attribute-cache) (cond ((and found (eq action :flush)) (setf (gethash table attribute-cache) (list t nil))) ((and found (eq action t)) (setf (gethash table attribute-cache) (list t (second val)))) ((and found (null action)) (setf (gethash table attribute-cache) (list nil nil))) ((not found) (setf (gethash table attribute-cache) (list action nil)))))) ((eq table t) (maphash (lambda (k v) (cond ((eq action :flush) (setf (gethash k attribute-cache) (list t nil))) ((null action) (setf (gethash k attribute-cache) (list nil nil))) ((eq t action) (setf (gethash k attribute-cache) (list t (second v)))))) attribute-cache)) ((eq table :default) (maphash (lambda (k v) (when (eq (first v) :unspecified) (cond ((eq action :flush) (setf (gethash k attribute-cache) (list t nil))) ((null action) (setf (gethash k attribute-cache) (list nil nil))) ((eq t action) (setf (gethash k attribute-cache) (list t (second v))))))) attribute-cache)))) (values)) (defun list-attributes (name &key (owner nil) (database *default-database*)) "Returns a list of strings representing the attributes of table NAME in DATABASE which defaults to *DEFAULT-DATABASE*. OWNER is nil by default which means that only attributes owned by users are listed. If OWNER is a string denoting a user name, only attributes owned by OWNER are listed. If OWNER is :all then all attributes are listed." (database-list-attributes (database-identifier name database) database :owner owner)) (defun attribute-type (attribute table &key (owner nil) (database *default-database*)) "Returns a keyword representing the vendor-specific field type of the supplied attribute ATTRIBUTE in the table specified by TABLE in DATABASE which defaults to *DEFAULT-DATABASE*. OWNER is nil by default which means that the attribute specified by ATTRIBUTE, if it exists, must be user owned else nil is returned. If OWNER is a string denoting a user name, the attribute, if it exists, must be owned by OWNER else nil is returned, whereas if OWNER is :all then the attribute, if it exists, will be returned regardless of its owner." (database-attribute-type (database-identifier attribute database) (database-identifier table database) database :owner owner)) (defun list-attribute-types (table &key (owner nil) (database *default-database*)) "Returns a list containing information about the SQL types of each of the attributes in the table specified by TABLE in DATABASE which has a default value of *DEFAULT-DATABASE*. OWNER is nil by default which means that only attributes owned by users are listed. If OWNER is a string denoting a user name, only attributes owned by OWNER are listed. If OWNER is :all then all attributes are listed. The elements of the returned list are lists where the first element is the name of the attribute, the second element is its SQL type, the third is the type precision, the fourth is the scale of the attribute and the fifth is 1 if the attribute accepts null values and otherwise 0." (with-slots (attribute-cache) database (let ((table-ident (database-identifier table database))) (multiple-value-bind (val found) (gethash table-ident attribute-cache) (if (and found (second val)) (second val) (let ((types (mapcar #'(lambda (attribute) (cons attribute (multiple-value-list (database-attribute-type (database-identifier attribute database) table-ident database :owner owner)))) (list-attributes table :database database :owner owner)))) (cond ((and (not found) (eq t *cache-table-queries-default*)) (setf (gethash table-ident attribute-cache) (list :unspecified types))) ((and found (eq t (first val)) (setf (gethash table-ident attribute-cache) (list t types))))) types)))))) ;; Sequences (defun create-sequence (name &key (database *default-database*)) "Creates a sequence called NAME in DATABASE which defaults to *DEFAULT-DATABASE*." (let ((sequence-name (database-identifier name database))) (database-create-sequence sequence-name database)) (values)) (defun drop-sequence (name &key (if-does-not-exist :error) (database *default-database*)) "Drops the sequence called NAME from DATABASE which defaults to *DEFAULT-DATABASE*. If the sequence does not exist and IF-DOES-NOT-EXIST is :ignore then DROP-SEQUENCE returns nil whereas an error is signalled if IF-DOES-NOT-EXIST is :error." (ecase if-does-not-exist (:ignore (unless (sequence-exists-p name :database database) (return-from drop-sequence))) (:error t)) (database-drop-sequence name database) (values)) (defun list-sequences (&key (owner nil) (database *default-database*)) "Returns a list of strings representing sequence names in DATABASE which defaults to *DEFAULT-DATABASE*. OWNER is nil by default which means that only sequences owned by users are listed. If OWNER is a string denoting a user name, only sequences owned by OWNER are listed. If OWNER is :all then all sequences are listed." (database-list-sequences database :owner owner)) (defun sequence-exists-p (name &key (owner nil) (database *default-database*)) "Tests for the existence of an SQL sequence called NAME in DATABASE which defaults to *DEFAULT-DATABASE*. OWNER is nil by default which means that only sequences owned by users are examined. If OWNER is a string denoting a user name, only sequences owned by OWNER are examined. If OWNER is :all then all sequences are examined." (let ((seqs (list-sequences :owner owner :database database)) ;; handle symbols, we know the db will return strings (n1 (database-identifier name database)) (n2 (%sequence-name-to-table name database))) (when (or (member n1 seqs :test #'database-identifier-equal) (member n2 seqs :test #'database-identifier-equal)) t))) (defun sequence-next (name &key (database *default-database*)) "Increment and return the next value in the sequence called NAME in DATABASE which defaults to *DEFAULT-DATABASE*." (database-sequence-next (database-identifier name database) database)) (defun set-sequence-position (name position &key (database *default-database*)) "Explicitly set the the position of the sequence called NAME in DATABASE, which defaults to *DEFAULT-DATABASE*, to POSITION which is returned." (database-set-sequence-position (database-identifier name database) position database)) (defun sequence-last (name &key (database *default-database*)) "Return the last value allocated in the sequence called NAME in DATABASE which defaults to *DEFAULT-DATABASE*." (database-sequence-last (database-identifier name database) database)) cl-sql-6.4.1/sql/expressions.lisp0000644000175000017500000012276312064366222016017 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; ;;;; Classes defining SQL expressions and methods for formatting the ;;;; appropriate SQL commands. ;;;; ;;;; This file is part of CLSQL. ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* (in-package #:clsql-sys) (defvar +empty-string+ "''") (defvar +null-string+ "NULL") (defvar *sql-stream* nil "stream which accumulates SQL output") (defclass %database-identifier () ((escaped :accessor escaped :initarg :escaped :initform nil) (unescaped :accessor unescaped :initarg :unescaped :initform nil)) (:documentation "A database identifier represents a string/symbol ready to be spliced into a sql string. It keeps references to both the escaped and unescaped versions so that unescaped versions can be compared to the results of list-tables/views/attributes etc. It also allows you to be sure that an identifier is escaped only once. (escaped-database-identifiers *any-reasonable-object*) should be called to produce a string that is safe to splice directly into sql strings. (unescaped-database-identifier *any-reasonable-object*) is generally what you pass to it with the exception that symbols have been clsql-sys:sql-escape which converts to a string and changes - to _ (so that unescaped can be compared to the results of eg: list-tables) ")) (defmethod escaped ((it null)) it) (defmethod unescaped ((it null)) it) (defun database-identifier-equal (i1 i2 &optional (database clsql-sys:*default-database*)) (setf i1 (database-identifier i1 database) i2 (database-identifier i2 database)) (flet ((cast (i) (if (symbolp (unescaped i)) (sql-escape (unescaped i)) (unescaped i)))) (or ;; check for an exact match (equal (escaped-database-identifier i1) (escaped-database-identifier i2)) ;; check for an inexact match if we had symbols in the mix (string-equal (cast i1) (cast i2))))) (defun delistify-dsd (list) "Some MOPs, like openmcl 0.14.2, cons attribute values in a list." (if (and (listp list) (null (cdr list))) (car list) list)) (defun special-char-p (s) "Check if a string has any special characters" (loop for char across s thereis (find char '(#\space #\, #\. #\! #\@ #\# #\$ #\% #\' #\" #\^ #\& #\* #\| #\( #\) #\- #\+ #\< #\> #\{ #\})))) (defun special-cased-symbol-p (sym) "Should the symbols case be preserved, or should we convert to default casing" (let ((name (symbol-name sym))) (case (readtable-case *readtable*) (:upcase (not (string= (string-upcase name) name))) (:downcase (not (string= (string-downcase name) name))) (t t)))) (defun %make-database-identifier (inp &optional database) "We want to quote an identifier if it came to us as a string or if it has special characters in it." (labels ((%escape-identifier (inp &optional orig) "Quote an identifier unless it is already quoted" (cond ;; already quoted ((and (eql #\" (elt inp 0)) (eql #\" (elt inp (- (length inp) 1)))) (make-instance '%database-identifier :unescaped (or orig inp) :escaped inp)) (T (make-instance '%database-identifier :unescaped (or orig inp) :escaped (concatenate 'string "\"" (replace-all inp "\"" "\\\"") "\"")))))) (typecase inp (string (%escape-identifier inp)) (%database-identifier inp) (symbol (let ((s (sql-escape inp))) (if (and (not (eql '* inp)) (special-char-p s)) (%escape-identifier (if (special-cased-symbol-p inp) s (convert-to-db-default-case s database)) inp) (make-instance '%database-identifier :escaped s :unescaped inp)) ))))) (defun combine-database-identifiers (ids &optional (database clsql-sys:*default-database*) &aux res all-sym? pkg) "Create a new database identifier by combining parts in a reasonable way " (setf ids (mapcar #'database-identifier ids) all-sym? (every (lambda (i) (symbolp (unescaped i))) ids) pkg (when all-sym? (symbol-package (unescaped (first ids))))) (labels ((cast ( i ) (typecase i (null nil) (%database-identifier (cast (unescaped i))) (symbol (if all-sym? (sql-escape i) (convert-to-db-default-case (sql-escape i) database))) (string i))) (comb (i1 i2) (setf i1 (cast i1) i2 (cast i2)) (if (and i1 i2) (concatenate 'string (cast i1) "_" (cast i2)) (or i1 i2)))) (setf res (reduce #'comb ids)) (database-identifier (if all-sym? (intern res pkg) res) database))) (defun escaped-database-identifier (name &optional database find-class-p) (escaped (database-identifier name database find-class-p))) (defun unescaped-database-identifier (name &optional database find-class-p) (unescaped (database-identifier name database find-class-p))) (defun sql-output (sql-expr &optional (database *default-database*)) "Top-level call for generating SQL strings. Returns an SQL string appropriate for DATABASE which corresponds to the supplied lisp expression SQL-EXPR." (with-output-to-string (*sql-stream*) (output-sql sql-expr database))) (defmethod output-sql (expr database) (write-string (database-output-sql expr database) *sql-stream*) (values)) (defvar *output-hash* (make-weak-hash-table :test #'equal) "For caching generated SQL strings, set to NIL to disable." ) (defmethod output-sql :around ((sql t) database) (if (null *output-hash*) (call-next-method) (let* ((hash-key (output-sql-hash-key sql database)) (hash-value (when hash-key (gethash hash-key *output-hash*)))) (cond ((and hash-key hash-value) (write-string hash-value *sql-stream*)) (hash-key (let ((*sql-stream* (make-string-output-stream))) (call-next-method) (setf hash-value (get-output-stream-string *sql-stream*)) (setf (gethash hash-key *output-hash*) hash-value)) (write-string hash-value *sql-stream*)) (t (call-next-method)))))) (defmethod output-sql-hash-key (expr database) (declare (ignore expr database)) nil) (defclass %sql-expression () ()) (defmethod output-sql ((expr %sql-expression) database) (declare (ignore database)) (write-string +null-string+ *sql-stream*)) (defmethod print-object ((self %sql-expression) stream) (print-unreadable-object (self stream :type t) (write-string (sql-output self) stream)) self) ;; For straight up strings (defclass sql (%sql-expression) ((text :initarg :string :initform "")) (:documentation "A literal SQL expression.")) (defmethod make-load-form ((sql sql) &optional environment) (declare (ignore environment)) (with-slots (text) sql `(make-instance 'sql :string ',text))) (defmethod output-sql ((expr sql) database) (declare (ignore database)) (write-string (slot-value expr 'text) *sql-stream*) t) (defmethod print-object ((ident sql) stream) (format stream "#<~S \"~A\">" (type-of ident) (sql-output ident nil)) ident) ;; For SQL Identifiers of generic type (defclass sql-ident (%sql-expression) ((name :initarg :name :initform +null-string+)) (:documentation "An SQL identifer.")) (defmethod make-load-form ((sql sql-ident) &optional environment) (declare (ignore environment)) (with-slots (name) sql `(make-instance 'sql-ident :name ',name))) (defmethod output-sql ((expr %database-identifier) database) (write-string (escaped expr) *sql-stream*)) (defmethod output-sql ((expr sql-ident) database) (with-slots (name) expr (write-string (escaped-database-identifier name database) *sql-stream*)) t) ;; For SQL Identifiers for attributes (defclass sql-ident-attribute (sql-ident) ((qualifier :initarg :qualifier :initform +null-string+) (type :initarg :type :initform +null-string+)) (:documentation "An SQL Attribute identifier.")) (defmethod collect-table-refs (sql) (declare (ignore sql)) nil) (defmethod collect-table-refs ((sql list)) (loop for i in sql appending (listify (collect-table-refs i)))) (defmethod collect-table-refs ((sql sql-ident-attribute)) (let ((qual (slot-value sql 'qualifier))) (when qual ;; going to be used as a table, search classes (list (make-instance 'sql-ident-table :name (database-identifier qual nil t)))))) (defmethod make-load-form ((sql sql-ident-attribute) &optional environment) (declare (ignore environment)) (with-slots (qualifier type name) sql `(make-instance 'sql-ident-attribute :name ',name :qualifier ',qualifier :type ',type))) (defmethod output-sql-hash-key ((expr sql-ident-attribute) database) (with-slots (qualifier name type) expr (list (and database (database-underlying-type database)) 'sql-ident-attribute (unescaped-database-identifier qualifier) (unescaped-database-identifier name) type))) ;; For SQL Identifiers for tables (defclass sql-ident-table (sql-ident) ((alias :initarg :table-alias :initform nil)) (:documentation "An SQL table identifier.")) (defmethod make-load-form ((sql sql-ident-table) &optional environment) (declare (ignore environment)) (with-slots (alias name) sql `(make-instance 'sql-ident-table :name ',name :table-alias ',alias))) (defmethod collect-table-refs ((sql sql-ident-table)) (list sql)) (defmethod output-sql ((expr sql-ident-table) database) (with-slots (name alias) expr (flet ((p (s) ;; the etypecase is in sql-escape too (write-string (escaped-database-identifier s database) *sql-stream*))) (p name) (when alias (princ #\space *sql-stream*) (p alias)))) t) (defmethod output-sql ((expr sql-ident-attribute) database) ;;; KMR: The TYPE field is used by CommonSQL for type conversion -- it ;;; should not be output in SQL statements (let ((*print-pretty* nil)) (with-slots (qualifier name type) expr (format *sql-stream* "~@[~a.~]~a" (when qualifier ;; check for classes (escaped-database-identifier qualifier database T)) (escaped-database-identifier name database)) t))) (defmethod output-sql-hash-key ((expr sql-ident-table) database) (with-slots (name alias) expr (list (and database (database-underlying-type database)) 'sql-ident-table (unescaped-database-identifier name) (unescaped-database-identifier alias)))) (defclass sql-relational-exp (%sql-expression) ((operator :initarg :operator :initform nil) (sub-expressions :initarg :sub-expressions :initform nil)) (:documentation "An SQL relational expression.")) (defmethod make-load-form ((self sql-relational-exp) &optional environment) (make-load-form-saving-slots self :slot-names '(operator sub-expressions) :environment environment)) (defmethod collect-table-refs ((sql sql-relational-exp)) (let ((tabs nil)) (dolist (exp (slot-value sql 'sub-expressions)) (let ((refs (collect-table-refs exp))) (if refs (setf tabs (append refs tabs))))) (remove-duplicates tabs :test #'database-identifier-equal))) ;; Write SQL for relational operators (like 'AND' and 'OR'). ;; should do arity checking of subexpressions (defun %write-operator (operator database) (typecase operator (string (write-string operator *sql-stream*)) (symbol (write-string (symbol-name operator) *sql-stream*)) (T (output-sql operator database)))) (defmethod output-sql ((expr sql-relational-exp) database) (with-slots (operator sub-expressions) expr ;; we do this as two runs so as not to emit confusing superflous parentheses ;; The first loop renders all the child outputs so that we can skip anding with ;; empty output (which causes sql errors) ;; the next loop simply emits each sub-expression with the appropriate number of ;; parens and operators (flet ((trim (sub) (string-trim +whitespace-chars+ (with-output-to-string (*sql-stream*) (output-sql sub database))))) (let ((str-subs (loop for sub in sub-expressions for str-sub = (trim sub) when (and str-sub (> (length str-sub) 0)) collect str-sub))) (case (length str-subs) (0 nil) (1 (write-string (first str-subs) *sql-stream*)) (t (write-char #\( *sql-stream*) (write-string (first str-subs) *sql-stream*) (loop for str-sub in (rest str-subs) do (write-char #\Space *sql-stream*) ;; do this so that symbols can be output as database identifiers ;; rather than allowing symbols to inject sql (%write-operator operator database) (write-char #\Space *sql-stream*) (write-string str-sub *sql-stream*)) (write-char #\) *sql-stream*)) )))) t) (defclass sql-upcase-like (sql-relational-exp) () (:documentation "An SQL 'like' that upcases its arguments.")) (defmethod output-sql ((expr sql-upcase-like) database) (flet ((write-term (term) (write-string "upper(" *sql-stream*) (output-sql term database) (write-char #\) *sql-stream*))) (with-slots (sub-expressions) expr (let ((subs (if (consp (car sub-expressions)) (car sub-expressions) sub-expressions))) (write-char #\( *sql-stream*) (do ((sub subs (cdr sub))) ((null (cdr sub)) (write-term (car sub))) (write-term (car sub)) (write-string " LIKE " *sql-stream*)) (write-char #\) *sql-stream*)))) t) (defclass sql-assignment-exp (sql-relational-exp) () (:documentation "An SQL Assignment expression.")) (defmethod output-sql ((expr sql-assignment-exp) database) (with-slots (operator sub-expressions) expr (do ((sub sub-expressions (cdr sub))) ((null (cdr sub)) (output-sql (car sub) database)) (output-sql (car sub) database) (write-char #\Space *sql-stream*) (%write-operator operator database) (write-char #\Space *sql-stream*))) t) (defclass sql-value-exp (%sql-expression) ((modifier :initarg :modifier :initform nil) (components :initarg :components :initform nil)) (:documentation "An SQL value expression.") ) (defmethod collect-table-refs ((sql sql-value-exp)) (let ((tabs nil)) (if (listp (slot-value sql 'components)) (progn (dolist (exp (slot-value sql 'components)) (let ((refs (collect-table-refs exp))) (if refs (setf tabs (append refs tabs))))) (remove-duplicates tabs :test #'database-identifier-equal)) nil))) (defmethod output-sql ((expr sql-value-exp) database) (with-slots (modifier components) expr (if modifier (progn (write-char #\( *sql-stream*) (cond ((sql-operator modifier) (%write-operator modifier database)) ((or (stringp modifier) (symbolp modifier)) (write-string (escaped-database-identifier modifier) *sql-stream*)) (t (output-sql modifier database))) (write-char #\Space *sql-stream*) (output-sql components database) (write-char #\) *sql-stream*)) (output-sql components database)))) (defclass sql-typecast-exp (sql-value-exp) () (:documentation "An SQL typecast expression.")) (defmethod output-sql ((expr sql-typecast-exp) database) (with-slots (components) expr (output-sql components database))) (defmethod collect-table-refs ((sql sql-typecast-exp)) (when (slot-value sql 'components) (collect-table-refs (slot-value sql 'components)))) (defclass sql-function-exp (%sql-expression) ((name :initarg :name :initform nil) (args :initarg :args :initform nil)) (:documentation "An SQL function expression.")) (defmethod collect-table-refs ((sql sql-function-exp)) (let ((tabs nil)) (dolist (exp (slot-value sql 'args)) (let ((refs (collect-table-refs exp))) (if refs (setf tabs (append refs tabs))))) (remove-duplicates tabs :test #'database-identifier-equal))) (defvar *in-subselect* nil) (defmethod output-sql ((expr sql-function-exp) database) (with-slots (name args) expr (typecase name ((or string symbol) (write-string (escaped-database-identifier name) *sql-stream*)) (t (output-sql name database))) (let ((*in-subselect* nil)) ;; aboid double parens (when args (output-sql args database)))) t) (defclass sql-between-exp (sql-function-exp) () (:documentation "An SQL between expression.")) (defmethod output-sql ((expr sql-between-exp) database) (with-slots (args) expr (output-sql (first args) database) (write-string " BETWEEN " *sql-stream*) (output-sql (second args) database) (write-string " AND " *sql-stream*) (output-sql (third args) database)) t) (defclass sql-query-modifier-exp (%sql-expression) ((modifier :initarg :modifier :initform nil) (components :initarg :components :initform nil)) (:documentation "An SQL query modifier expression.")) (defmethod output-sql ((expr sql-query-modifier-exp) database) (with-slots (modifier components) expr (%write-operator modifier database) (write-string " " *sql-stream*) (%write-operator (car components) database) (when components (mapc #'(lambda (comp) (write-string ", " *sql-stream*) (output-sql comp database)) (cdr components)))) t) (defclass sql-set-exp (%sql-expression) ((operator :initarg :operator :initform nil) (sub-expressions :initarg :sub-expressions :initform nil)) (:documentation "An SQL set expression.")) (defmethod collect-table-refs ((sql sql-set-exp)) (let ((tabs nil)) (dolist (exp (slot-value sql 'sub-expressions)) (let ((refs (collect-table-refs exp))) (if refs (setf tabs (append refs tabs))))) (remove-duplicates tabs :test #'database-identifier-equal))) (defmethod output-sql ((expr sql-set-exp) database) (with-slots (operator sub-expressions) expr (let ((subs (if (consp (car sub-expressions)) (car sub-expressions) sub-expressions))) (when (= (length subs) 1) (%write-operator operator database) (write-char #\Space *sql-stream*)) (do ((sub subs (cdr sub))) ((null (cdr sub)) (output-sql (car sub) database)) (output-sql (car sub) database) (write-char #\Space *sql-stream*) (%write-operator operator database) (write-char #\Space *sql-stream*)))) t) (defclass sql-query (%sql-expression) ((selections :initarg :selections :initform nil) (all :initarg :all :initform nil) (flatp :initarg :flatp :initform nil) (set-operation :initarg :set-operation :initform nil) (distinct :initarg :distinct :initform nil) (from :initarg :from :initform nil) (where :initarg :where :initform nil) (group-by :initarg :group-by :initform nil) (having :initarg :having :initform nil) (limit :initarg :limit :initform nil) (offset :initarg :offset :initform nil) (order-by :initarg :order-by :initform nil) (inner-join :initarg :inner-join :initform nil) (on :initarg :on :initform nil)) (:documentation "An SQL SELECT query.")) (defclass sql-object-query (%sql-expression) ((objects :initarg :objects :initform nil) (flatp :initarg :flatp :initform nil) (exp :initarg :exp :initform nil) (refresh :initarg :refresh :initform nil))) (defmethod collect-table-refs ((sql sql-query)) (remove-duplicates (collect-table-refs (slot-value sql 'where)) :test #'database-identifier-equal)) (defvar *select-arguments* '(:all :database :distinct :flatp :from :group-by :having :order-by :set-operation :where :offset :limit :inner-join :on ;; below keywords are not a SQL argument, but these keywords may terminate select :caching :refresh)) (defun query-arg-p (sym) (member sym *select-arguments*)) (defun query-get-selections (select-args) "Return two values: the list of select-args up to the first keyword, uninclusive, and the args from that keyword to the end." (let ((first-key-arg (position-if #'query-arg-p select-args))) (if first-key-arg (values (subseq select-args 0 first-key-arg) (subseq select-args first-key-arg)) select-args))) (defun make-query (&rest args) (flet ((select-objects (target-args) (and target-args (every #'(lambda (arg) (and (symbolp arg) (find-class arg nil))) target-args)))) (multiple-value-bind (selections arglist) (query-get-selections args) (if (select-objects selections) (destructuring-bind (&key flatp refresh &allow-other-keys) arglist (make-instance 'sql-object-query :objects selections :flatp flatp :refresh refresh :exp arglist)) (destructuring-bind (&key all flatp set-operation distinct from where group-by having order-by offset limit inner-join on &allow-other-keys) arglist (if (null selections) (error "No target columns supplied to select statement.")) (if (null from) (error "No source tables supplied to select statement.")) (make-instance 'sql-query :selections selections :all all :flatp flatp :set-operation set-operation :distinct distinct :from from :where where :limit limit :offset offset :group-by group-by :having having :order-by order-by :inner-join inner-join :on on)))))) (defun output-sql-where-clause (where database) "ensure that we do not output a \"where\" sql keyword when we will not output a clause. Also sets *in-subselect* to use SQL parentheticals as needed." (when where (let ((where-out (string-trim '(#\newline #\space #\tab #\return) (with-output-to-string (*sql-stream*) (let ((*in-subselect* t)) (output-sql where database)))))) (when (> (length where-out) 0) (write-string " WHERE " *sql-stream*) (write-string where-out *sql-stream*))))) (defmethod output-sql ((query sql-query) database) (with-slots (distinct selections from where group-by having order-by limit offset inner-join on all set-operation) query (when *in-subselect* (write-string "(" *sql-stream*)) (write-string "SELECT " *sql-stream*) (when all (write-string " ALL " *sql-stream*)) (when (and distinct (not all)) (write-string " DISTINCT " *sql-stream*) (unless (eql t distinct) (write-string " ON " *sql-stream*) (output-sql distinct database) (write-char #\Space *sql-stream*))) (when (and limit (eql :mssql (database-underlying-type database))) (write-string " TOP " *sql-stream*) (output-sql limit database) (write-string " " *sql-stream*)) (let ((*in-subselect* t)) (output-sql (apply #'vector selections) database)) (when from (write-string " FROM " *sql-stream*) (typecase from (list (output-sql (apply #'vector (remove-duplicates from :test #'database-identifier-equal)) database)) (string (write-string (escaped-database-identifier from database) *sql-stream*)) (t (let ((*in-subselect* t)) (output-sql from database))))) (when inner-join (write-string " INNER JOIN " *sql-stream*) (output-sql inner-join database)) (when on (write-string " ON " *sql-stream*) (output-sql on database)) (output-sql-where-clause where database) (when group-by (write-string " GROUP BY " *sql-stream*) (if (listp group-by) (do ((order group-by (cdr order))) ((null order)) (let ((item (car order))) (typecase item (cons (output-sql (car item) database) (format *sql-stream* " ~A" (cadr item))) (t (output-sql item database))) (when (cdr order) (write-char #\, *sql-stream*)))) (output-sql group-by database))) (when having (write-string " HAVING " *sql-stream*) (output-sql having database)) (when order-by (write-string " ORDER BY " *sql-stream*) (if (listp order-by) (do ((order order-by (cdr order))) ((null order)) (let ((item (car order))) (typecase item (cons (output-sql (car item) database) (format *sql-stream* " ~A" (cadr item))) (t (output-sql item database))) (when (cdr order) (write-char #\, *sql-stream*)))) (output-sql order-by database))) (when (and limit (not (eql :mssql (database-underlying-type database)))) (write-string " LIMIT " *sql-stream*) (output-sql limit database)) (when offset (write-string " OFFSET " *sql-stream*) (output-sql offset database)) (when *in-subselect* (write-string ")" *sql-stream*)) (when set-operation (write-char #\Space *sql-stream*) (output-sql set-operation database))) t) (defmethod output-sql ((query sql-object-query) database) (declare (ignore database)) (with-slots (objects) query (when objects (format *sql-stream* "(~{~A~^ ~})" objects)))) ;; INSERT (defclass sql-insert (%sql-expression) ((into :initarg :into :initform nil) (attributes :initarg :attributes :initform nil) (values :initarg :values :initform nil) (query :initarg :query :initform nil)) (:documentation "An SQL INSERT statement.")) (defmethod output-sql ((ins sql-insert) database) (with-slots (into attributes values query) ins (write-string "INSERT INTO " *sql-stream*) (output-sql (typecase into (string (sql-expression :table into)) (t into)) database) (when attributes (write-char #\Space *sql-stream*) (output-sql attributes database)) (when values (write-string " VALUES " *sql-stream*) (let ((clsql-sys::*in-subselect* t)) (output-sql values database))) (when query (write-char #\Space *sql-stream*) (output-sql query database))) t) ;; DELETE (defclass sql-delete (%sql-expression) ((from :initarg :from :initform nil) (where :initarg :where :initform nil)) (:documentation "An SQL DELETE statement.")) (defmethod output-sql ((stmt sql-delete) database) (with-slots (from where) stmt (write-string "DELETE FROM " *sql-stream*) (typecase from ((or symbol string) (write-string (sql-escape from) *sql-stream*)) (t (output-sql from database))) (output-sql-where-clause where database)) t) ;; UPDATE (defclass sql-update (%sql-expression) ((table :initarg :table :initform nil) (attributes :initarg :attributes :initform nil) (values :initarg :values :initform nil) (where :initarg :where :initform nil)) (:documentation "An SQL UPDATE statement.")) (defmethod output-sql ((expr sql-update) database) (with-slots (table where attributes values) expr (flet ((update-assignments () (mapcar #'(lambda (a b) (make-instance 'sql-assignment-exp :operator '= :sub-expressions (list a b))) attributes values))) (write-string "UPDATE " *sql-stream*) (output-sql table database) (write-string " SET " *sql-stream*) (let ((clsql-sys::*in-subselect* t)) (output-sql (apply #'vector (update-assignments)) database)) (output-sql-where-clause where database))) t) ;; CREATE TABLE (defclass sql-create-table (%sql-expression) ((name :initarg :name :initform nil) (columns :initarg :columns :initform nil) (modifiers :initarg :modifiers :initform nil) (transactions :initarg :transactions :initform nil)) (:documentation "An SQL CREATE TABLE statement.")) ;; Here's a real warhorse of a function! (declaim (inline listify)) (defun listify (x) (if (listp x) x (list x))) (defmethod output-sql ((stmt sql-create-table) database) (flet ((output-column (column-spec) (destructuring-bind (name type &optional db-type &rest constraints) column-spec (let ((type (listify type))) (output-sql name database) (write-char #\Space *sql-stream*) (write-string (if (stringp db-type) db-type ; override definition (database-get-type-specifier (car type) (cdr type) database (database-underlying-type database))) *sql-stream*) (let ((constraints (database-constraint-statement (if (and db-type (symbolp db-type)) (cons db-type constraints) constraints) database))) (when constraints (write-string " " *sql-stream*) (write-string constraints *sql-stream*))))))) (with-slots (name columns modifiers transactions) stmt (write-string "CREATE TABLE " *sql-stream*) (write-string (escaped-database-identifier name database) *sql-stream*) (write-string " (" *sql-stream*) (do ((column columns (cdr column))) ((null (cdr column)) (output-column (car column))) (output-column (car column)) (write-string ", " *sql-stream*)) (when modifiers (do ((modifier (listify modifiers) (cdr modifier))) ((null modifier)) (write-string ", " *sql-stream*) (write-string (car modifier) *sql-stream*))) (write-char #\) *sql-stream*) (when (and (eq :mysql (database-underlying-type database)) transactions (db-type-transaction-capable? :mysql database)) (write-string " ENGINE=innodb" *sql-stream*)))) t) ;; CREATE VIEW (defclass sql-create-view (%sql-expression) ((name :initarg :name :initform nil) (column-list :initarg :column-list :initform nil) (query :initarg :query :initform nil) (with-check-option :initarg :with-check-option :initform nil)) (:documentation "An SQL CREATE VIEW statement.")) (defmethod output-sql ((stmt sql-create-view) database) (with-slots (name column-list query with-check-option) stmt (write-string "CREATE VIEW " *sql-stream*) (output-sql name database) (when column-list (write-string " " *sql-stream*) (output-sql (listify column-list) database)) (write-string " AS " *sql-stream*) (output-sql query database) (when with-check-option (write-string " WITH CHECK OPTION" *sql-stream*)))) ;; ;; DATABASE-OUTPUT-SQL ;; (defmethod database-output-sql ((str string) database) (declare (optimize (speed 3) (safety 1) #+cmu (extensions:inhibit-warnings 3))) (let ((len (length str))) (declare (type fixnum len)) (cond ((zerop len) +empty-string+) ((and (null (position #\' str)) (null (position #\\ str))) (concatenate 'string "'" str "'")) (t (let ((buf (make-string (+ (* len 2) 2) :initial-element #\'))) (declare (simple-string buf)) (do* ((i 0 (incf i)) (j 1 (incf j))) ((= i len) (subseq buf 0 (1+ j))) (declare (type fixnum i j)) (let ((char (aref str i))) (declare (character char)) (cond ((char= char #\') (setf (aref buf j) #\') (incf j) (setf (aref buf j) #\')) ((and (char= char #\\) ;; MTP: only escape backslash with pgsql/mysql (member (database-underlying-type database) '(:postgresql :mysql) :test #'eq)) (setf (aref buf j) #\\) (incf j) (setf (aref buf j) #\\)) (t (setf (aref buf j) char)))))))))) (let ((keyword-package (symbol-package :foo))) (defmethod database-output-sql ((sym symbol) database) (if (null sym) +null-string+ (if (equal (symbol-package sym) keyword-package) (database-output-sql (symbol-name sym) database) (escaped-database-identifier sym))))) (defmethod database-output-sql ((tee (eql t)) database) (if database (let ((val (database-output-sql-as-type 'boolean t database (database-type database)))) (when val (typecase val (string (format nil "'~A'" val)) (integer (format nil "~A" val))))) "'Y'")) #+nil(defmethod database-output-sql ((tee (eql t)) database) (declare (ignore database)) "'Y'") (defmethod database-output-sql ((num number) database) (declare (ignore database)) (number-to-sql-string num)) (defmethod database-output-sql ((arg list) database) (if (null arg) +null-string+ (format nil "(~{~A~^,~})" (mapcar #'(lambda (val) (sql-output val database)) arg)))) (defmethod database-output-sql ((arg vector) database) (format nil "~{~A~^,~}" (map 'list #'(lambda (val) (sql-output val database)) arg))) (defmethod output-sql-hash-key ((arg vector) database) (list 'vector (map 'list (lambda (arg) (or (output-sql-hash-key arg database) (return-from output-sql-hash-key nil))) arg))) (defmethod database-output-sql ((self wall-time) database) (declare (ignore database)) (db-timestring self)) (defmethod database-output-sql ((self date) database) (declare (ignore database)) (db-datestring self)) (defmethod database-output-sql ((self duration) database) (declare (ignore database)) (format nil "'~a'" (duration-timestring self))) #+ignore (defmethod database-output-sql ((self money) database) (database-output-sql (slot-value self 'odcl::units) database)) (defmethod database-output-sql (thing database) (if (or (null thing) (eq 'null thing)) +null-string+ (error 'sql-user-error :message (format nil "No type conversion to SQL for ~A is defined for DB ~A." (type-of thing) (type-of database))))) ;; ;; Column constraint types and conversion to SQL ;; (defparameter *constraint-types* (list (cons (symbol-name-default-case "NOT-NULL") "NOT NULL") (cons (symbol-name-default-case "PRIMARY-KEY") "PRIMARY KEY") (cons (symbol-name-default-case "NOT") "NOT") (cons (symbol-name-default-case "NULL") "NULL") (cons (symbol-name-default-case "PRIMARY") "PRIMARY") (cons (symbol-name-default-case "KEY") "KEY") (cons (symbol-name-default-case "UNSIGNED") "UNSIGNED") (cons (symbol-name-default-case "ZEROFILL") "ZEROFILL") (cons (symbol-name-default-case "AUTO-INCREMENT") "AUTO_INCREMENT") (cons (symbol-name-default-case "DEFAULT") "DEFAULT") (cons (symbol-name-default-case "UNIQUE") "UNIQUE") (cons (symbol-name-default-case "IDENTITY") "IDENTITY (1,1)") ;; added for sql-server support )) (defmethod database-constraint-statement (constraint-list database) (declare (ignore database)) (make-constraints-description constraint-list)) (defun make-constraints-description (constraint-list) (if constraint-list (let ((string "")) (do ((constraint constraint-list (cdr constraint))) ((null constraint) string) (let ((output (assoc (symbol-name (car constraint)) *constraint-types* :test #'equal))) (if (null output) (error 'sql-user-error :message (format nil "unsupported column constraint '~A'" constraint)) (setq string (concatenate 'string string (cdr output)))) (when (equal (symbol-name (car constraint)) "DEFAULT") (setq constraint (cdr constraint)) (setq string (concatenate 'string string " " (car constraint)))) (if (< 1 (length constraint)) (setq string (concatenate 'string string " ")))))))) (defmethod database-identifier ( name &optional database find-class-p &aux cls) "A function that takes whatever you give it, recursively coerces it, and returns a database-identifier. (escaped-database-identifiers *any-reasonable-object*) should be called to produce a string that is safe to splice directly into sql strings. This function should NOT throw errors when database is nil find-class-p should be T if we want to search for classes and check their use their view table. Should be used on symbols we are sure indicate tables ;; metaclasses has further typecases of this, so that it will ;; load less painfully (try-recompiles) in SBCL " (flet ((flatten-id (id) "if we have multiple pieces that we need to represent as db-id lets do that by rendering out the id, then creating a new db-id with that string as escaped" (let ((s (sql-output id database))) (make-instance '%database-identifier :escaped s :unescaped s)))) (setf name (dequote name)) (etypecase name (null nil) (string (%make-database-identifier name database)) (symbol ;; if this is being used as a table, we should check ;; for a class with this name and use the identifier specified ;; on it (if (and find-class-p (setf cls (find-standard-db-class name))) (database-identifier cls) (%make-database-identifier name database))) (%database-identifier name) ;; we know how to deref this without further escaping (sql-ident-table (with-slots ((inner-name name) alias) name (if alias (flatten-id name) (database-identifier inner-name)))) ;; if this is a single name we can derefence it (sql-ident-attribute (with-slots (qualifier (inner-name name)) name (if qualifier (flatten-id name) (database-identifier inner-name)))) (sql-ident (with-slots ((inner-name name)) name (database-identifier inner-name))) ;; dont know how to handle this really :/ (%sql-expression (flatten-id name)) ))) (defun %clsql-subclauses (clauses) "a helper for dealing with lists of sql clauses" (loop for c in clauses when c collect (typecase c (string (clsql-sys:sql-expression :string c)) (T c)))) (defun clsql-ands (clauses) "Correctly creates a sql 'and' expression for the clauses ignores any nil clauses returns a single child expression if there is only one returns an 'and' expression if there are many returns nil if there are no children" (let ((ex (%clsql-subclauses clauses))) (when ex (case (length ex) (1 (first ex)) (t (apply #'clsql-sys:sql-and ex)))))) (defun clsql-and (&rest clauses) "Correctly creates a sql 'and' expression for the clauses ignores any nil clauses returns a single child expression if there is only one returns an 'and' expression if there are many returns nil if there are no children" (clsql-ands clauses)) (defun clsql-ors (clauses) "Correctly creates a sql 'or' expression for the clauses ignores any nil clauses returns a single child expression if there is only one returns an 'or' expression if there are many returns nil if there are no children" (let ((ex (%clsql-subclauses clauses))) (when ex (case (length ex) (1 (first ex)) (t (apply #'clsql-sys:sql-or ex)))))) (defun clsql-or (&rest clauses) "Correctly creates a sql 'or' expression for the clauses ignores any nil clauses returns a single child expression if there is only one returns an 'or' expression if there are many returns nil if there are no children" (clsql-ors clauses)) cl-sql-6.4.1/sql/transaction.lisp0000644000175000017500000001535112021503403015737 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; ;;;; Transaction support ;;;; ;;;; This file is part of CLSQL. ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* (in-package #:clsql-sys) (defclass transaction () ((commit-hooks :initform () :accessor commit-hooks) (rollback-hooks :initform () :accessor rollback-hooks) (previous-autocommit :initarg :previous-autocommit :reader previous-autocommit) (status :initform nil :accessor transaction-status :documentation "nil or :committed"))) (defun add-transaction-commit-hook (commit-hook &key (database *default-database*)) "Adds COMMIT-HOOK, which should a designator for a function with no required arguments, to the list of hooks run when COMMIT is called on DATABASE which defaults to *DEFAULT-DATABASE*." (when (transaction database) (push commit-hook (commit-hooks (transaction database))))) (defun add-transaction-rollback-hook (rollback-hook &key (database *default-database*)) "Adds ROLLBACK-HOOK, which should a designator for a function with no required arguments, to the list of hooks run when ROLLBACK is called on DATABASE which defaults to *DEFAULT-DATABASE*." (when (transaction database) (push rollback-hook (rollback-hooks (transaction database))))) (defmethod database-start-transaction ((database database)) (unless (transaction database) (setf (transaction database) (make-instance 'transaction :previous-autocommit (database-autocommit database)))) ;; TODO: database-autocommit might get lost in some scenarios ;; when pooling connections (setf (database-autocommit database) nil) (when (= (incf (transaction-level database)) 1) (let ((transaction (transaction database))) (setf (commit-hooks transaction) nil (rollback-hooks transaction) nil (transaction-status transaction) nil) (case (database-underlying-type database) (:oracle nil) (:mssql (execute-command "BEGIN TRANSACTION" :database database)) (t (execute-command "BEGIN" :database database)))))) ;;ODBC should potentially be using the following scheme for transactions: ;; turn off autocommit for begin. then use sqlendtran (or maybe sqltransact) ;; whatever is appropriate for this version of odbc. (defmethod database-commit-transaction ((database database)) (with-slots (transaction transaction-level autocommit) database (if (plusp transaction-level) (if (zerop (decf transaction-level)) (progn (case (database-underlying-type database) (:mssql (execute-command "COMMIT TRANSACTION" :database database)) (t (execute-command "COMMIT" :database database))) (setf autocommit (previous-autocommit transaction)) (map nil #'funcall (commit-hooks transaction))) (setf (transaction-status (transaction database)) nil)) (warn 'sql-warning :message (format nil "Cannot commit transaction against ~A because there is no transaction in progress." database))))) (defmethod database-abort-transaction ((database database)) (with-slots (transaction transaction-level autocommit) database (if (plusp transaction-level) (when (zerop (decf transaction-level)) (unwind-protect (case (database-underlying-type database) (:mssql (execute-command "ROLLBACK TRANSACTION" :database database)) (t (execute-command "ROLLBACK" :database database))) (setf autocommit (previous-autocommit transaction)) (map nil #'funcall (rollback-hooks transaction)))) (warn 'sql-warning :message (format nil "Cannot abort transaction against ~A because there is no transaction in progress." database))))) (defun mark-transaction-committed (database) (when (and (transaction database) (not (transaction-status (transaction database)))) (setf (transaction-status (transaction database)) :committed))) (defmacro with-transaction ((&key (database '*default-database*)) &body body) "Starts a transaction in the database specified by DATABASE, which is *DEFAULT-DATABASE* by default, and executes BODY within that transaction. If BODY aborts or throws, DATABASE is rolled back and otherwise the transaction is committed." (let ((db (gensym "db-"))) `(let ((,db ,database)) (unwind-protect (prog2 (database-start-transaction ,db) (progn ,@body) (mark-transaction-committed ,db)) (if (eq (transaction-status (transaction ,db)) :committed) (database-commit-transaction ,db) (database-abort-transaction ,db)))))) (defun commit (&key (database *default-database*)) "If DATABASE, which defaults to *DEFAULT-DATABASE*, is currently within the scope of a transaction, commits changes made since the transaction began." (database-commit-transaction database) nil) (defun rollback (&key (database *default-database*)) "If DATABASE, which defaults to *DEFAULT-DATABASE*, is currently within the scope of a transaction, rolls back changes made since the transaction began." (database-abort-transaction database) nil) (defun start-transaction (&key (database *default-database*)) "Starts a transaction block on DATABASE which defaults to *DEFAULT-DATABASE* and which continues until ROLLBACK or COMMIT are called." (unless (in-transaction-p :database database) (database-start-transaction database)) nil) (defun in-transaction-p (&key (database *default-database*)) "A predicate to test whether DATABASE, which defaults to *DEFAULT-DATABASE*, is currently within the scope of a transaction." (and database (transaction database) (= (transaction-level database) 1))) (defun set-autocommit (value &key (database *default-database*)) "Turns autocommit off for DATABASE if VALUE is NIL, and otherwise turns it on. Returns the old value of autocommit flag. For RDBMS (such as Oracle) which don't automatically commit changes, turning autocommit on has the effect of explicitly committing changes made whenever SQL statements are executed. Autocommit is turned on by default." (let ((old-value (database-autocommit database))) (setf (database-autocommit database) value) (database-autocommit database) old-value)) cl-sql-6.4.1/sql/initialize.lisp0000644000175000017500000000502411335067642015570 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; FILE IDENTIFICATION ;;;; ;;;; Name: initialize.lisp ;;;; Purpose: Initializion routines for db backend ;;;; Programmers: Kevin M. Rosenberg ;;;; Date Started: May 2002 ;;;; ;;;; This file, part of CLSQL, is Copyright (c) 2002-2010 by Kevin M. Rosenberg ;;;; and Copyright (c) 1999-2001 by Pierre R. Mai ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* (in-package #:clsql-sys) (defvar *loaded-database-types* nil "Contains a list of database types which have been defined/loaded.") (defmethod database-type-load-foreign (x) (error "No generic function defined for database-type-load-foreign with parameters of ~S" x)) (defmethod database-type-load-foreign :after (database-type) (when (database-type-library-loaded database-type) (pushnew database-type *loaded-database-types*))) (defun reload-database-types () "Reloads any foreign code for the loaded database types after a dump." (mapc #'database-type-load-foreign *loaded-database-types*)) (defvar *default-database-type* nil "Designates the default database type which is initialised by the function INITIALISE-DATABASE-TYPE.") (defvar *initialized-database-types* nil "A list of database types which have currently been initialised by calling INITIALIZE-DATABASE-TYPE.") (defun initialize-database-type (&key (database-type *default-database-type*)) "Initializes the supplied DATABASE-TYPE, if it is not already initialized, as indicated by *INITIALIZED-DATABASE-TYPES* and returns DATABASE-TYPE. *DEFAULT-DATABASE-TYPE* is set to DATABASE-TYPE and, if DATABASE-TYPE has not been initialised, it is added to *INITIALIZED-DATABASE-TYPES*. " (when (member database-type *initialized-database-types*) (return-from initialize-database-type database-type)) (let ((system (intern (concatenate 'string (symbol-name '#:clsql-) (symbol-name database-type))))) (when (not (find-package system)) (asdf:operate 'asdf:load-op system))) (when (database-initialize-database-type database-type) (push database-type *initialized-database-types*) (setf *default-database-type* database-type) database-type)) cl-sql-6.4.1/sql/kmr-mop.lisp0000644000175000017500000000740112064366222015006 0ustar kevinkevin;;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; FILE IDENTIFICATION ;;;; ;;;; Name: kmr-mop.lisp ;;;; Purpose: MOP support for multiple-implementions ;;;; Programmer: Kevin M. Rosenberg ;;;; Date Started: Apr 2003 ;;;; ;;;; This file imports MOP symbols into the CLSQL-MOP package and then ;;;; re-exports into CLSQL-SYS them to hide differences in ;;;; MOP implementations. ;;;; ;;;; This file was extracted from the KMRCL utilities ;;;; ************************************************************************* (in-package #:clsql-sys) #+lispworks (defun intern-eql-specializer (slot) `(eql ,slot)) (defmacro process-class-option (metaclass slot-name &optional required) #+lispworks `(defmethod clos:process-a-class-option ((class ,metaclass) (name (eql ,slot-name)) value) (when (and ,required (null value)) (error "metaclass ~A class slot ~A must have a value" (quote ,metaclass) name)) (list name `',value)) #-lispworks (declare (ignore metaclass slot-name required)) ) (defmacro process-slot-option (metaclass slot-name) #+lispworks `(defmethod clos:process-a-slot-option ((class ,metaclass) (option (eql ,slot-name)) value already-processed-options slot) (list* option `',value already-processed-options)) #-lispworks (declare (ignore metaclass slot-name)) ) (eval-when (:compile-toplevel :load-toplevel :execute) (defclass %slot-order-test-class () ((a) (b))) (finalize-inheritance (find-class '%slot-order-test-class)) (let ((slots (class-slots (find-class '%slot-order-test-class)))) (ecase (slot-definition-name (first slots)) (a) (b (pushnew :mop-slot-order-reversed cl:*features*))))) (defun ordered-class-slots (class) #+mop-slot-order-reversed (reverse (class-slots class)) #-mop-slot-order-reversed (class-slots class)) (defun ordered-class-direct-slots (class) "Gets an ordered list of direct class slots" ;; NB: this used to return effective-slot-definitions in direct ;; opposition to the function name. Not sure why (setf class (to-class class)) #+mop-slot-order-reversed (reverse (class-direct-slots class)) #-mop-slot-order-reversed (class-direct-slots class)) (defun find-slot-if (class predicate &optional direct? recurse?) "Looks up a direct-slot-definition by name" (setf class (to-class class)) (labels ((find-it (class) (let* ((slots (if direct? (ordered-class-direct-slots class) (ordered-class-slots class))) (it (find-if predicate slots))) (or it (when recurse? (loop for sup in (class-direct-superclasses class) for rtn = (find-it sup) until rtn finally (return rtn))))))) (find-it class))) (defun find-slot-by-name (class slot-name &optional direct? recurse?) "Looks up a direct-slot-definition by name" (setf class (to-class class) slot-name (to-slot-name slot-name)) (find-slot-if class (lambda (slot-def) (eql (to-slot-name slot-def) slot-name)) direct? recurse?)) ;; Lispworks has symbol for slot rather than the slot instance (defun %svuc-slot-name (slot) #+lispworks slot #-lispworks (slot-definition-name slot)) (defun %svuc-slot-object (slot class) (declare (ignorable class)) #+lispworks (clos:find-slot-definition slot class) #-lispworks slot) cl-sql-6.4.1/sql/time.lisp0000644000175000017500000013601111577737507014402 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; ;;;; A variety of structures and function for creating and ;;;; manipulating dates, times, durations and intervals for ;;;; CLSQL. ;;;; ;;;; This file was originally part of ODCL and is Copyright (c) 2002 - ;;;; 2003 onShore Development, Inc. ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* (in-package #:clsql-sys) ;; ------------------------------------------------------------ ;; Months (defvar *month-keywords* '(:january :february :march :april :may :june :july :august :september :october :november :december)) (defvar *month-names* '("" "January" "February" "March" "April" "May" "June" "July" "August" "September" "October" "November" "December")) (defun month-name (month-index) (nth month-index *month-names*)) (defun ordinal-month (month-keyword) "Return the zero-based month number for the given MONTH keyword." (position month-keyword *month-keywords*)) ;; ------------------------------------------------------------ ;; Days (defvar *day-keywords* '(:sunday :monday :tuesday :wednesday :thursday :friday :saturday)) (defvar *day-names* '("Sunday" "Monday" "Tuesday" "Wednesday" "Thursday" "Friday" "Saturday")) (defun day-name (day-index) (nth day-index *day-names*)) (defun ordinal-day (day-keyword) "Return the zero-based day number for the given DAY keyword." (position day-keyword *day-keywords*)) ;; ------------------------------------------------------------ ;; time classes: wall-time, duration (eval-when (:compile-toplevel :load-toplevel) (defstruct (wall-time (:conc-name time-) (:constructor %make-wall-time) (:print-function %print-wall-time)) (mjd 0 :type fixnum) (second 0 :type fixnum) (usec 0 :type fixnum)) (defun %print-wall-time (time stream depth) (declare (ignore depth)) (if *print-escape* (format stream "#" (format-time nil time)) (format-time stream time :format :pretty))) (defstruct (duration (:constructor %make-duration) (:print-function %print-duration)) (year 0 :type fixnum) (month 0 :type fixnum) (day 0 :type fixnum) (hour 0 :type fixnum) (second 0 :type fixnum) (minute 0 :type fixnum) (usec 0 :type fixnum)) (defun %print-duration (duration stream depth) (declare (ignore depth)) (if *print-escape* (format stream "#" (format-duration nil duration :precision :second)) (format-duration stream duration :precision :second))) (defstruct (date (:constructor %make-date) (:print-function %print-date)) (mjd 0 :type fixnum)) (defun %print-date (date stream depth) (declare (ignore depth)) (if *print-escape* (format stream "#" (format-date nil date)) (format-date stream date :format :pretty))) );eval-when (defun duration-timestring (duration) (let ((second (duration-second duration)) (minute (duration-minute duration)) (hour (duration-hour duration)) (day (duration-day duration)) (month (duration-month duration)) (year (duration-year duration))) (format nil "P~dY~dM~dD~dH~dM~dS" year month day hour minute second))) ;; ------------------------------------------------------------ ;; Constructors (defun make-time (&key (year 0) (month 1) (day 1) (hour 0) (minute 0) (second 0) (usec 0) (offset 0)) (let ((mjd (gregorian-to-mjd month day year)) (sec (+ (* hour 60 60) (* minute 60) second (- offset)))) (multiple-value-bind (day-add raw-sec) (floor sec (* 60 60 24)) (%make-wall-time :mjd (+ mjd day-add) :second raw-sec :usec usec)))) (defun make-date (&key (year 0) (month 1) (day 1) (hour 0) (minute 0) (second 0) (usec 0) (offset 0)) (time->date (make-time :year year :month month :day day :hour hour :minute minute :second second :usec usec :offset offset))) (defun copy-time (time) (%make-wall-time :mjd (time-mjd time) :second (time-second time))) (defun utime->time (utime) "Return a pair: (GREGORIAN DAY . TIME-OF-DAY)" (multiple-value-bind (second minute hour day mon year) (decode-universal-time utime) (make-time :year year :month mon :day day :hour hour :minute minute :second second))) (defun date->time (date) "Returns a walltime for the given date" (%make-wall-time :mjd (date-mjd date))) (defun time->date (time) "Returns a date for the given wall time (obvious loss in resolution)" (%make-date :mjd (time-mjd time))) (defun get-time () "Return a pair: (GREGORIAN DAY . TIME-OF-DAY)" (utime->time (get-universal-time))) (defun get-date () "Returns a date for today" (time->date (get-time))) (defun make-duration (&key (year 0) (month 0) (day 0) (hour 0) (minute 0) (second 0) (usec 0)) (multiple-value-bind (second-add usec-1000000) (floor usec 1000000) (multiple-value-bind (minute-add second-60) (floor (+ second second-add) 60) (multiple-value-bind (hour-add minute-60) (floor (+ minute minute-add) 60) (multiple-value-bind (day-add hour-24) (floor (+ hour hour-add) 24) (%make-duration :year year :month month :day (+ day day-add) :hour hour-24 :minute minute-60 :second second-60 :usec usec-1000000)))))) ;; ------------------------------------------------------------ ;; Accessors (defun time-hms (time) (multiple-value-bind (hourminute second) (floor (time-second time) 60) (multiple-value-bind (hour minute) (floor hourminute 60) (values hour minute second)))) (defun time-ymd (time) (destructuring-bind (month day year) (mjd-to-gregorian (time-mjd time)) (values year month day))) (defun time-dow (time) "Return the 0 indexed Day of the week starting with Sunday" (mod (+ 3 (time-mjd time)) 7)) (defun decode-time (time) "returns the decoded time as multiple values: usec, second, minute, hour, day, month, year, integer day-of-week" (multiple-value-bind (year month day) (time-ymd time) (multiple-value-bind (hour minute second) (time-hms time) (values (time-usec time) second minute hour day month year (mod (+ (time-mjd time) 3) 7))))) (defun date-ymd (date) (time-ymd (date->time date))) (defun date-dow (date) (time-dow (date->time date))) (defun decode-date (date) "returns the decoded date as multiple values: day month year integer day-of-week" (multiple-value-bind (year month day) (time-ymd (date->time date)) (values day month year (date-dow date)))) ;; duration specific (defun duration-reduce (duration precision &optional round) (ecase precision (:usec (+ (duration-usec duration) (* (duration-reduce duration :second) 1000000))) (:second (+ (if round (floor (duration-usec duration) 500000) 0) (duration-second duration) (* (duration-reduce duration :minute) 60))) (:minute (+ (if round (floor (duration-second duration) 30) 0) (duration-minute duration) (* (duration-reduce duration :hour) 60))) (:hour (+ (if round (floor (duration-minute duration) 30) 0) (duration-hour duration) (* (duration-reduce duration :day) 24))) (:day (+ (if round (floor (duration-hour duration) 12) 0) (duration-day duration))))) ;; ------------------------------------------------------------ ;; Arithemetic and comparators (defun duration= (duration-a duration-b) (= (duration-reduce duration-a :usec) (duration-reduce duration-b :usec))) (defun duration< (duration-a duration-b) (< (duration-reduce duration-a :usec) (duration-reduce duration-b :usec))) (defun duration<= (duration-a duration-b) (<= (duration-reduce duration-a :usec) (duration-reduce duration-b :usec))) (defun duration>= (x y) (duration<= y x)) (defun duration> (x y) (duration< y x)) (defun %time< (x y) (let ((mjd-x (time-mjd x)) (mjd-y (time-mjd y))) (if (/= mjd-x mjd-y) (< mjd-x mjd-y) (if (/= (time-second x) (time-second y)) (< (time-second x) (time-second y)) (< (time-usec x) (time-usec y)))))) (defun %time>= (x y) (if (/= (time-mjd x) (time-mjd y)) (>= (time-mjd x) (time-mjd y)) (if (/= (time-second x) (time-second y)) (>= (time-second x) (time-second y)) (>= (time-usec x) (time-usec y))))) (defun %time<= (x y) (if (/= (time-mjd x) (time-mjd y)) (<= (time-mjd x) (time-mjd y)) (if (/= (time-second x) (time-second y)) (<= (time-second x) (time-second y)) (<= (time-usec x) (time-usec y))))) (defun %time> (x y) (if (/= (time-mjd x) (time-mjd y)) (> (time-mjd x) (time-mjd y)) (if (/= (time-second x) (time-second y)) (> (time-second x) (time-second y)) (> (time-usec x) (time-usec y))))) (defun %time= (x y) (and (= (time-mjd x) (time-mjd y)) (= (time-second x) (time-second y)) (= (time-usec x) (time-usec y)))) (defun time= (number &rest more-numbers) "Returns T if all of its arguments are numerically equal, NIL otherwise." (do ((nlist more-numbers (cdr nlist))) ((atom nlist) t) (declare (list nlist)) (if (not (%time= (car nlist) number)) (return nil)))) (defun time/= (number &rest more-numbers) "Returns T if no two of its arguments are numerically equal, NIL otherwise." (do* ((head number (car nlist)) (nlist more-numbers (cdr nlist))) ((atom nlist) t) (declare (list nlist)) (unless (do* ((nl nlist (cdr nl))) ((atom nl) t) (declare (list nl)) (if (%time= head (car nl)) (return nil))) (return nil)))) (defun time< (number &rest more-numbers) "Returns T if its arguments are in strictly increasing order, NIL otherwise." (do* ((n number (car nlist)) (nlist more-numbers (cdr nlist))) ((atom nlist) t) (declare (list nlist)) (if (not (%time< n (car nlist))) (return nil)))) (defun time> (number &rest more-numbers) "Returns T if its arguments are in strictly decreasing order, NIL otherwise." (do* ((n number (car nlist)) (nlist more-numbers (cdr nlist))) ((atom nlist) t) (declare (list nlist)) (if (not (%time> n (car nlist))) (return nil)))) (defun time<= (number &rest more-numbers) "Returns T if arguments are in strictly non-decreasing order, NIL otherwise." (do* ((n number (car nlist)) (nlist more-numbers (cdr nlist))) ((atom nlist) t) (declare (list nlist)) (if (not (%time<= n (car nlist))) (return nil)))) (defun time>= (number &rest more-numbers) "Returns T if arguments are in strictly non-increasing order, NIL otherwise." (do* ((n number (car nlist)) (nlist more-numbers (cdr nlist))) ((atom nlist) t) (declare (list nlist)) (if (not (%time>= n (car nlist))) (return nil)))) (defun time-max (number &rest more-numbers) "Returns the greatest of its arguments." (do ((nlist more-numbers (cdr nlist)) (result number)) ((null nlist) (return result)) (declare (list nlist)) (if (%time> (car nlist) result) (setf result (car nlist))))) (defun time-min (number &rest more-numbers) "Returns the least of its arguments." (do ((nlist more-numbers (cdr nlist)) (result number)) ((null nlist) (return result)) (declare (list nlist)) (if (%time< (car nlist) result) (setf result (car nlist))))) (defun time-compare (time-a time-b) (let ((mjd-a (time-mjd time-a)) (mjd-b (time-mjd time-b)) (sec-a (time-second time-a)) (sec-b (time-second time-b)) (usec-a (time-usec time-a)) (usec-b (time-usec time-b))) (if (= mjd-a mjd-b) (if (= sec-a sec-b) (if (= usec-a usec-b) :equal (if (< usec-a usec-b) :less-than :greater-than)) (if (< sec-a sec-b) :less-than :greater-than)) (if (< mjd-a mjd-b) :less-than :greater-than)))) ; now the same for dates (eval-when (:compile-toplevel :load-toplevel) (defun replace-string (string1 search-string replace-string &key (test #'string=)) "Search within string1 for search-string, replace with replace-string, non-destructively." (let ((replace-string-length (length replace-string)) (search-string-length (length search-string))) (labels ((sub-replace-string (current-string position) (let ((found-position (search search-string current-string :test test :start2 position))) (if (null found-position) current-string (sub-replace-string (concatenate 'string (subseq current-string 0 found-position) replace-string (subseq current-string (+ found-position search-string-length))) (+ position replace-string-length)))))) (sub-replace-string string1 0)))) );eval-when (defmacro wrap-time-for-date (time-func &key (result-func)) (let ((date-func (intern (replace-string (symbol-name time-func) (symbol-name-default-case "TIME") (symbol-name-default-case "DATE"))))) `(defun ,date-func (number &rest more-numbers) (let ((result (apply #',time-func (mapcar #'date->time (cons number more-numbers))))) ,(if result-func `(funcall #',result-func result) 'result))))) (wrap-time-for-date time=) (wrap-time-for-date time/=) (wrap-time-for-date time<) (wrap-time-for-date time>) (wrap-time-for-date time<=) (wrap-time-for-date time>=) (wrap-time-for-date time-max :result-func time->date) (wrap-time-for-date time-min :result-func time->date) (defun date-compare (date-a date-b) (time-compare (date->time date-a) (date->time date-b))) ;; ------------------------------------------------------------ ;; Formatting and output (defun db-timestring (time &key stream) "return the string to store the given time in the database" (if stream (progn (write-char #\' stream) (iso-timestring time :stream stream) (write-char #\' stream)) (concatenate 'string "'" (iso-timestring time) "'"))) (defun iso-timestring (time &key stream) (multiple-value-bind (usec sec min hour day month year dow) (decode-time time) (declare (ignore dow)) (flet ((fmt (stream) (when (< year 1000) (princ #\0 stream)) (when (< year 100) (princ #\0 stream)) (when (< year 10) (princ #\0 stream)) (princ year stream) (princ #\- stream) (when (< month 10) (princ #\0 stream)) (princ month stream) (princ #\- stream) (when (< day 10) (princ #\0 stream)) (princ day stream) (princ #\T stream) ;strict ISO says T here isn't optional. (when (< hour 10) (princ #\0 stream)) (princ hour stream) (princ #\: stream) (when (< min 10) (princ #\0 stream)) (princ min stream) (princ #\: stream) (when (< sec 10) (princ #\0 stream)) (princ sec stream) (when (and usec (plusp usec)) ;; we dont do this because different dbs support differnt precision levels (princ #\. stream) (loop for i from 5 downto 0 for x10 = (expt 10 i) do (multiple-value-bind (quo rem) (floor (/ usec x10)) (setf usec (- usec (* quo x10))) (princ quo stream) (when (= rem 0) (return))))) nil)) (if stream (fmt stream) (with-output-to-string (stream) (fmt stream)))))) (defun db-datestring (date) (db-timestring (date->time date))) (defun iso-datestring (date) (iso-timestring (date->time date))) ;; ------------------------------------------------------------ ;; Intervals (defstruct interval (start nil) (end nil) (name nil) (contained nil) (type nil) (data nil)) ;; fix : should also return :contains / :contained (defun interval-relation (x y) "Compare the relationship of node x to node y. Returns either :contained :contains :follows :overlaps or :precedes." (let ((xst (interval-start x)) (xend (interval-end x)) (yst (interval-start y)) (yend (interval-end y))) (case (time-compare xst yst) (:equal (case (time-compare xend yend) (:less-than :contained) ((:equal :greater-than) :contains))) (:greater-than (case (time-compare xst yend) ((:equal :greater-than) :follows) (:less-than (case (time-compare xend yend) ((:less-than :equal) :contained) ((:greater-than) :overlaps))))) (:less-than (case (time-compare xend yst) ((:equal :less-than) :precedes) (:greater-than (case (time-compare xend yend) (:less-than :overlaps) ((:equal :greater-than) :contains)))))))) ;; ------------------------------------------------------------ ;; interval lists (defun sort-interval-list (list) (sort list (lambda (x y) (case (interval-relation x y) ((:precedes :contains) t) ((:follows :overlaps :contained) nil))))) ;; interval push will return its list of intervals in strict order. (defun interval-push (interval-list interval &optional container-rule) (declare (ignore container-rule)) (let ((sorted-list (sort-interval-list interval-list))) (dotimes (x (length sorted-list)) (let ((elt (nth x sorted-list))) (case (interval-relation elt interval) (:follows (return-from interval-push (insert-at-index x sorted-list interval))) (:contains (return-from interval-push (replace-at-index x sorted-list (make-interval :start (interval-start elt) :end (interval-end elt) :type (interval-type elt) :contained (interval-push (interval-contained elt) interval) :data (interval-data elt))))) ((:overlaps :contained) (error "Overlap"))))) (append sorted-list (list interval)))) ;; interval lists (defun interval-match (list time) "Return the index of the first interval in list containing time" ;; this depends on ordering of intervals! (let ((list (sort-interval-list list))) (dotimes (x (length list)) (let ((elt (nth x list))) (when (and (time<= (interval-start elt) time) (time< time (interval-end elt))) (return-from interval-match x)))))) (defun interval-clear (list time) (dotimes (x (length list)) (let ((elt (nth x list))) (when (and (time<= (interval-start elt) time) (time< time (interval-end elt))) (if (interval-match (interval-contained elt) time) (return-from interval-clear (replace-at-index x list (make-interval :start (interval-start elt) :end (interval-end elt) :type (interval-type elt) :contained (interval-clear (interval-contained elt) time) :data (interval-data elt)))) (return-from interval-clear (delete-at-index x list))))))) (defun interval-edit (list time start end &optional tag) "Attempts to modify the most deeply nested interval in list which begins at time. If no changes are made, returns nil." ;; function required sorted interval list (let ((list (sort-interval-list list))) (if (null list) nil (dotimes (x (length list)) (let ((elt (nth x list))) (when (and (time<= (interval-start elt) time) (time< time (interval-end elt))) (or (interval-edit (interval-contained elt) time start end tag) (cond ((and (< 0 x) (time< start (interval-end (nth (1- x) list)))) (error "Overlap of previous interval")) ((and (< x (1- (length list))) (time< (interval-start (nth (1+ x) list)) end)) (error "~S ~S ~S ~S Overlap of next interval" x (length list) (interval-start (nth (1+ x) list)) end )) ((time= (interval-start elt) time) (return-from interval-edit (replace-at-index x list (make-interval :start start :end end :type (interval-type elt) :contained (restrict-intervals (interval-contained elt) start end) :data (or tag (interval-data elt)))))))))))))) (defun restrict-intervals (list start end &aux newlist) (let ((test-interval (make-interval :start start :end end))) (dolist (elt list) (when (equal :contained (interval-relation elt test-interval)) (push elt newlist))) (nreverse newlist))) ;;; utils from odcl/list.lisp (defun replace-at-index (idx list elt) (cond ((= idx 0) (cons elt (cdr list))) ((= idx (1- (length list))) (append (butlast list) (list elt))) (t (append (subseq list 0 idx) (list elt) (subseq list (1+ idx)))))) (defun insert-at-index (idx list elt) (cond ((= idx 0) (cons elt list)) ((= idx (1- (length list))) (append list (list elt))) (t (append (subseq list 0 idx) (list elt) (subseq list idx))))) (defun delete-at-index (idx list) (cond ((= idx 0) (cdr list)) ((= idx (1- (length list))) (butlast list)) (t (append (subseq list 0 idx) (subseq list (1+ idx)))))) ;; ------------------------------------------------------------ ;; return MJD for Gregorian date (defun gregorian-to-mjd (month day year) (let ((b 0) (month-adj month) (year-adj (if (< year 0) (+ year 1) year)) d c) (when (< month 3) (incf month-adj 12) (decf year-adj)) (unless (or (< year 1582) (and (= year 1582) (or (< month 10) (and (= month 10) (< day 15))))) (let ((a (floor (/ year-adj 100)))) (setf b (+ (- 2 a) (floor (/ a 4)))))) (if (< year-adj 0) (setf c (floor (- (* 365.25d0 year-adj) 679006.75d0))) (setf c (floor (- (* 365.25d0 year-adj) 679006d0)))) (setf d (floor (* 30.6001 (+ 1 month-adj)))) ;; (cmsg "b ~s c ~s d ~s day ~s" b c d day) (+ b c d day))) ;; convert MJD to Gregorian date (defun mjd-to-gregorian (mjd) (let (z r g a b c year month day) (setf z (floor (+ mjd 678882))) (setf r (- (+ mjd 678882) z)) (setf g (- z .25)) (setf a (floor (/ g 36524.25))) (setf b (- a (floor (/ a 4)))) (setf year (floor (/ (+ b g) 365.25))) (setf c (- (+ b z) (floor (* 365.25 year)))) (setf month (truncate (/ (+ (* 5 c) 456) 153))) (setf day (+ (- c (truncate (/ (- (* 153 month) 457) 5))) r)) (when (> month 12) (incf year) (decf month 12)) (list month day year))) (defun duration+ (time &rest durations) "Add each DURATION to TIME, returning a new wall-time value." (let ((year (duration-year time)) (month (duration-month time)) (day (duration-day time)) (hour (duration-hour time)) (minute (duration-minute time)) (second (duration-second time)) (usec (duration-usec time))) (dolist (duration durations) (incf year (duration-year duration)) (incf month (duration-month duration)) (incf day (duration-day duration)) (incf hour (duration-hour duration)) (incf minute (duration-minute duration)) (incf second (duration-second duration)) (incf usec (duration-usec duration))) (make-duration :year year :month month :day day :hour hour :minute minute :second second :usec usec))) (defun duration- (duration &rest durations) "Subtract each DURATION from TIME, returning a new duration value." (let ((year (duration-year duration)) (month (duration-month duration)) (day (duration-day duration)) (hour (duration-hour duration)) (minute (duration-minute duration)) (second (duration-second duration)) (usec (duration-usec duration))) (dolist (duration durations) (decf year (duration-year duration)) (decf month (duration-month duration)) (decf day (duration-day duration)) (decf hour (duration-hour duration)) (decf minute (duration-minute duration)) (decf second (duration-second duration)) (decf usec (duration-usec duration))) (make-duration :year year :month month :day day :hour hour :minute minute :second second :usec usec))) ;; Date + Duration (defun time+ (time &rest durations) "Add each DURATION to TIME, returning a new wall-time value." (let ((new-time (copy-time time))) (dolist (duration durations) (roll new-time :year (duration-year duration) :month (duration-month duration) :day (duration-day duration) :hour (duration-hour duration) :minute (duration-minute duration) :second (duration-second duration) :usec (duration-usec duration) :destructive t)) new-time)) (defun date+ (date &rest durations) "Add each DURATION to DATE, returning a new date value. Note that (barring daylight saving time) 12h + 12h will result in a new day, but doing it as separate calculations will not, as the time is chopped to a date before being returned." (time->date (apply #'time+ (cons (date->time date) durations)))) (defun time- (time &rest durations) "Subtract each DURATION from TIME, returning a new wall-time value." (let ((new-time (copy-time time))) (dolist (duration durations) (roll new-time :year (- (duration-year duration)) :month (- (duration-month duration)) :day (- (duration-day duration)) :hour (- (duration-hour duration)) :minute (- (duration-minute duration)) :second (- (duration-second duration)) :usec (- (duration-usec duration)) :destructive t)) new-time)) (defun date- (date &rest durations) "Subtract each DURATION to DATE, returning a new date value. Note that (barring daylight saving time) 12h + 12h will result in a new day, but doing it as separate calculations will not, as the time is chopped to a date before being returned." (time->date (apply #'time- (cons (date->time date) durations)))) (defun time-difference (time1 time2) "Returns a DURATION representing the difference between TIME1 and TIME2." (flet ((do-diff (time1 time2) (let (day-diff sec-diff) (setf day-diff (- (time-mjd time2) (time-mjd time1))) (if (> day-diff 0) (progn (decf day-diff) (setf sec-diff (+ (time-second time2) (- (* 60 60 24) (time-second time1))))) (setf sec-diff (- (time-second time2) (time-second time1)))) (make-duration :day day-diff :second sec-diff)))) (if (time< time1 time2) (do-diff time1 time2) (do-diff time2 time1)))) (defun date-difference (date1 date2) "Returns a DURATION representing the difference between TIME1 and TIME2." (time-difference (date->time date1) (date->time date2))) (defun format-date (stream date &key format (date-separator "-") (internal-separator " ")) "produces on stream the datestring corresponding to the date with the given options" (format-time stream (date->time date) :format format :date-separator date-separator :internal-separator internal-separator)) (defun format-time (stream time &key format (date-separator "-") (time-separator ":") (internal-separator " ")) "produces on stream the timestring corresponding to the wall-time with the given options" (let ((*print-circle* nil)) (multiple-value-bind (usec second minute hour day month year dow) (decode-time time) (case format (:pretty (format stream "~A ~A, ~A ~D, ~D" (pretty-time hour minute) (day-name dow) (month-name month) day year)) (:short-pretty (format stream "~A, ~D/~D/~D" (pretty-time hour minute) month day year)) ((:iso :iso8601) (iso-timestring time :stream stream)) (t (format stream "~2,'0D~A~2,'0D~A~2,'0D~A~2,'0D~A~2,'0D~A~2,'0D.~6,'0D" year date-separator month date-separator day internal-separator hour time-separator minute time-separator second usec) ))))) (defun pretty-time (hour minute) (cond ((eq hour 0) (format nil "12:~2,'0D AM" minute)) ((eq hour 12) (format nil "12:~2,'0D PM" minute)) ((< hour 12) (format nil "~D:~2,'0D AM" hour minute)) ((and (> hour 12) (< hour 24)) (format nil "~D:~2,'0D PM" (- hour 12) minute)) (t (error "pretty-time got bad hour")))) (defun leap-days-in-days (days) ;; return the number of leap days between Mar 1 2000 and ;; (Mar 1 2000) + days, where days can be negative (if (< days 0) (ceiling (/ (- days) (* 365 4))) (floor (/ days (* 365 4))))) (defun current-year () (third (mjd-to-gregorian (time-mjd (get-time))))) (defun current-month () (first (mjd-to-gregorian (time-mjd (get-time))))) (defun current-day () (second (mjd-to-gregorian (time-mjd (get-time))))) (defun parse-date-time (string) "parses date like 08/08/01, 8.8.2001, eg" (when (> (length string) 1) (let ((m (current-month)) (d (current-day)) (y (current-year))) (let ((integers (mapcar #'parse-integer (hork-integers string)))) (case (length integers) (1 (setf y (car integers))) (2 (setf m (car integers)) (setf y (cadr integers))) (3 (setf m (car integers)) (setf d (cadr integers)) (setf y (caddr integers))) (t (return-from parse-date-time)))) (when (< y 100) (incf y 2000)) (make-time :year y :month m :day d)))) (defun hork-integers (input) (let ((output '()) (start 0)) (dotimes (x (length input)) (unless (<= 48 (char-code (aref input x)) 57) (push (subseq input start x) output) (setf start (1+ x)))) (nreverse (push (subseq input start) output)))) (defun merged-time (day time-of-day) (%make-wall-time :mjd (time-mjd day) :second (time-second time-of-day))) (defun time-meridian (hours) (cond ((= hours 0) (values 12 "AM")) ((= hours 12) (values 12 "PM")) ((< 12 hours) (values (- hours 12) "PM")) (t (values hours "AM")))) (defgeneric to-string (val &rest keys) ) (defmethod to-string ((time wall-time) &rest keys) (destructuring-bind (&key (style :daytime) &allow-other-keys) keys (print-date time style))) (defun print-date (time &optional (style :daytime)) (multiple-value-bind (usec second minute hour day month year dow) (decode-time time) (declare (ignore usec second)) (multiple-value-bind (hours meridian) (time-meridian hour) (ecase style (:time-of-day ;; 2:00 PM (format nil "~d:~2,'0d ~a" hours minute meridian)) (:long-day ;; October 11th, 2000 (format nil "~a ~d, ~d" (month-name month) day year)) (:month ;; October (month-name month)) (:month-year ;; October 2000 (format nil "~a ~d" (month-name month) year)) (:full ;; 11:08 AM, November 22, 2002 (format nil "~d:~2,'0d ~a, ~a ~d, ~d" hours minute meridian (month-name month) day year)) (:full+weekday ;; 11:09 AM Friday, November 22, 2002 (format nil "~d:~2,'0d ~a ~a, ~a ~d, ~d" hours minute meridian (nth dow *day-names*) (month-name month) day year)) (:daytime ;; 11:09 AM, 11/22/2002 (format-time nil time :format :short-pretty)) (:day ;; 11/22/2002 (format nil "~d/~d/~d" month day year)))))) (defun time-element (time element) (multiple-value-bind (usec second minute hour day month year dow) (decode-time time) (declare (ignore usec)) (ecase element (:seconds second) (:minutes minute) (:hours hour) (:day-of-month day) (:integer-day-of-week dow) (:day-of-week (nth dow *day-keywords*)) (:month month) (:year year)))) (defun date-element (date element) (time-element (date->time date) element)) (defun format-duration (stream duration &key (precision :minute)) (let ((second (duration-second duration)) (minute (duration-minute duration)) (hour (duration-hour duration)) (day (duration-day duration)) (month (duration-month duration)) (year (duration-year duration)) (return (null stream)) (stream (or stream (make-string-output-stream)))) (ecase precision (:day (setf hour 0 second 0 minute 0)) (:hour (setf second 0 minute 0)) (:minute (setf second 0)) (:second t)) (if (= 0 year month day hour minute) (format stream "0 minutes") (let ((sent? nil)) (when (< 0 year) (format stream "~d year~p" year year) (setf sent? t)) (when (< 0 month) (when sent? (write-char #\Space stream)) (format stream "~d month~p" month month) (setf sent? t)) (when (< 0 day) (when sent? (write-char #\Space stream)) (format stream "~d day~p" day day) (setf sent? t)) (when (< 0 hour) (when sent? (write-char #\Space stream)) (format stream "~d hour~p" hour hour) (setf sent? t)) (when (< 0 minute) (when sent? (write-char #\Space stream)) (format stream "~d min~p" minute minute) (setf sent? t)) (when (< 0 second) (when sent? (write-char #\Space stream)) (format stream "~d sec~p" second second)))) (when return (get-output-stream-string stream)))) (defgeneric midnight (self)) (defmethod midnight ((self wall-time)) "truncate hours, minutes and seconds" (%make-wall-time :mjd (time-mjd self))) (defun roll (date &key (year 0) (month 0) (day 0) (second 0) (hour 0) (minute 0) (usec 0) (destructive nil)) (unless (= 0 year month) (multiple-value-bind (year-orig month-orig day-orig) (time-ymd date) (multiple-value-bind (new-year new-month) (floor (+ month month-orig (* 12 (+ year year-orig))) 12) (let ((new-date (make-time :year new-year :month new-month :day day-orig :second (time-second date) :usec usec))) (if destructive (setf (time-mjd date) (time-mjd new-date)) (setq date new-date)))))) (let ((mjd (time-mjd date)) (sec (time-second date))) (multiple-value-bind (sec-new usec-new) (floor (+ usec (time-usec date) (* 1000000 (+ sec second (* 60 minute) (* 60 60 hour)))) 1000000) (multiple-value-bind (mjd-new sec-new) (floor sec-new (* 60 60 24)) (if destructive (progn (setf (time-mjd date) (+ mjd mjd-new day) (time-second date) sec-new (time-usec date) usec-new) date) (%make-wall-time :mjd (+ mjd mjd-new day) :second sec-new :usec usec-new)))))) (defun roll-to (date size position) (ecase size (:month (ecase position (:beginning (roll date :day (+ 1 (- (time-element date :day-of-month))))) (:end (roll date :day (+ (days-in-month (time-element date :month) (time-element date :year)) (- (time-element date :day-of-month))))))))) (defun week-containing (time) (let* ((midn (midnight time)) (dow (time-element midn :integer-day-of-week))) (list (roll midn :day (- dow)) (roll midn :day (- 7 dow))))) (defun leap-year? (year) "t if YEAR is a leap yeap in the Gregorian calendar" (and (= 0 (mod year 4)) (or (not (= 0 (mod year 100))) (= 0 (mod year 400))))) (defun valid-month-p (month) "t if MONTH exists in the Gregorian calendar" (<= 1 month 12)) (defun valid-gregorian-date-p (date) "t if DATE (year month day) exists in the Gregorian calendar" (let ((max-day (days-in-month (nth 1 date) (nth 0 date)))) (<= 1 (nth 2 date) max-day))) (defun days-in-month (month year &key (careful t)) "the number of days in MONTH of YEAR, observing Gregorian leap year rules" (declare (type fixnum month year)) (when careful (check-type month (satisfies valid-month-p) "between 1 (January) and 12 (December)")) (if (eql month 2) ; feb (if (leap-year? year) 29 28) (let ((even (mod (1- month) 2))) (if (< month 8) ; aug (- 31 even) (+ 30 even))))) (defun day-of-year (year month day &key (careful t)) "the day number within the year of the date DATE. For example, 1987 1 1 returns 1" (declare (type fixnum year month day)) (when careful (let ((date (list year month day))) (check-type date (satisfies valid-gregorian-date-p) "a valid Gregorian date"))) (let ((doy (+ day (* 31 (1- month))))) (declare (type fixnum doy)) (when (< 2 month) (setf doy (- doy (floor (+ 23 (* 4 month)) 10))) (when (leap-year? year) (incf doy))) doy)) (defun parse-yearstring (string) (let ((year (or (parse-integer-insensitively string) (extract-roman string)))) (when (and year (< 1500 year 2500)) (make-time :year year)))) (defun parse-integer-insensitively (string) (let ((start (position-if #'digit-char-p string)) (end (position-if #'digit-char-p string :from-end t))) (when (and start end) (parse-integer (subseq string start (1+ end)) :junk-allowed t)))) (defvar *roman-digits* '((#\M . 1000) (#\D . 500) (#\C . 100) (#\L . 50) (#\X . 10) (#\V . 5) (#\I . 1))) (defun extract-roman (string &aux parse) (dotimes (x (length string)) (let ((val (cdr (assoc (aref string x) *roman-digits*)))) (when (and val parse (< (car parse) val)) (push (- (pop parse)) parse)) (push val parse))) (apply #'+ parse)) ;; ------------------------------------------------------------ ;; Parsing iso-8601 timestrings (define-condition iso-8601-syntax-error (sql-user-error) ((bad-component;; year, month whatever :initarg :bad-component :reader bad-component)) (:report (lambda (c stream) (format stream "Bad component: ~A " (bad-component c))))) (defun parse-timestring (timestring &key (start 0) end junk-allowed) "parse a timestring and return the corresponding wall-time. If the timestring starts with P, read a duration; otherwise read an ISO 8601 formatted date string." (declare (ignore junk-allowed)) (etypecase timestring (wall-time timestring) (date (date->time timestring)) (string (let ((string (subseq timestring start end))) (if (char= (aref string 0) #\P) (parse-iso-8601-duration string) (parse-iso-8601-time string)))))) (defun parse-datestring (datestring &key (start 0) end junk-allowed) "parse a ISO 8601 timestring and return the corresponding date. Will throw a hissy fit if the date string is a duration. Will ignore any precision beyond day (hour/min/sec/usec)." (etypecase datestring (date datestring) (wall-time (time->date datestring)) (string (let ((parsed-value (parse-timestring datestring :start start :end end :junk-allowed junk-allowed))) (etypecase parsed-value (date parsed-value) (wall-time (time->date parsed-value))))))) (defvar *iso-8601-duration-delimiters* '((#\Y . :years) (#\D . :days) (#\H . :hours) (#\M . :months/minutes) (#\S . :seconds))) (defun iso-8601-delimiter (elt) (cdr (assoc elt *iso-8601-duration-delimiters*))) (defun iso-8601-duration-subseq (string end) (let* ((pos (position-if #'iso-8601-delimiter string :end end :from-end t)) (pos2 (when pos (position-if-not #'digit-char-p string :end pos :from-end t))) (number (when pos2 (parse-integer (subseq string (1+ pos2) pos) :junk-allowed t)))) (when number (values number (1+ pos) (1+ pos2) (iso-8601-delimiter (aref string pos)))))) (defun parse-iso-8601-duration (string) "return a wall-time from a duration string" (block parse (let ((years 0) (months 0) (days 0) (secs 0) (hours 0) (minutes 0) (index (length string)) (months/minutes nil)) (loop (multiple-value-bind (duration end next-index duration-type) (iso-8601-duration-subseq string index) (declare (ignore end)) (case duration-type (:years (incf years duration)) (:months/minutes (if months/minutes (incf months duration) (progn (setq months/minutes t) (incf minutes duration)))) (:days (setq months/minutes t) (incf days duration)) (:hours (setq months/minutes t) (incf hours duration)) (:seconds (incf secs duration)) (t (return-from parse (make-duration :year years :month months :day days :hour hours :minute minutes :second secs)))) (setf index next-index)))))) ;; e.g. 2000-11-11 00:00:00-06 (defun parse-iso-8601-time (string) "return the wall-time corresponding to the given ISO 8601 datestring" (multiple-value-bind (year month day hour minute second usec offset) (syntax-parse-iso-8601 string) (make-time :year year :month month :day day :hour hour :minute minute :second second :usec usec :offset offset))) (defun syntax-parse-iso-8601 (string) ;; use strlen to determine if fractional seconds are present in timestamp (let ((strlen (length string)) year month day hour minute second usec gmt-sec-offset) (handler-case (progn (setf year (parse-integer string :start 0 :end 4) month (parse-integer string :start 5 :end 7) day (parse-integer string :start 8 :end 10) hour (if (<= 13 strlen) (parse-integer string :start 11 :end 13) 0) minute (if (<= 16 strlen) (parse-integer string :start 14 :end 16) 0) second (if (<= 19 strlen) (parse-integer string :start 17 :end 19) 0)) (cond ((and (> strlen 19) (or (char= #\, (char string 19)) (char= #\. (char string 19)))) (multiple-value-bind (parsed-usec usec-end) (parse-integer string :start 20 :junk-allowed t) (let ((parsed-usec (and parsed-usec (floor (* parsed-usec (expt 10 (+ 6 (- usec-end) 20))))))) (setf usec (or parsed-usec 0) gmt-sec-offset (if (<= (+ 3 usec-end) strlen) (let ((skip-to (or (position #\+ string :start 19) (position #\- string :start 19)))) (if skip-to (* 60 60 (parse-integer string :start skip-to :end (+ skip-to 3))) 0)) 0))))) (t (setf usec 0 gmt-sec-offset (if (<= 22 strlen) (let ((skip-to (or (position #\+ string :start 19) (position #\- string :start 19)))) (if skip-to (* 60 60 (parse-integer string :start skip-to :end (+ skip-to 3))) 0)) 0)))) (unless (< 0 year) (error 'iso-8601-syntax-error :bad-component '(year . 0))) (unless (< 0 month) (error 'iso-8601-syntax-error :bad-component '(month . 0))) (unless (< 0 day) (error 'iso-8601-syntax-error :bad-component '(month . 0))) (values year month day hour minute second usec gmt-sec-offset)) (simple-error () (error 'iso-8601-syntax-error :bad-component (car (find-if (lambda (pair) (null (cdr pair))) `((year . ,year) (month . ,month) (day . ,day) (hour . ,hour) (minute . ,minute) (second . ,second) (usec . ,usec) (timezone . ,gmt-sec-offset))))))))) cl-sql-6.4.1/sql/sequences.lisp0000644000175000017500000000717311746263021015424 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; ;;;; Generic sequence implementation. Backends should use native sequences if ;;;; are available. ;;;; ;;;; This file is part of CLSQL. ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* (in-package #:clsql-sys) (defclass generic-database (database) () (:documentation "Encapsulate same behavior across backends.")) ;;; Sequence functions (defvar *old-sequence-names* nil "Should CLSQL use its old sequence naming scheme _CLSQL_SEQ_{table} instead of the current scheme {table}_CLSQL_SEQ") (defun %sequence-name-to-table (sequence-name database) (escaped (combine-database-identifiers (if *old-sequence-names* (list '_CLSQL_SEQ sequence-name) (list sequence-name 'CLSQL_SEQ)) database))) (defmethod database-create-sequence (sequence-name database) (let ((table-name (%sequence-name-to-table sequence-name database))) (database-execute-command (concatenate 'string "CREATE TABLE " table-name " (last_value int NOT NULL PRIMARY KEY, increment_by int, min_value int, is_called char(1))") database) (database-execute-command (concatenate 'string "INSERT INTO " table-name " VALUES (1,1,1,'f')") database))) (defmethod database-drop-sequence (sequence-name database) (database-execute-command (concatenate 'string "DROP TABLE " (%sequence-name-to-table sequence-name database)) database)) (defun %seq-name-key () (if *old-sequence-names* "_CLSQL_SEQ_" "_CLSQL_SEQ")) (defun %table-name-to-sequence-name (table-name) ;; if this was escaped it still should be, ;; if it wasnt it still shouldnt-be (check-type table-name string) (replace-all table-name (%seq-name-key) "")) (defmethod database-list-sequences (database &key (owner nil)) (declare (ignore owner)) (mapcan #'(lambda (s) (and (search (%seq-name-key) s :test #'string-equal) (list (%table-name-to-sequence-name s)))) (database-list-tables-and-sequences database))) (defmethod database-set-sequence-position (sequence-name position database) (database-execute-command (format nil "UPDATE ~A SET last_value=~A,is_called='t'" (%sequence-name-to-table sequence-name database) position) database) position) (defmethod database-sequence-next (sequence-name database) (without-interrupts (let* ((table-name (%sequence-name-to-table sequence-name database)) (tuple (car (database-query (concatenate 'string "SELECT last_value,is_called FROM " table-name) database :auto nil)))) (cond ((char-equal (schar (second tuple) 0) #\f) (database-execute-command (format nil "UPDATE ~A SET is_called='t'" table-name) database) (car tuple)) (t (let ((new-pos (1+ (car tuple)))) (database-execute-command (format nil "UPDATE ~A SET last_value=~D" table-name new-pos) database) new-pos)))))) (defmethod database-sequence-last (sequence-name database) (without-interrupts (caar (database-query (concatenate 'string "SELECT last_value FROM " (%sequence-name-to-table sequence-name database)) database :auto nil)))) cl-sql-6.4.1/sql/fdml.lisp0000644000175000017500000005370712064366222014360 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; ;;;; The CLSQL Functional Data Manipulation Language (FDML). ;;;; ;;;; This file is part of CLSQL. ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* (in-package #:clsql-sys) ;; some helpers to make dealing with attribute-value-pairs a bit more structured (defclass attribute-value-pair () ((attribute :accessor attribute :initarg :attribute :initform nil) (db-value :accessor db-value :initarg :db-value :initform nil)) (:documentation "Represents an attribute-sql-expression and its value, used to pass to insert/update. Was previously a two list")) (defun make-attribute-value-pair (slot-def value database) (check-slot-type slot-def value) (make-instance 'attribute-value-pair :attribute (sql-expression :attribute (database-identifier slot-def database)) :db-value (db-value-from-slot slot-def value database))) (defun to-attributes-and-values (av-pairs) (etypecase (first av-pairs) (list (loop for (a v) in av-pairs collect a into attributes collect v into db-values finally (return (values attributes db-values)))) (attribute-value-pair (loop for pair in av-pairs collecting (attribute pair) into attributes collecting (db-value pair) into db-values finally (return (values attributes db-values)))))) ;;; Basic operations on databases (defmethod database-query-result-set ((expr %sql-expression) database &key full-set result-types) (database-query-result-set (sql-output expr database) database :full-set full-set :result-types result-types)) (defmethod execute-command ((sql-expression string) &key (database *default-database*)) (record-sql-command sql-expression database) (let ((res (database-execute-command sql-expression database))) (record-sql-result res database)) (values)) (defmethod execute-command ((expr %sql-expression) &key (database *default-database*)) (execute-command (sql-output expr database) :database database) (values)) (defmethod query ((query-expression string) &key (database *default-database*) (result-types :auto) (flatp nil) (field-names t)) (record-sql-command query-expression database) (multiple-value-bind (rows names) (database-query query-expression database result-types field-names) (let ((result (if (and flatp (= 1 (length (car rows)))) (mapcar #'car rows) rows))) (record-sql-result result database) (if field-names (values result names) result)))) (defmethod query ((expr %sql-expression) &key (database *default-database*) (result-types :auto) (flatp nil) (field-names t)) (query (sql-output expr database) :database database :flatp flatp :result-types result-types :field-names field-names)) (defmethod query ((expr sql-object-query) &key (database *default-database*) (result-types :auto) (flatp nil) (field-names t)) (declare (ignore result-types field-names)) (apply #'select (append (slot-value expr 'objects) (slot-value expr 'exp) (when (slot-value expr 'refresh) (list :refresh (sql-output expr database))) (when (or flatp (slot-value expr 'flatp) ) (list :flatp t)) (list :database database)))) (defun print-query (query-exp &key titles (formats t) (sizes t) (stream t) (database *default-database*)) "Prints a tabular report of the results returned by the SQL query QUERY-EXP, which may be a symbolic SQL expression or a string, in DATABASE which defaults to *DEFAULT-DATABASE*. The report is printed onto STREAM which has a default value of t which means that *STANDARD-OUTPUT* is used. The TITLE argument, which defaults to nil, allows the specification of a list of strings to use as column titles in the tabular output. SIZES accepts a list of column sizes, one for each column selected by QUERY-EXP, to use in formatting the tabular report. The default value of t means that minimum sizes are computed. FORMATS is a list of format strings to be used for printing each column selected by QUERY-EXP. The default value of FORMATS is t meaning that ~A is used to format all columns or ~VA if column sizes are used." (flet ((compute-sizes (data) (mapcar #'(lambda (x) (apply #'max (mapcar #'(lambda (y) (if (null y) 3 (length y))) x))) (apply #'mapcar (cons #'list data)))) (format-record (record control sizes) (format stream "~&~?" control (if (null sizes) record (mapcan #'(lambda (s f) (list s f)) sizes record))))) (let* ((query-exp (etypecase query-exp (string query-exp) (sql-query (sql-output query-exp database)))) (data (query query-exp :database database :result-types nil :field-names nil)) (sizes (if (or (null sizes) (listp sizes)) sizes (compute-sizes (if titles (cons titles data) data)))) (formats (if (or (null formats) (not (listp formats))) (make-list (length (car data)) :initial-element (if (null sizes) "~A " "~VA ")) formats)) (control-string (format nil "~{~A~}" formats))) (when titles (format-record titles control-string sizes)) (dolist (d data (values)) (format-record d control-string sizes))))) (defun insert-records (&key (into nil) (attributes nil) (values nil) (av-pairs nil) (query nil) (database *default-database*)) "Inserts records into the table specified by INTO in DATABASE which defaults to *DEFAULT-DATABASE*. There are five ways of specifying the values inserted into each row. In the first VALUES contains a list of values to insert and ATTRIBUTES, AV-PAIRS and QUERY are nil. This can be used when values are supplied for all attributes in INTO. In the second, ATTRIBUTES is a list of column names, VALUES is a corresponding list of values and AV-PAIRS and QUERY are nil. In the third, ATTRIBUTES, VALUES and QUERY are nil and AV-PAIRS is a list of (attribute value) pairs, or attribute-value-pair objects. In the fourth, VALUES, AV-PAIRS and ATTRIBUTES are nil and QUERY is a symbolic SQL query expression in which the selected columns also exist in INTO. In the fifth method, VALUES and AV-PAIRS are nil and ATTRIBUTES is a list of column names and QUERY is a symbolic SQL query expression which returns values for the specified columns." (let ((stmt (make-sql-insert :into into :attrs attributes :vals values :av-pairs av-pairs :subquery query))) (execute-command stmt :database database))) (defun make-sql-insert (&key (into nil) (attrs nil) (vals nil) (av-pairs nil) (subquery nil)) (unless into (error 'sql-user-error :message ":into keyword not supplied")) (let ((insert (make-instance 'sql-insert :into (database-identifier into nil)))) (with-slots (attributes values query) insert (cond ((and vals (not attrs) (not query) (not av-pairs)) (setf values vals)) ((and vals attrs (not subquery) (not av-pairs)) (setf attributes attrs) (setf values vals)) ((and av-pairs (not vals) (not attrs) (not subquery)) (multiple-value-setq (attributes values) (to-attributes-and-values av-pairs))) ((and subquery (not vals) (not attrs) (not av-pairs)) (setf query subquery)) ((and subquery attrs (not vals) (not av-pairs)) (setf attributes attrs) (setf query subquery)) (t (error 'sql-user-error :message "bad or ambiguous keyword combination."))) insert))) (defun delete-records (&key (from nil) (where nil) (database *default-database*)) "Deletes records satisfying the SQL expression WHERE from the table specified by FROM in DATABASE specifies a database which defaults to *DEFAULT-DATABASE*." (let ((stmt (make-instance 'sql-delete :from (database-identifier from database) :where where))) (execute-command stmt :database database))) (defun update-records (table &key (attributes nil) (values nil) (av-pairs nil) (where nil) (database *default-database*)) "Updates the attribute values of existing records satsifying the SQL expression WHERE in the table specified by TABLE in DATABASE which defaults to *DEFAULT-DATABASE*. There are three ways of specifying the values to update for each row. In the first, VALUES contains a list of values to use in the update and ATTRIBUTES and AV-PAIRS are nil. This can be used when values are supplied for all attributes in TABLE. In the second, ATTRIBUTES is a list of column names, VALUES is a corresponding list of values and AV-PAIRS is nil. In the third, ATTRIBUTES and VALUES are nil and AV-PAIRS is an alist of (attribute value) pairs." (when av-pairs (multiple-value-setq (attributes values) (to-attributes-and-values av-pairs))) (let ((stmt (make-instance 'sql-update :table (database-identifier table database) :attributes attributes :values values :where where))) (execute-command stmt :database database))) ;;; Iteration (defmacro do-query (((&rest args) query-expression &key (database '*default-database*) (result-types :auto)) &body body) "Repeatedly executes BODY within a binding of ARGS on the fields of each row selected by the SQL query QUERY-EXPRESSION, which may be a string or a symbolic SQL expression, in DATABASE which defaults to *DEFAULT-DATABASE*. The values returned by the execution of BODY are returned. RESULT-TYPES is a list of symbols which specifies the lisp type for each field returned by QUERY-EXPRESSION. If RESULT-TYPES is nil all results are returned as strings whereas the default value of :auto means that the lisp types are automatically computed for each field." (let ((result-set (gensym "RESULT-SET-")) (qe (gensym "QUERY-EXPRESSION-")) (columns (gensym "COLUMNS-")) (row (gensym "ROW-")) (db (gensym "DB-")) (last-form-eval (gensym "LFE-"))) `(let ((,qe ,query-expression) (,db ,database)) (typecase ,qe (sql-object-query (dolist (,row (query ,qe :database ,db)) (destructuring-bind ,args ,row ,@body))) (t ;; Functional query (multiple-value-bind (,result-set ,columns) (database-query-result-set ,qe ,db :full-set nil :result-types ,result-types) (when ,result-set (unwind-protect (do ((,row (make-list ,columns)) (,last-form-eval nil)) ((not (database-store-next-row ,result-set ,db ,row)) ,last-form-eval) (destructuring-bind ,args ,row (setq ,last-form-eval (progn ,@body)))) (database-dump-result-set ,result-set ,db))))))))) (defun map-query (output-type-spec function query-expression &key (database *default-database*) (result-types :auto)) "Map the function FUNCTION over the attribute values of each row selected by the SQL query QUERY-EXPRESSION, which may be a string or a symbolic SQL expression, in DATABASE which defaults to *DEFAULT-DATABASE*. The results of the function are collected as specified in OUTPUT-TYPE-SPEC and returned like in MAP. RESULT-TYPES is a list of symbols which specifies the lisp type for each field returned by QUERY-EXPRESSION. If RESULT-TYPES is nil all results are returned as strings whereas the default value of :auto means that the lisp types are automatically computed for each field." (typecase query-expression (sql-object-query (map output-type-spec #'(lambda (x) (apply function x)) (query query-expression))) (t ;; Functional query (macrolet ((type-specifier-atom (type) `(if (atom ,type) ,type (car ,type)))) (case (type-specifier-atom output-type-spec) ((nil) (map-query-for-effect function query-expression database result-types)) (list (map-query-to-list function query-expression database result-types)) ((simple-vector simple-string vector string array simple-array bit-vector simple-bit-vector base-string simple-base-string) (map-query-to-simple output-type-spec function query-expression database result-types)) (t (funcall #'map-query (cmucl-compat:result-type-or-lose output-type-spec t) function query-expression :database database :result-types result-types))))))) (defun map-query-for-effect (function query-expression database result-types) (multiple-value-bind (result-set columns) (database-query-result-set query-expression database :full-set nil :result-types result-types) (let ((flatp (and (= columns 1) (typep query-expression 'sql-query) (slot-value query-expression 'flatp)))) (when result-set (unwind-protect (do ((row (make-list columns))) ((not (database-store-next-row result-set database row)) nil) (if flatp (apply function row) (funcall function row))) (database-dump-result-set result-set database)))))) (defun map-query-to-list (function query-expression database result-types) (multiple-value-bind (result-set columns) (database-query-result-set query-expression database :full-set nil :result-types result-types) (let ((flatp (and (= columns 1) (typep query-expression 'sql-query) (slot-value query-expression 'flatp)))) (when result-set (unwind-protect (let ((result (list nil))) (do ((row (make-list columns)) (current-cons result (cdr current-cons))) ((not (database-store-next-row result-set database row)) (cdr result)) (rplacd current-cons (list (if flatp (apply function row) (funcall function (copy-list row))))))) (database-dump-result-set result-set database)))))) (defun map-query-to-simple (output-type-spec function query-expression database result-types) (multiple-value-bind (result-set columns rows) (database-query-result-set query-expression database :full-set t :result-types result-types) (let ((flatp (and (= columns 1) (typep query-expression 'sql-query) (slot-value query-expression 'flatp)))) (when result-set (unwind-protect (if rows ;; We know the row count in advance, so we allocate once (do ((result (cmucl-compat:make-sequence-of-type output-type-spec rows)) (row (make-list columns)) (index 0 (1+ index))) ((not (database-store-next-row result-set database row)) result) (declare (fixnum index)) (setf (aref result index) (if flatp (apply function row) (funcall function (copy-list row))))) ;; Database can't report row count in advance, so we have ;; to grow and shrink our vector dynamically (do ((result (cmucl-compat:make-sequence-of-type output-type-spec 100)) (allocated-length 100) (row (make-list columns)) (index 0 (1+ index))) ((not (database-store-next-row result-set database row)) (cmucl-compat:shrink-vector result index)) (declare (fixnum allocated-length index)) (when (>= index allocated-length) (setq allocated-length (* allocated-length 2) result (adjust-array result allocated-length))) (setf (aref result index) (if flatp (apply function row) (funcall function (copy-list row)))))) (database-dump-result-set result-set database)))))) ;;; Row processing macro from CLSQL (defmacro for-each-row (((&rest fields) &key from order-by where distinct limit) &body body) (let ((d (gensym "DISTINCT-")) (bind-fields (loop for f in fields collect (car f))) (w (gensym "WHERE-")) (o (gensym "ORDER-BY-")) (frm (gensym "FROM-")) (l (gensym "LIMIT-")) (q (gensym "QUERY-"))) `(let ((,frm ,from) (,w ,where) (,d ,distinct) (,l ,limit) (,o ,order-by)) (let ((,q (query-string ',fields ,frm ,w ,d ,o ,l))) (loop for tuple in (query ,q) collect (destructuring-bind ,bind-fields tuple ,@body)))))) (defun query-string (fields from where distinct order-by limit) (concatenate 'string (format nil "select ~A~{~A~^,~} from ~{~A~^ and ~}" (if distinct "distinct " "") (field-names fields) (from-names from)) (if where (format nil " where ~{~A~^ ~}" (where-strings where)) "") (if order-by (format nil " order by ~{~A~^, ~}" (order-by-strings order-by))) (if limit (format nil " limit ~D" limit) ""))) (defun lisp->sql-name (field) (typecase field (string field) (symbol (string-upcase (symbol-name field))) (cons (cadr field)) (t (format nil "~A" field)))) (defun field-names (field-forms) "Return a list of field name strings from a fields form" (loop for field-form in field-forms collect (lisp->sql-name (if (cadr field-form) (cadr field-form) (car field-form))))) (defun from-names (from) "Return a list of field name strings from a fields form" (loop for table in (if (atom from) (list from) from) collect (lisp->sql-name table))) (defun where-strings (where) (loop for w in (if (atom (car where)) (list where) where) collect (if (consp w) (format nil "~A ~A ~A" (second w) (first w) (third w)) (format nil "~A" w)))) (defun order-by-strings (order-by) (loop for o in order-by collect (if (atom o) (lisp->sql-name o) (format nil "~A ~A" (lisp->sql-name (car o)) (lisp->sql-name (cadr o)))))) ;;; Large objects support (defun create-large-object (&key (database *default-database*)) "Creates a new large object in the database and returns the object identifier" (database-create-large-object database)) (defun write-large-object (object-id data &key (database *default-database*)) "Writes data to the large object" (database-write-large-object object-id data database)) (defun read-large-object (object-id &key (database *default-database*)) "Reads the large object content" (database-read-large-object object-id database)) (defun delete-large-object (object-id &key (database *default-database*)) "Deletes the large object in the database" (database-delete-large-object object-id database)) ;;; Prepared statements (defun prepare-sql (sql-stmt types &key (database *default-database*) (result-types :auto) field-names) "Prepares a SQL statement for execution. TYPES contains a list of types corresponding to the input parameters. Returns a prepared-statement object. A type can be :int :double :null (:blob n) (:string n) " (unless (db-type-has-prepared-stmt? (database-type database)) (error 'sql-user-error :message (format nil "Database backend type ~:@(~A~) does not support prepared statements." (database-type database)))) (database-prepare sql-stmt types database result-types field-names)) (defun bind-parameter (prepared-stmt position value) "Sets the value of a parameter is in prepared statement." (database-bind-parameter prepared-stmt position value) value) (defun run-prepared-sql (prepared-stmt) "Execute the prepared sql statment. All input parameters must be bound." (database-run-prepared prepared-stmt)) (defun free-prepared-sql (prepared-stmt) "Delete the objects associated with a prepared statement." (database-free-prepared prepared-stmt)) cl-sql-6.4.1/sql/Makefile0000644000175000017500000000126711335067642014203 0ustar kevinkevin#!/usr/bin/make ########################################################################## # FILE IDENTIFICATION # # Name: Makefile # Purpose: Makefile for CLSQL SQL interface # Programer: Kevin M. Rosenberg # Date Started: Mar 2002 # # This file, part of CLSQL, is Copyright (c) 2002-2010 by Kevin M. Rosenberg # # CLSQL users are granted the rights to distribute and use this software # as governed by the terms of the Lisp Lesser GNU Public License # (http://opensource.franz.com/preamble.html), also known as the LLGPL. ########################################################################## SUBDIRS= include ../Makefile.common .PHONY: distclean distclean: clean cl-sql-6.4.1/sql/syntax.lisp0000644000175000017500000001772211616055736014770 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; ;;;; CLSQL square bracket symbolic query syntax. Functions for ;;;; enabling and disabling the syntax and for building SQL ;;;; expressions using the syntax. ;;;; ;;;; This file is part of CLSQL. ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* (in-package #:clsql-sys) (defvar *original-readtable* nil) (defvar *sql-macro-open-char* #\[) (defvar *sql-macro-close-char* #\]) (defvar *restore-sql-reader-syntax* nil) ;; Exported functions for disabling SQL syntax. (defmacro disable-sql-reader-syntax () "Turns off the SQL reader syntax setting the syntax state such that if the syntax is subsequently enabled, RESTORE-SQL-READER-SYNTAX-STATE will disable it again." '(eval-when (:compile-toplevel :load-toplevel :execute) (setf *restore-sql-reader-syntax* nil) (%disable-sql-reader-syntax))) (defmacro locally-disable-sql-reader-syntax () "Turns off the SQL reader syntax without changing the syntax state such that RESTORE-SQL-READER-SYNTAX-STATE will re-establish the current syntax state." '(eval-when (:compile-toplevel :load-toplevel :execute) (%disable-sql-reader-syntax))) (defun %disable-sql-reader-syntax () (when *original-readtable* (setf *readtable* *original-readtable* *original-readtable* nil)) (values)) ;; Exported functions for enabling SQL syntax. (defmacro enable-sql-reader-syntax () "Turns on the SQL reader syntax setting the syntax state such that if the syntax is subsequently disabled, RESTORE-SQL-READER-SYNTAX-STATE will enable it again." '(eval-when (:compile-toplevel :load-toplevel :execute) (setf *restore-sql-reader-syntax* t) (%enable-sql-reader-syntax))) (defmacro locally-enable-sql-reader-syntax () "Turns on the SQL reader syntax without changing the syntax state such that RESTORE-SQL-READER-SYNTAX-STATE will re-establish the current syntax state." '(eval-when (:compile-toplevel :load-toplevel :execute) (%enable-sql-reader-syntax))) (defmacro file-enable-sql-reader-syntax () "Turns on the SQL reader syntax for the rest of the file. The CL spec says that when finished loading a file the original *readtable* is restored. clhs COMPILE-FILE" '(eval-when (:compile-toplevel :load-toplevel :execute) (setf *readtable* (copy-readtable)) (set-macro-character *sql-macro-open-char* #'sql-reader-open) (set-macro-character *sql-macro-close-char* (get-macro-character #\))))) (defun %enable-sql-reader-syntax () (unless *original-readtable* (setf *original-readtable* *readtable* *readtable* (copy-readtable)) (set-macro-character *sql-macro-open-char* #'sql-reader-open) (set-macro-character *sql-macro-close-char* (get-macro-character #\)))) (values)) (defmacro restore-sql-reader-syntax-state () "Enables the SQL reader syntax if ENABLE-SQL-READER-SYNTAX has been called more recently than DISABLE-SQL-READER-SYNTAX and otherwise disables the SQL reader syntax. By default, the SQL reader syntax is disabled." '(eval-when (:compile-toplevel :load-toplevel :execute) (if *restore-sql-reader-syntax* (%enable-sql-reader-syntax) (%disable-sql-reader-syntax)))) (defun sql-reader-open (stream char) (declare (ignore char)) (let ((sqllist (read-delimited-list #\] stream t))) (unless *read-suppress* (handler-case (cond ((string= (write-to-string (car sqllist)) "||") (cons (sql-operator 'concat-op) (cdr sqllist))) ((and (= (length sqllist) 1) (eql (car sqllist) '*)) (apply #'generate-sql-reference sqllist)) ((sql-operator (car sqllist)) (cons (sql-operator (car sqllist)) (cdr sqllist))) (t (apply #'generate-sql-reference sqllist))) (sql-user-error (c) (error 'sql-user-error :message (format nil "Error ~A occured while attempting to parse '~A' at file position ~A" (sql-user-error-message c) sqllist (file-position stream)))))))) (defun generate-sql-reference (&rest arglist) (cond ((= (length arglist) 1) ; string, table or attribute (let ((arg (first arglist))) (typecase arg (string (sql-expression :string arg)) (symbol ;; handle . separated names (let* ((sn (symbol-name arg)) (idx (position #\. sn))) (cond (idx (sql-expression :table (intern (subseq sn 0 idx)) :attribute (intern (subseq sn (+ idx 1))) )) (T (sql-expression :attribute arg)))) )))) ((<= 2 (length arglist)) (let ((sqltype (when (keywordp (caddr arglist)) (caddr arglist) nil))) (cond ((stringp (cadr arglist)) (sql-expression :table (car arglist) :alias (cadr arglist) :type sqltype)) ((keywordp (cadr arglist)) (sql-expression :attribute (car arglist) :type (cadr arglist))) (t (sql-expression :attribute (cadr arglist) :table (car arglist) :type sqltype))))) (t (error 'sql-user-error :message "bad expression syntax")))) ;; Exported functions for dealing with SQL syntax (defun sql (&rest args) "Returns an SQL string generated from the expressions ARGS. The expressions are translated into SQL strings and then concatenated with a single space delimiting each expression. An error of type SQL-USER-ERROR is signalled if any element in ARGS is not of the supported types (a symbol, string, number or symbolic SQL expression) or a list or vector containing only these supported types." (format nil "~{~A~^ ~}" (mapcar #'sql-output args))) (defun sql-expression (&key string table alias attribute type) "Returns an SQL expression constructed from the supplied arguments which may be combined as follows: ATTRIBUTE and TYPE; ATTRIBUTE; ALIAS or TABLE and ATTRIBUTE and TYPE; ALIAS or TABLE and ATTRIBUTE; TABLE, ATTRIBUTE and TYPE; TABLE and ATTRIBUTE; TABLE and ALIAS; TABLE; and STRING. An error of type SQL-USER-ERROR is signalled if an unsupported combination of keyword arguments is specified." (cond (string (make-instance 'sql :string string)) (attribute (make-instance 'sql-ident-attribute :name attribute :qualifier (or table alias) :type type)) ((and table (not attribute)) (make-instance 'sql-ident-table :name table :table-alias alias)))) (defun sql-operator (operator) "Returns the Lisp symbol corresponding to the SQL operator represented by the symbol OPERATOR. If OPERATOR does not represent a supported SQL operator or is not a symbol, nil is returned." (typecase operator (string nil) (symbol (values (gethash (symbol-name-default-case (symbol-name operator)) *sql-op-table*))))) (defun sql-operation (operator &rest args) "Returns an SQL expression constructed from the supplied symbol OPERATOR representing an SQL operator or function and its arguments ARGS. An error of type SQL-USER-ERROR is signalled if OPERATOR is not a symbol representing a supported SQL operator. If OPERATOR is passed the symbol FUNCTION then the first value in ARGS must be a string representing a valid SQL function and the remaining values in ARGS its arguments as strings." (if (sql-operator operator) (apply (symbol-function (sql-operator operator)) args) (error 'sql-user-error :message (format nil "~A is not a recognized SQL operator." operator)))) cl-sql-6.4.1/sql/conditions.lisp0000644000175000017500000001323311616055736015604 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; FILE IDENTIFICATION ;;;; ;;;; Name: conditions.lisp ;;;; Purpose: Error conditions for CLSQL ;;;; ;;;; This file, part of CLSQL, is Copyright (c) 2002-2010 by Kevin M. Rosenberg ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* (in-package #:clsql-sys) (defvar *backend-warning-behavior* :warn "Action to perform on warning messages from backend. Default is to :warn. May also be set to :error to signal an error or :ignore/nil to silently ignore the warning.") ;;; CommonSQL-compatible conditions (define-condition sql-condition () ()) (define-condition sql-error (simple-error sql-condition) ()) (define-condition sql-database-error (sql-error) ((error-id :initarg :error-id :initform nil :reader sql-error-error-id) (secondary-error-id :initarg :secondary-error-id :initform nil :reader sql-error-secondary-error-id) (database-message :initarg :message :initform nil :reader sql-error-database-message) (database :initarg :database :initform nil :reader sql-error-database)) (:report (lambda (c stream) (format stream "A database error occurred~@[ on database ~A~]: ~A / ~A~% ~A" (sql-error-database c) (sql-error-error-id c) (sql-error-secondary-error-id c) (sql-error-database-message c)))) (:documentation "Used to signal an error in a CLSQL database interface.")) (define-condition sql-connection-error (sql-database-error) ((database-type :initarg :database-type :initform nil :reader sql-error-database-type) (connection-spec :initarg :connection-spec :initform nil :reader sql-error-connection-spec)) (:report (lambda (c stream) (format stream "While trying to connect to database ~A~% using database-type ~A:~% Error ~D / ~A~% has occurred." (when (and (sql-error-connection-spec c) (sql-error-database-type c)) (database-name-from-spec (sql-error-connection-spec c) (sql-error-database-type c))) (sql-error-database-type c) (sql-error-error-id c) (sql-error-database-message c)))) (:documentation "Used to signal an error in connecting to a database.")) (define-condition sql-database-data-error (sql-database-error) ((expression :initarg :expression :initarg nil :reader sql-error-expression)) (:report (lambda (c stream) (format stream "While accessing database ~A~% with expression ~S:~% Error ~D / ~A~% has occurred." (sql-error-database c) (sql-error-expression c) (sql-error-error-id c) (sql-error-database-message c)))) (:documentation "Used to signal an error with the SQL data passed to a database.")) (define-condition sql-temporary-error (sql-database-error) () (:documentation "Used to signal an error when the database cannot currently process a valid interaction because, for example, it is still executing another command possibly issued by another user.")) (define-condition sql-timeout-error (sql-connection-error) () (:documentation "Used to signal an error when the database times out while processing some operation.")) (define-condition sql-fatal-error (sql-connection-error) () (:documentation "Used to signal an error when the database connection is no longer usable.")) (define-condition sql-user-error (sql-error) ((message :initarg :message :initform "Unspecified error" :reader sql-user-error-message)) (:report (lambda (c stream) (format stream "A CLSQL lisp code error occurred: ~A " (sql-user-error-message c)))) (:documentation "Used to signal lisp errors inside CLSQL.")) ;; Signal conditions (defun signal-closed-database-error (database) (error 'sql-fatal-error :database database :connection-spec (when database (connection-spec database)) :database-type (when database (database-type database)) :message "Database is closed.")) (defun signal-no-database-error (database) (error 'sql-database-error :database database :message (format nil "~A is not a database." database))) ;;; CLSQL Extensions (define-condition sql-warning (warning sql-condition) ((message :initarg :message :initform nil :reader sql-warning-message)) (:report (lambda (c stream) (format stream "~A" (sql-warning-message c))))) (define-condition sql-database-warning (sql-warning) ((database :initarg :database :reader sql-warning-database)) (:report (lambda (c stream) (format stream "While accessing database ~A~% Warning: ~A~% has occurred." (sql-warning-database c) (sql-warning-message c))))) (define-condition database-too-strange (sql-user-error) () (:documentation "Used to signal cases where CLSQL is going to fail at mapping your database correctly")) (defun signal-database-too-strange (message) (error 'database-too-strange :message message)) cl-sql-6.4.1/sql/generic-postgresql.lisp0000644000175000017500000004344612064366222017252 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; ;;;; Generic postgresql layer, used by db-postgresql and db-postgresql-socket ;;;; ;;;; This file is part of CLSQL. ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* (in-package #:clsql-sys) (defclass generic-postgresql-database (database) ((has-table-pg_roles :type boolean :reader has-table-pg_roles :initform nil)) (:documentation "Encapsulate same behavior across postgresql and postgresql-socket backends.")) ;; Object functions (defmethod database-get-type-specifier (type args database (db-type (eql :postgresql))) (declare (ignore type args database)) "VARCHAR") (defmethod database-get-type-specifier ((type (eql 'string)) args database (db-type (eql :postgresql))) (declare (ignore database)) (if args (format nil "CHAR(~A)" (car args)) "VARCHAR")) (defmethod database-get-type-specifier ((type (eql 'tinyint)) args database (db-type (eql :postgresql))) (declare (ignore args database)) "INT2") (defmethod database-get-type-specifier ((type (eql 'smallint)) args database (db-type (eql :postgresql))) (declare (ignore args database)) "INT2") (defmethod database-get-type-specifier ((type (eql 'wall-time)) args database (db-type (eql :postgresql))) (declare (ignore args database)) "TIMESTAMP WITHOUT TIME ZONE") (defmethod database-get-type-specifier ((type (eql 'number)) args database (db-type (eql :postgresql))) (declare (ignore database)) (cond ((and (consp args) (= (length args) 2)) (format nil "NUMERIC(~D,~D)" (first args) (second args))) ((and (consp args) (= (length args) 1)) (format nil "NUMERIC(~D)" (first args))) (t "NUMERIC"))) ;;; Backend functions (defun owner-clause (owner) (cond ((stringp owner) (format nil " AND (relowner=(SELECT usesysid FROM pg_user WHERE (usename='~A')))" owner)) ((null owner) (format nil " AND (relowner<>(SELECT usesysid FROM pg_user WHERE usename='postgres'))")) (t ""))) (defun has-table (name database) (let ((name-retrieved (caar (database-query (format nil "SELECT relname FROM pg_class WHERE relname='~A'" name) database nil nil)))) (if (and (stringp name-retrieved) (plusp (length name-retrieved))) t nil))) (defmethod slot-unbound (class (obj generic-postgresql-database) (slot (eql 'has-table-pg_roles))) ;; Lazily cache slot value (declare (ignore class)) (setf (slot-value obj 'has-table-pg_roles) (has-table "pg_roles" obj))) (defun database-list-objects-of-type (database type owner) (mapcar #'car (database-query (format nil (if (and (has-table-pg_roles database) (not (eq owner :all))) " SELECT c.relname FROM pg_catalog.pg_class c LEFT JOIN pg_catalog.pg_roles r ON r.oid = c.relowner LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace WHERE c.relkind IN ('~A','') AND n.nspname NOT IN ('pg_catalog', 'pg_toast') AND pg_catalog.pg_table_is_visible(c.oid) ~A" "SELECT relname FROM pg_class WHERE (relkind = '~A')~A") type (owner-clause owner)) database nil nil))) (defmethod database-list-tables ((database generic-postgresql-database) &key (owner nil)) (database-list-objects-of-type database "r" owner)) (defmethod database-list-views ((database generic-postgresql-database) &key (owner nil)) (database-list-objects-of-type database "v" owner)) (defmethod database-list-indexes ((database generic-postgresql-database) &key (owner nil)) (database-list-objects-of-type database "i" owner)) (defmethod database-list-table-indexes (table (database generic-postgresql-database) &key (owner nil)) (let ((indexrelids (database-query (format nil "select indexrelid from pg_index where indrelid=(select relfilenode from pg_class where LOWER(relname)='~A'~A)" (string-downcase (unescaped-database-identifier table)) (owner-clause owner)) database :auto nil)) (result nil)) (dolist (indexrelid indexrelids (nreverse result)) (push (caar (database-query (format nil "select relname from pg_class where relfilenode='~A'" (car indexrelid)) database nil nil)) result)))) (defmethod database-list-attributes ((table %database-identifier) (database generic-postgresql-database) &key (owner nil)) (let* ((table (unescaped-database-identifier table)) (owner-clause (cond ((stringp owner) (format nil " AND (relowner=(SELECT usesysid FROM pg_user WHERE usename='~A'))" owner)) ((null owner) " AND (not (relowner=1))") (t ""))) (result (mapcar #'car (database-query (format nil "SELECT attname FROM pg_class,pg_attribute WHERE pg_class.oid=attrelid AND attisdropped = FALSE AND relname='~A'~A" (string-downcase table) owner-clause) database nil nil)))) (if result (remove-if #'(lambda (it) (member it '("cmin" "cmax" "xmax" "xmin" "oid" "ctid" ;; kmr -- added tableoid "tableoid") :test #'equal)) result)))) (defmethod database-attribute-type ((attribute %database-identifier) (table %database-identifier) (database generic-postgresql-database) &key (owner nil) &aux (table (unescaped-database-identifier table)) (attribute (unescaped-database-identifier attribute))) (let ((row (car (database-query (format nil "SELECT pg_type.typname,pg_attribute.attlen,pg_attribute.atttypmod,pg_attribute.attnotnull FROM pg_type,pg_class,pg_attribute WHERE pg_class.oid=pg_attribute.attrelid AND pg_class.relname='~A' AND pg_attribute.attname='~A' AND pg_attribute.atttypid=pg_type.oid~A" (string-downcase table) (string-downcase attribute) (owner-clause owner)) database nil nil)))) (when row (destructuring-bind (typname attlen atttypmod attnull) row (setf attlen (%get-int attlen) atttypmod (%get-int atttypmod)) (let ((coltype (ensure-keyword typname)) (colnull (typecase attnull (string (if (string-equal "f" attnull) 1 0)) (null 1) (T 0))) collen colprec) (setf (values collen colprec) (case coltype ((:numeric :decimal) (if (= -1 atttypmod) (values nil nil) (values (ash (- atttypmod 4) -16) (boole boole-and (- atttypmod 4) #xffff)))) (otherwise (values (cond ((and (= -1 attlen) (= -1 atttypmod)) nil) ((= -1 attlen) (- atttypmod 4)) (t attlen)) nil)))) (values coltype collen colprec colnull)))))) (defmethod database-create-sequence (sequence-name (database generic-postgresql-database)) (let ((cmd (concatenate 'string "CREATE SEQUENCE " (escaped-database-identifier sequence-name database)))) (database-execute-command cmd database))) (defmethod database-drop-sequence (sequence-name (database generic-postgresql-database)) (database-execute-command (concatenate 'string "DROP SEQUENCE " (escaped-database-identifier sequence-name database)) database)) (defmethod database-list-sequences ((database generic-postgresql-database) &key (owner nil)) (database-list-objects-of-type database "S" owner)) (defmethod database-set-sequence-position (name (position integer) (database generic-postgresql-database)) (values (%get-int (caar (database-query (format nil "SELECT SETVAL ('~A', ~A)" (escaped-database-identifier name) position) database nil nil))))) (defmethod database-sequence-next (sequence-name (database generic-postgresql-database)) (values (%get-int (caar (database-query (concatenate 'string "SELECT NEXTVAL ('" (escaped-database-identifier sequence-name) "')") database nil nil))))) (defmethod database-sequence-last (sequence-name (database generic-postgresql-database)) (values (%get-int (caar (database-query (concatenate 'string "SELECT LAST_VALUE FROM " (escaped-database-identifier sequence-name)) database nil nil))))) (defmethod auto-increment-sequence-name (table column (database generic-postgresql-database)) (let* ((sequence-name (or (database-identifier (slot-value column 'autoincrement-sequence)) (combine-database-identifiers (list table column 'seq) database)))) (when (search "'" (escaped-database-identifier sequence-name) :test #'string-equal) (signal-database-too-strange "PG Sequence names shouldnt contain single quotes for the sake of sanity")) sequence-name)) (defmethod database-last-auto-increment-id ((database generic-postgresql-database) table column) (let ((seq-name (auto-increment-sequence-name table column database))) (first (clsql:query (format nil "SELECT currval ('~a')" (escaped-database-identifier seq-name)) :flatp t :database database :result-types '(:int))))) (defmethod database-generate-column-definition (class slotdef (database generic-postgresql-database)) (when (member (view-class-slot-db-kind slotdef) '(:base :key)) (let ((cdef (list (sql-expression :attribute (database-identifier slotdef database)) (specified-type slotdef) (view-class-slot-db-type slotdef))) (const (listify (view-class-slot-db-constraints slotdef))) (seq (auto-increment-sequence-name class slotdef database))) (when seq (setf const (remove :auto-increment const)) (unless (member :default const) (let* ((next (format nil "nextval('~a')" (escaped-database-identifier seq)))) (setf const (append const (list :default next)))))) (append cdef const)))) (defmethod database-add-autoincrement-sequence ((self standard-db-class) (database generic-postgresql-database)) (let ((ordered-slots (slots-for-possibly-normalized-class self))) (dolist (slotdef ordered-slots) ;; ensure that referenceed sequences actually exist before referencing them (let ((sequence-name (auto-increment-sequence-name self slotdef database))) (when (and sequence-name (not (sequence-exists-p sequence-name :database database))) (create-sequence sequence-name :database database)))))) (defmethod database-remove-autoincrement-sequence ((table standard-db-class) (database generic-postgresql-database)) (let ((ordered-slots (slots-for-possibly-normalized-class table))) (dolist (slotdef ordered-slots) ;; ensure that referenceed sequences are dropped with the table (let ((sequence-name (auto-increment-sequence-name table slotdef database))) (when sequence-name (drop-sequence sequence-name)))))) (defun postgresql-database-list (connection-spec type) (destructuring-bind (host name &rest other-args) connection-spec (declare (ignore name)) (let ((database (database-connect (list* host "template1" other-args) type))) (unwind-protect (progn (setf (slot-value database 'clsql-sys::state) :open) (mapcar #'car (database-query "select datname from pg_database" database nil nil))) (progn (database-disconnect database) (setf (slot-value database 'clsql-sys::state) :closed)))))) (defmethod database-list (connection-spec (type (eql :postgresql))) (postgresql-database-list connection-spec type)) (defmethod database-list (connection-spec (type (eql :postgresql-socket))) (postgresql-database-list connection-spec type)) #+nil (defmethod database-describe-table ((database generic-postgresql-database) table) ;; MTP: LIST-ATTRIBUTE-TYPES currently executes separate queries for ;; each attribute. It would be more efficient to have a single SQL ;; query return the type data for all attributes. This code is ;; retained as an example of how to do this for PostgreSQL. (database-query (format nil "select a.attname, t.typname from pg_class c, pg_attribute a, pg_type t where c.relname = '~a' and a.attnum > 0 and a.attrelid = c.oid and a.atttypid = t.oid" (sql-escape (string-downcase table))) database :auto nil)) ;;; Prepared statements (defvar *next-prepared-id-num* 0) (defun next-prepared-id () (let ((num (incf *next-prepared-id-num*))) (format nil "CLSQL_PS_~D" num))) (defclass postgresql-stmt () ((database :initarg :database :reader database) (id :initarg :id :reader id) (bindings :initarg :bindings :reader bindings) (field-names :initarg :field-names :accessor stmt-field-names) (result-types :initarg :result-types :reader result-types))) (defun clsql-type->postgresql-type (type) (cond ((in type :int :integer) "INT4") ((in type :short) "INT2") ((in type :bigint) "INT8") ((in type :float :double :number) "NUMERIC") ((and (consp type) (in (car type) :char :varchar)) "VARCHAR") (t (error 'sql-user-error :message (format nil "Unknown clsql type ~A." type))))) (defun prepared-sql-to-postgresql-sql (sql) ;; FIXME: Convert #\? to "$n". Don't convert within strings (declare (simple-string sql)) (with-output-to-string (out) (do ((len (length sql)) (param 0) (in-str nil) (pos 0 (1+ pos))) ((= len pos)) (declare (fixnum len param pos)) (let ((c (schar sql pos))) (declare (character c)) (cond ((or (char= c #\") (char= c #\')) (setq in-str (not in-str)) (write-char c out)) ((and (char= c #\?) (not in-str)) (write-char #\$ out) (write-string (write-to-string (incf param)) out)) (t (write-char c out))))))) (defmethod database-prepare (sql-stmt types (database generic-postgresql-database) result-types field-names) (let ((id (next-prepared-id))) (database-execute-command (format nil "PREPARE ~A (~{~A~^,~}) AS ~A" id (mapcar #'clsql-type->postgresql-type types) (prepared-sql-to-postgresql-sql sql-stmt)) database) (make-instance 'postgresql-stmt :id id :database database :result-types result-types :field-names field-names :bindings (make-list (length types))))) (defmethod database-bind-parameter ((stmt postgresql-stmt) position value) (setf (nth (1- position) (bindings stmt)) value)) (defun binding-to-param (binding) (typecase binding (string (concatenate 'string "'" (sql-escape-quotes binding) "'")) (t binding))) (defmethod database-run-prepared ((stmt postgresql-stmt)) (with-slots (database id bindings field-names result-types) stmt (let ((query (format nil "EXECUTE ~A (~{~A~^,~})" id (mapcar #'binding-to-param bindings)))) (cond ((and field-names (not (consp field-names))) (multiple-value-bind (res names) (database-query query database result-types field-names) (setf field-names names) (values res names))) (field-names (values (nth-value 0 (database-query query database result-types nil)) field-names)) (t (database-query query database result-types field-names)))))) ;;; Capabilities (defmethod db-type-has-fancy-math? ((db-type (eql :postgresql))) t) (defmethod db-type-default-case ((db-type (eql :postgresql))) :lower) (defmethod db-type-has-prepared-stmt? ((db-type (eql :postgresql))) t) (defmethod db-type-has-prepared-stmt? ((db-type (eql :postgresql-socket))) t) (defmethod db-type-has-auto-increment? ((db-type (eql :postgresql))) t) cl-sql-6.4.1/sql/ooddl.lisp0000644000175000017500000002503112064366222014524 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; ;;;; The CLSQL Object Oriented Data Definitional Language (OODDL) ;;;; ;;;; This file is part of CLSQL. ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* (in-package #:clsql-sys) (defclass standard-db-object () ((view-database :initform nil :initarg :view-database :reader view-database :db-kind :virtual)) (:metaclass standard-db-class) (:documentation "Superclass for all CLSQL View Classes.")) (defparameter *default-string-length* 255 "The length of a string which does not have a user-specified length.") (defvar *db-auto-sync* nil "A non-nil value means that creating View Class instances or setting their slots automatically creates/updates the corresponding records in the underlying database.") (defvar *db-deserializing* nil) (defvar *db-initializing* nil) (defmethod slot-value-using-class ((class standard-db-class) instance slot-def) "When a slot is unbound but should contain a join object or a value from a normalized view-class, then retrieve and set those slots, so the value can be returned" (declare (optimize (speed 3))) (unless *db-deserializing* (let* ((slot-name (%svuc-slot-name slot-def)) (slot-object (%svuc-slot-object slot-def class))) (unless (slot-boundp instance slot-name) (let ((*db-deserializing* t)) (cond ((join-slot-p slot-def) (setf (slot-value instance slot-name) (if (view-database instance) (fault-join-slot class instance slot-object) ;; TODO: you could in theory get a join object even if ;; its joined-to object was not in the database nil ))) ((not-direct-normalized-slot-p class slot-def) (if (view-database instance) (update-fault-join-normalized-slot class instance slot-def) (setf (slot-value instance slot-name) nil)))))))) (call-next-method)) (defmethod (setf slot-value-using-class) (new-value (class standard-db-class) instance slot-def) "Handle auto syncing values to the database if *db-auto-sync* is t" (declare (ignore new-value)) (let* ((slot-name (%svuc-slot-name slot-def)) (slot-object (%svuc-slot-object slot-def class)) (slot-kind (view-class-slot-db-kind slot-object))) (prog1 (call-next-method) (when (and *db-auto-sync* (not *db-initializing*) (not *db-deserializing*) (not (eql slot-kind :virtual))) (update-record-from-slot instance slot-name))))) (defmethod initialize-instance ((object standard-db-object) &rest all-keys &key &allow-other-keys) (declare (ignore all-keys)) (let ((*db-initializing* t)) (call-next-method) (when (and *db-auto-sync* (not *db-deserializing*)) (update-records-from-instance object)))) ;; ;; Build the database tables required to store the given view class ;; (defun create-view-from-class (view-class-name &key (database *default-database*) (transactions t)) "Creates a table as defined by the View Class VIEW-CLASS-NAME in DATABASE which defaults to *DEFAULT-DATABASE*." (let ((tclass (find-class view-class-name))) (if tclass (let ((*default-database* database) (pclass (car (class-direct-superclasses tclass)))) (when (and (normalizedp tclass) (not (table-exists-p pclass))) (create-view-from-class (class-name pclass) :database database :transactions transactions)) (%install-class tclass database :transactions transactions)) (error "Class ~s not found." view-class-name))) (values)) (defmethod auto-increment-column-p (slotdef &optional (database clsql-sys:*default-database*)) (declare (ignore database)) (or (member :auto-increment (listify (view-class-slot-db-constraints slotdef))) (slot-value slotdef 'autoincrement-sequence))) (defmethod %install-class ((self standard-db-class) database &key (transactions t)) (let ((schemadef '()) (ordered-slots (slots-for-possibly-normalized-class self))) (dolist (slotdef ordered-slots) (let ((res (database-generate-column-definition self slotdef database))) (when res (push res schemadef)))) (if (not schemadef) (unless (normalizedp self) (error "Class ~s has no :base slots" self)) (progn (database-add-autoincrement-sequence self database) (create-table (sql-expression :table (database-identifier self database)) (nreverse schemadef) :database database :transactions transactions :constraints (database-pkey-constraint self database)) (push self (database-view-classes database))))) t) (defmethod database-pkey-constraint ((class standard-db-class) database) ;; Keylist will always be a list of escaped-indentifier (let ((keylist (mapcar #'(lambda (x) (escaped-database-identifier x database)) (keyslots-for-class class))) (table (escaped (combine-database-identifiers (list class 'PK) database)))) (when keylist (format nil "CONSTRAINT ~A PRIMARY KEY (~{~A~^,~})" table keylist)))) (defmethod database-generate-column-definition (class slotdef database) (declare (ignore class)) (when (key-or-base-slot-p slotdef) (let ((cdef (list (sql-expression :attribute (database-identifier slotdef database)) (specified-type slotdef)))) (setf cdef (append cdef (list (view-class-slot-db-type slotdef)))) (let ((const (view-class-slot-db-constraints slotdef))) (when const (setq cdef (append cdef (listify const))))) cdef))) ;; ;; Drop the tables which store the given view class ;; (defun drop-view-from-class (view-class-name &key (database *default-database*) (owner nil)) "Removes a table defined by the View Class VIEW-CLASS-NAME from DATABASE which defaults to *DEFAULT-DATABASE*." (let ((tclass (find-class view-class-name))) (if tclass (let ((*default-database* database)) (%uninstall-class tclass :owner owner)) (error "Class ~s not found." view-class-name))) (values)) (defun %uninstall-class (self &key (database *default-database*) (owner nil)) (drop-table (sql-expression :table (database-identifier self database)) :if-does-not-exist :ignore :database database :owner owner) (database-remove-autoincrement-sequence self database) (setf (database-view-classes database) (remove self (database-view-classes database)))) ;; ;; List all known view classes ;; (defun list-classes (&key (test #'identity) (root-class (find-class 'standard-db-object)) (database *default-database*)) "Returns a list of all the View Classes which are connected to DATABASE, which defaults to *DEFAULT-DATABASE*, and which descend from the class ROOT-CLASS and which satisfy the function TEST. By default ROOT-CLASS is STANDARD-DB-OBJECT and TEST is IDENTITY." (flet ((find-superclass (class) (member root-class (class-precedence-list class)))) (let ((view-classes (and database (database-view-classes database)))) (when view-classes (remove-if #'(lambda (c) (or (not (funcall test c)) (not (find-superclass c)))) view-classes))))) ;; ;; Define a new view class ;; (defmacro def-view-class (class supers slots &rest cl-options) "Creates a View Class called CLASS whose slots SLOTS can map onto the attributes of a table in a database. If SUPERS is nil then the superclass of CLASS will be STANDARD-DB-OBJECT, otherwise SUPERS is a list of superclasses for CLASS which must include STANDARD-DB-OBJECT or a descendent of this class. The syntax of DEFCLASS is extended through the addition of a class option :base-table which defines the database table onto which the View Class maps and which defaults to CLASS. The DEFCLASS syntax is also extended through additional slot options. The :db-kind slot option specifies the kind of DB mapping which is performed for this slot and defaults to :base which indicates that the slot maps to an ordinary column of the database table. A :db-kind value of :key indicates that this slot is a special kind of :base slot which maps onto a column which is one of the unique keys for the database table, the value :join indicates this slot represents a join onto another View Class which contains View Class objects, and the value :virtual indicates a standard CLOS slot which does not map onto columns of the database table. If a slot is specified with :db-kind :join, the slot option :db-info contains a list which specifies the nature of the join. For slots of :db-kind :base or :key, the :type slot option has a special interpretation such that Lisp types, such as string, integer and float are automatically converted into appropriate SQL types for the column onto which the slot maps. This behaviour may be over-ridden using the :db-type slot option which is a string specifying the vendor-specific database type for this slot's column definition in the database. The :column slot option specifies the name of the SQL column which the slot maps onto, if :db-kind is not :virtual, and defaults to the slot name. The :void-value slot option specifies the value to store if the SQL value is NULL and defaults to NIL. The :db-constraints slot option is a string representing an SQL table constraint expression or a list of such strings." `(progn (defclass ,class ,supers ,slots ,@(if (find :metaclass `,cl-options :key #'car) `,cl-options (cons '(:metaclass clsql-sys::standard-db-class) `,cl-options))) (finalize-inheritance (find-class ',class)) (find-class ',class))) (defun keyslots-for-class (class) (slot-value class 'key-slots)) cl-sql-6.4.1/sql/operations.lisp0000644000175000017500000002173211725170505015612 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; ;;;; Definition of SQL operations used with the symbolic SQL syntax. ;;;; ;;;; This file is part of CLSQL. ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* (in-package #:clsql-sys) ;; Keep a hashtable for mapping symbols to sql generator functions, ;; for use by the bracketed reader syntax. (defvar *sql-op-table* (make-hash-table :test #'equal)) ;; Define an SQL operation type. (defmacro defsql (function definition-keys &body body) `(progn (defun ,function ,@body) (let ((symbol (cadr (member :symbol ',definition-keys)))) (setf (gethash (if symbol (symbol-name-default-case symbol) ',function) *sql-op-table*) ',function)))) ;; SQL operations (defsql sql-query (:symbol "select") (&rest args) (apply #'make-query args)) (defsql sql-any (:symbol "any") (&rest rest) (make-instance 'sql-function-exp :name 'any :args rest)) (defsql sql-some (:symbol "some") (&rest rest) (make-instance 'sql-function-exp :name 'some :args rest)) (defsql sql-all (:symbol "all") (&rest rest) (make-instance 'sql-function-exp :name 'all :args rest)) (defsql sql-not (:symbol "not") (&rest rest) (make-instance 'sql-value-exp :modifier 'not :components rest)) (defsql sql-union (:symbol "union") (&rest rest) (make-instance 'sql-set-exp :operator 'union :sub-expressions rest)) (defsql sql-intersect (:symbol "intersect") (&rest rest) (make-instance 'sql-set-exp :operator 'intersect :sub-expressions rest)) (defsql sql-except (:symbol "except") (&rest rest) (make-instance 'sql-set-exp :operator 'except :sub-expressions rest)) (defsql sql-minus (:symbol "minus") (&rest rest) (make-instance 'sql-set-exp :operator 'minus :sub-expressions rest)) (defsql sql-limit (:symbol "limit") (&rest rest) (make-instance 'sql-query-modifier-exp :modifier 'limit :components rest)) (defsql sql-group-by (:symbol "group-by") (&rest rest) (make-instance 'sql-query-modifier-exp :modifier '|GROUP BY| :components rest)) (defsql sql-order-by (:symbol "order-by") (&rest rest) (make-instance 'sql-query-modifier-exp :modifier '|ORDER BY| :components rest)) (defsql sql-having (:symbol "having") (&rest rest) (make-instance 'sql-query-modifier-exp :modifier 'having :components rest)) (defsql sql-null (:symbol "null") (&optional not-null-thing) (if not-null-thing (make-instance 'sql-relational-exp :operator 'is :sub-expressions (list not-null-thing nil)) (make-instance 'sql-value-exp :components 'null))) (defsql sql-not-null (:symbol "not-null") (&optional not-null-thing) (if not-null-thing (make-instance 'sql-relational-exp :operator 'IS :sub-expressions (list not-null-thing (sql-expression :string "NOT NULL"))) (sql-expression :string "NOT NULL"))) (defsql sql-exists (:symbol "exists") (&rest rest) (make-instance 'sql-function-exp :name 'exists :args rest)) (defsql sql-* (:symbol "*") (&rest rest) (if (zerop (length rest)) (make-instance 'sql-ident :name '*) (make-instance 'sql-relational-exp :operator '* :sub-expressions rest))) (defsql sql-+ (:symbol "+") (&rest rest) (if (cdr rest) (make-instance 'sql-relational-exp :operator '+ :sub-expressions rest) (make-instance 'sql-value-exp :modifier '+ :components rest))) (defsql sql-/ (:symbol "/") (&rest rest) (make-instance 'sql-relational-exp :operator '/ :sub-expressions rest)) (defsql sql-- (:symbol "-") (&rest rest) (if (cdr rest) (make-instance 'sql-relational-exp :operator '- :sub-expressions rest) (make-instance 'sql-value-exp :modifier '- :components rest))) (defsql sql-like (:symbol "like") (&rest rest) (make-instance 'sql-relational-exp :operator 'like :sub-expressions rest)) (defsql sql-uplike (:symbol "uplike") (&rest rest) (make-instance 'sql-upcase-like :sub-expressions rest)) (defsql sql-and (:symbol "and") (&rest rest) (make-instance 'sql-relational-exp :operator 'and :sub-expressions rest)) (defsql sql-or (:symbol "or") (&rest rest) (make-instance 'sql-relational-exp :operator 'or :sub-expressions rest)) (defsql sql-in (:symbol "in") (&rest rest) (make-instance 'sql-relational-exp :operator 'in :sub-expressions rest)) (defsql sql-concat-op (:symbol "concat-op") (&rest rest) (make-instance 'sql-relational-exp :operator '\|\| :sub-expressions rest)) (defsql sql-concat (:symbol "concat") (&rest rest) (make-instance 'sql-function-exp :name 'concat :args rest)) (defsql sql-substr (:symbol "substr") (&rest rest) (if (= (length rest) 3) (make-instance 'sql-function-exp :name 'substr :args rest) (error 'sql-user-error :message "SUBSTR must have 3 arguments."))) (defsql sql-substring (:symbol "substring") (&rest rest) (if (= (length rest) 3) (make-instance 'sql-function-exp :name 'substring :args rest) (error 'sql-user-error :message "SUBSTRING must have 3 arguments."))) (defsql sql-is (:symbol "is") (&rest rest) (make-instance 'sql-relational-exp :operator 'is :sub-expressions rest)) (defsql sql-= (:symbol "=") (&rest rest) (make-instance 'sql-relational-exp :operator '= :sub-expressions rest)) (defsql sql-== (:symbol "==") (&rest rest) (make-instance 'sql-assignment-exp :operator '= :sub-expressions rest)) (defsql sql-< (:symbol "<") (&rest rest) (make-instance 'sql-relational-exp :operator '< :sub-expressions rest)) (defsql sql-> (:symbol ">") (&rest rest) (make-instance 'sql-relational-exp :operator '> :sub-expressions rest)) (defsql sql-<> (:symbol "<>") (&rest rest) (make-instance 'sql-relational-exp :operator '<> :sub-expressions rest)) (defsql sql->= (:symbol ">=") (&rest rest) (make-instance 'sql-relational-exp :operator '>= :sub-expressions rest)) (defsql sql-<= (:symbol "<=") (&rest rest) (make-instance 'sql-relational-exp :operator '<= :sub-expressions rest)) (defsql sql-count (:symbol "count") (&rest rest) (make-instance 'sql-function-exp :name 'count :args rest)) (defsql sql-max (:symbol "max") (&rest rest) (make-instance 'sql-function-exp :name 'max :args rest)) (defsql sql-min (:symbol "min") (&rest rest) (make-instance 'sql-function-exp :name 'min :args rest)) (defsql sql-avg (:symbol "avg") (&rest rest) (make-instance 'sql-function-exp :name 'avg :args rest)) (defsql sql-sum (:symbol "sum") (&rest rest) (make-instance 'sql-function-exp :name 'sum :args rest)) (defsql sql-the (:symbol "the") (&rest rest) (make-instance 'sql-typecast-exp :modifier (first rest) :components (second rest))) (defsql sql-function (:symbol "function") (&rest args) (make-instance 'sql-function-exp :name (make-symbol (car args)) :args (cdr args))) (defsql sql-between (:symbol "between") (&rest rest) (if (= (length rest) 3) (make-instance 'sql-between-exp :name 'between :args rest) (error 'sql-user-error :message "BETWEEN must have 3 arguments."))) (defsql sql-distinct (:symbol "distinct") (&rest rest) (make-instance 'sql-query-modifier-exp :modifier 'distinct :components rest)) (defsql sql-coalesce (:symbol "coalesce") (&rest rest) (make-instance 'sql-function-exp :name 'coalesce :args rest)) (defsql sql-nvl (:symbol "nvl") (&rest rest) (if (= (length rest) 2) (make-instance 'sql-function-exp :name 'coalesce :args rest) (error 'sql-user-error :message "NVL accepts exactly 2 arguments."))) (defsql sql-userenv (:symbol "userenv") (&rest rest) (make-instance 'sql-function-exp :name 'userenv :args rest)) (defsql sql-lower (:symbol "lower") (&rest rest) (if (= (length rest) 1) (make-instance 'sql-function-exp :name 'lower :args rest) (error 'sql-user-error :message "LOWER must have 1 argument."))) (defsql sql-upper (:symbol "upper") (&rest rest) (if (= (length rest) 1) (make-instance 'sql-function-exp :name 'upper :args rest) (error 'sql-user-error :message "UPPER must have 1 argument."))) cl-sql-6.4.1/sql/generics.lisp0000644000175000017500000002050412064366222015222 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; FILE IDENTIFICATION ;;;; ;;;; Name: generics.lisp ;;;; Purpose: Generic function definitions for DB interfaces ;;;; Author: Kevin M. Rosenberg ;;;; Created: Apr 2004 ;;;; ;;;; This file, part of CLSQL, is Copyright (c) 2004-2010 by Kevin M. Rosenberg ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* (in-package #:clsql-sys) ;; FDML (defgeneric choose-database-for-instance (object &optional database) (:documentation "Used by the oodml functions to select which database object to use. Chooses the database associated with the object primarily, falls back to the database provided as an argument or the *DEFAULT-DATABASE*.")) (defgeneric execute-command (expression &key database) (:documentation "Executes the SQL command EXPRESSION, which may be an SQL expression or a string representing any SQL statement apart from a query, on the supplied DATABASE which defaults to *DEFAULT-DATABASE*.")) (defgeneric query (query-expression &key database result-types flatp field-names) (:documentation "Executes the SQL query expression QUERY-EXPRESSION, which may be an SQL expression or a string, on the supplied DATABASE which defaults to *DEFAULT-DATABASE*. RESULT-TYPES is a list of symbols which specifies the lisp type for each field returned by QUERY-EXPRESSION. If RESULT-TYPES is nil all results are returned as strings whereas the default value of :auto means that the lisp types are automatically computed for each field. FIELD-NAMES is t by default which means that the second value returned is a list of strings representing the columns selected by QUERY-EXPRESSION. If FIELD-NAMES is nil, the list of column names is not returned as a second value. FLATP has a default value of nil which means that the results are returned as a list of lists. If FLATP is t and only one result is returned for each record selected by QUERY-EXPRESSION, the results are returned as elements of a list.")) ;; OODML (defgeneric update-record-from-slot (object slot &key database) (:documentation "Updates the value stored in the column represented by the slot, specified by the CLOS slot name SLOT, of View Class instance OBJECT. DATABASE defaults to *DEFAULT-DATABASE* and specifies the database in which the update is made only if OBJECT is not associated with a database. In this case, a record is created in DATABASE and the attribute represented by SLOT is initialised from the value of the supplied slots with other attributes having default values. Furthermore, OBJECT becomes associated with DATABASE.")) (defgeneric update-record-from-slots (object slots &key database) (:documentation "Updates the values stored in the columns represented by the slots, specified by the CLOS slot names SLOTS, of View Class instance OBJECT. DATABASE defaults to *DEFAULT-DATABASE* and specifies the database in which the update is made only if OBJECT is not associated with a database. In this case, a record is created in the appropriate table of DATABASE and the attributes represented by SLOTS are initialised from the values of the supplied slots with other attributes having default values. Furthermore, OBJECT becomes associated with DATABASE.")) (defgeneric update-records-from-instance (object &key database) (:documentation "Using an instance of a View Class, OBJECT, update the table that stores its instance data. DATABASE defaults to *DEFAULT-DATABASE* and specifies the database in which the update is made only if OBJECT is not associated with a database. In this case, a record is created in the appropriate table of DATABASE using values from the slot values of OBJECT, and OBJECT becomes associated with DATABASE.")) (defgeneric delete-instance-records (object &key database) (:documentation "Deletes the records represented by OBJECT in the appropriate table of the database associated with OBJECT. If OBJECT is not yet associated with a database, an error is signalled.")) (defgeneric update-instance-from-records (object &key database) (:documentation "Updates the slot values of the View Class instance OBJECT using the attribute values of the appropriate table of DATABASE which defaults to the database associated with OBJECT or, if OBJECT is not associated with a database, *DEFAULT-DATABASE*. Join slots are updated but instances of the class on which the join is made are not updated.")) (defgeneric update-slot-from-record (object slot &key database) (:documentation "Updates the slot value, specified by the CLOS slot name SLOT, of the View Class instance OBJECT using the attribute values of the appropriate table of DATABASE which defaults to the database associated with OBJECT or, if OBJECT is not associated with a database, *DEFAULT-DATABASE*. Join slots are updated but instances of the class on which the join is made are not updated.")) (defgeneric instance-refreshed (object) (:documentation "Provides a hook which is called within an object oriented call to SELECT with a non-nil value of REFRESH when the View Class instance OBJECT has been updated from the database. A method specialised on STANDARD-DB-OBJECT is provided which has no effects. Methods specialised on particular View Classes can be used to specify any operations that need to be made on View Classes instances which have been updated in calls to SELECT.")) (defgeneric update-slot-with-null (instance slotdef) (:documentation "Called to update a slot when its column has a NULL value. If nulls are allowed for the column, the slot's value will be nil, otherwise its value will be set to the result of calling DATABASE-NULL-VALUE on the type of the slot.")) (defgeneric database-pkey-constraint (class database) ) (defgeneric %install-class (class database &key transactions) ) (defgeneric database-generate-column-definition (class slotdef database) ) (defgeneric update-slot-from-db (instance slotdef val) ) (defgeneric key-value-from-db (slotdef value database) ) (defgeneric get-slot-values-from-view (obj slotdeflist values) ) (defgeneric database-output-sql-as-type (type val database db-type) ) (defgeneric read-sql-value (val type database db-type) ) (defgeneric database-add-autoincrement-sequence (class database) (:method (class database) nil) (:documentation "If a database needs to add a sequence for its autoincrement to work, this is where it should go. Default is that it doesnt so just return nil")) (defgeneric database-remove-autoincrement-sequence (class database) (:method (class database) nil) (:documentation "If a database needs to add a sequence for its autoincrement to work, this is where it should go. Default is that it doesnt so just return nil")) (defgeneric auto-increment-sequence-name (class slotdef database) (:documentation "The sequence name to create for this autoincremnt column on this class if returns nil, there is no associated sequence ")) (defmethod auto-increment-sequence-name :around (class slot database) (when (auto-increment-column-p slot database) (call-next-method))) (defgeneric database-last-auto-increment-id (database table column) ) ;; Generation of SQL strings from lisp expressions (defgeneric output-sql (expr database) (:documentation "Writes an SQL string appropriate for DATABASE and corresponding to the lisp expression EXPR to *SQL-STREAM*. The function SQL-OUTPUT is a top-level call for generating SQL strings which initialises *SQL-STREAM*, calls OUTPUT-SQL and reads the generated SQL string from *SQL-STREAM*.")) (defgeneric database-output-sql (expr database) (:documentation "Returns an SQL string appropriate for DATABASE and corresponding to the lisp expression EXPR. DATABASE-OUTPUT-SQL is called by OUTPUT-SQL when no more specific method exists for EXPR.")) (defgeneric output-sql-hash-key (expr database) (:documentation "Returns a list (or other object suitable for use as the key of an EQUAL hash table) which uniquely identifies the arguments EXPR and DATABASE.")) (defgeneric collect-table-refs (sql) ) (defgeneric database-constraint-statement (constraints database) ) cl-sql-6.4.1/sql/base-classes.lisp0000644000175000017500000000521311335067642015774 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; FILE IDENTIFICATION ;;;; ;;;; Name: base-classes.lisp ;;;; Purpose: Base classes for high-level SQL interface ;;;; Programmers: Kevin M. Rosenberg based on ;;;; original code by Pierre R. Mai ;;;; Date Started: Feb 2002 ;;;; ;;;; This file, part of CLSQL, is Copyright (c) 2002-2010 by Kevin M. Rosenberg ;;;; and Copyright (c) 1999-2001 by Pierre R. Mai ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* (in-package #:clsql-sys) (defclass database () ((name :initform nil :initarg :name :reader database-name) (connection-spec :initform nil :initarg :connection-spec :reader connection-spec :documentation "Required to use connection pool.") (database-type :initarg :database-type :initform :unknown :reader database-type) (encoding :initarg :encoding :initform nil :documentation "External format character encoding.") (state :initform :closed :reader database-state) (autocommit :initform t :accessor database-autocommit) (command-recording-stream :accessor command-recording-stream :initform nil) (result-recording-stream :accessor result-recording-stream :initform nil) (record-caches :accessor record-caches :initform nil) (view-classes :accessor database-view-classes :initform nil) (transaction-level :initform 0 :accessor transaction-level) (transaction :initform nil :accessor transaction) (conn-pool :initform nil :initarg :conn-pool :accessor conn-pool) (attribute-cache :initform (make-hash-table :size 100 :test 'equal) :accessor attribute-cache :documentation "Internal cache of table attributes. It is keyed by table-name. Values are a list of ACTION specified for table and any cached value of list-attributes-types.")) (:documentation "This class is the supertype of all databases handled by CLSQL.")) (defmethod print-object ((object database) stream) (print-unreadable-object (object stream :type t :identity t) (format stream "~A ~A" (if (slot-boundp object 'name) (database-name object) "") (database-state object))) object) (setf (documentation 'database-name 'function) "Returns the name of a database.") cl-sql-6.4.1/sql/database.lisp0000644000175000017500000003657211577723152015212 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; ;;;; Base database functions ;;;; ;;;; This file is part of CLSQL. ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* (in-package #:clsql-sys) (defvar *connect-if-exists* :error "Default value for the if-exists keyword argument in calls to CONNECT. Meaningful values are :new, :warn-new, :error, :warn-old and :old.") ;;TODO: this variable appears to be global, not thread specific and is ;; not protected when modifying the list. (defvar *connected-databases* nil "List of active database objects.") (defun connected-databases () "Returns the list of active database objects." *connected-databases*) (defvar *default-database* nil "Specifies the default database to be used.") (defun is-database-open (database) (eql (database-state database) :open)) (defun find-database (database &key (errorp t) (db-type nil)) "Returns the connected databases of type DB-TYPE whose names match the string DATABASE. If DATABASE is a database object, it is returned. If DB-TYPE is nil all databases matching the string DATABASE are considered. If no matching databases are found and ERRORP is nil then nil is returned. If ERRORP is nil and one or more matching databases are found, then the most recently connected database is returned as a first value and the number of matching databases is returned as a second value. If no, or more than one, matching databases are found and ERRORP is true, an error is signalled." (etypecase database (database (values database 1)) (string (let* ((matches (remove-if #'(lambda (db) (not (and (string= (database-name db) database) (if db-type (equal (database-type db) db-type) t)))) (connected-databases))) (count (length matches))) (if (or (not errorp) (= count 1)) (values (car matches) count) (cerror "Return nil." 'sql-database-error :message (format nil "There exists ~A database called ~A." (if (zerop count) "no" "more than one") database))))) (null (error "A database must be specified rather than NIL.")))) (defun connect (connection-spec &key (if-exists *connect-if-exists*) (make-default t) (pool nil) (database-type *default-database-type*) (encoding nil)) "Connects to a database of the supplied DATABASE-TYPE which defaults to *DEFAULT-DATABASE-TYPE*, using the type-specific connection specification CONNECTION-SPEC. The value of IF-EXISTS, which defaults to *CONNECT-IF-EXISTS*, determines what happens if a connection to the database specified by CONNECTION-SPEC is already established. A value of :new means create a new connection. A value of :warn-new means warn the user and create a new connect. A value of :warn-old means warn the user and use the old connection. A value of :error means fail, notifying the user. A value of :old means return the old connection. MAKE-DEFAULT is t by default which means that *DEFAULT-DATABASE* is set to the new connection, otherwise *DEFAULT-DATABASE* is not changed. If POOL is t the connection will be taken from the general pool, if POOL is a CONN-POOL object the connection will be taken from this pool." (unless database-type (error 'sql-database-error :message "Must specify a database-type.")) (when (stringp connection-spec) (setq connection-spec (string-to-list-connection-spec connection-spec))) (unless (member database-type *loaded-database-types*) (asdf:operate 'asdf:load-op (ensure-keyword (concatenate 'string (symbol-name '#:clsql-) (symbol-name database-type))) :verbose nil)) (if pool (let ((conn (acquire-from-pool connection-spec database-type pool encoding))) (when make-default (setq *default-database* conn)) conn) (let* ((db-name (database-name-from-spec connection-spec database-type)) (old-db (unless (eq if-exists :new) (find-database db-name :db-type database-type :errorp nil))) (result nil)) (if old-db (ecase if-exists (:warn-new (setq result (database-connect connection-spec database-type)) (warn 'sql-warning :message (format nil "Created new connection ~A to database ~A~%, although there is an existing connection (~A)." result (database-name result) old-db))) (:error (restart-case (error 'sql-connection-error :message (format nil "There is an existing connection ~A to database ~A." old-db (database-name old-db))) (create-new () :report "Create a new connection." (setq result (database-connect connection-spec database-type))) (use-old () :report "Use the existing connection." (setq result old-db)))) (:warn-old (setq result old-db) (warn 'sql-warning :message (format nil "Using existing connection ~A to database ~A." old-db (database-name old-db)))) (:old (setq result old-db))) (setq result (database-connect connection-spec database-type))) (when result (setf (slot-value result 'state) :open) (pushnew result *connected-databases*) (when make-default (setq *default-database* result)) (setf (encoding result) encoding) result)))) (defun disconnect (&key (database *default-database*) (error nil)) "Closes the connection to DATABASE and resets *DEFAULT-DATABASE* if that database was disconnected. If DATABASE is a database instance, this object is closed. If DATABASE is a string, then a connected database whose name matches DATABASE is sought in the list of connected databases. If no matching database is found and ERROR and DATABASE are both non-nil an error is signaled, otherwise nil is returned. If the database is from a pool it will be released to this pool." (let ((database (find-database database :errorp (and database error)))) (when database (if (conn-pool database) (with-process-lock ((conn-pool-lock (conn-pool database)) "Delete from pool") (when (release-to-pool database) (setf *connected-databases* (delete database *connected-databases*)) (when (eq database *default-database*) (setf *default-database* (car *connected-databases*))) t)) (when (database-disconnect database) ;;TODO: RACE COND: 2 threads disconnecting could stomp on *connected-databases* (setf *connected-databases* (delete database *connected-databases*)) (when (eq database *default-database*) (setf *default-database* (car *connected-databases*))) (setf (slot-value database 'state) :closed) t))))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defmacro check-connection-spec (connection-spec database-type template) "Check the connection specification against the provided template, and signal an sql-user-error if they don't match. This function is called by database backends." `(handler-case (destructuring-bind ,template ,connection-spec (declare (ignore ,@(remove '&optional template))) t) (error () (error 'sql-user-error :message (format nil "The connection specification ~A~%is invalid for database type ~A.~%The connection specification must conform to ~A" ,connection-spec ,database-type (quote ,template)))))) (defun reconnect (&key (database *default-database*) (error nil) (force t)) "Reconnects DATABASE which defaults to *DEFAULT-DATABASE* to the underlying database management system. On success, t is returned and the variable *DEFAULT-DATABASE* is set to the newly reconnected database. If DATABASE is a database instance, this object is closed. If DATABASE is a string, then a connected database whose name matches DATABASE is sought in the list of connected databases. If no matching database is found and ERROR and DATABASE are both non-nil an error is signaled, otherwise nil is returned. When the current database connection cannot be closed, if FORCE is non-nil, as it is by default, the connection is closed and errors are suppressed. If force is nil and the database connection cannot be closed, an error is signalled." (let ((db (etypecase database (database database) ((or string list) (let ((db (find-database database :errorp nil))) (when (null db) (if (and database error) (error 'sql-connection-error :message (format nil "Unable to find database with connection-spec ~A." database)) (return-from reconnect nil))) db))))) (when (is-database-open db) (if force (ignore-errors (disconnect :database db)) (disconnect :database db :error nil))) (connect (connection-spec db) :encoding (encoding db)))) (defun status (&optional full) "Prints information about the currently connected databases to *STANDARD-OUTPUT*. The argument FULL is nil by default and a value of t means that more detailed information about each database is printed." (flet ((get-data () (let ((data '())) (dolist (db (connected-databases) data) (push (append (list (if (equal db *default-database*) "*" "") (database-name db) (string-downcase (string (database-type db))) (cond ((and (command-recording-stream db) (result-recording-stream db)) "Both") ((command-recording-stream db) "Commands") ((result-recording-stream db) "Results") (t "nil"))) (when full (list (if (conn-pool db) "t" "nil") (format nil "~A" (length (database-list-tables db))) (format nil "~A" (length (database-list-views db)))))) data)))) (compute-sizes (data) (mapcar #'(lambda (x) (apply #'max (mapcar #'length x))) (apply #'mapcar (cons #'list data)))) (print-separator (size) (format t "~&~A" (make-string size :initial-element #\-)))) (format t "~&CLSQL STATUS: ~A~%" (iso-timestring (get-time))) (let ((data (get-data))) (when data (let* ((titles (if full (list "" "DATABASE" "TYPE" "RECORDING" "POOLED" "TABLES" "VIEWS") (list "" "DATABASE" "TYPE" "RECORDING"))) (sizes (compute-sizes (cons titles data))) (total-size (+ (apply #'+ sizes) (* 2 (1- (length titles))))) (control-string (format nil "~~&~~{~{~~~AA ~}~~}" sizes))) (print-separator total-size) (format t control-string titles) (print-separator total-size) (dolist (d data) (format t control-string d)) (print-separator total-size)))) (values))) (defun create-database (connection-spec &key (database-type *default-database-type*)) "This function creates a database in the database system specified by DATABASE-TYPE." (when (stringp connection-spec) (setq connection-spec (string-to-list-connection-spec connection-spec))) (database-create connection-spec database-type)) (defun probe-database (connection-spec &key (database-type *default-database-type*)) "This function tests for the existence of a database in the database system specified by DATABASE-TYPE." (when (stringp connection-spec) (setq connection-spec (string-to-list-connection-spec connection-spec))) (database-probe connection-spec database-type)) (defun destroy-database (connection-spec &key (database-type *default-database-type*)) "This function destroys a database in the database system specified by DATABASE-TYPE." (when (stringp connection-spec) (setq connection-spec (string-to-list-connection-spec connection-spec))) (database-destroy connection-spec database-type)) (defun list-databases (connection-spec &key (database-type *default-database-type*)) "This function returns a list of databases existing in the database system specified by DATABASE-TYPE." (when (stringp connection-spec) (setq connection-spec (string-to-list-connection-spec connection-spec))) (database-list connection-spec database-type)) (defun encoding (db) (when (typep db 'database) (slot-value db 'encoding))) (defun (setf encoding) (encoding db) (when (typep db 'database) (setf (slot-value db 'encoding) encoding) (when (eql (slot-value db 'state) :open) (case (database-type db) ;; FIXME: If database object is open then ;; send command to SQL engine specifying the character ;; encoding for the database (:mysql ) ((:postgresql :postgresql-socket) ))))) (defmacro with-database ((db-var connection-spec &key make-default pool (if-exists *connect-if-exists*) (database-type *default-database-type*) (encoding nil)) &body body) "Evaluate the body in an environment, where DB-VAR is bound to the database connection given by CONNECTION-SPEC and CONNECT-ARGS. The connection is automatically closed or released to the pool on exit from the body. MAKE-DEFAULT has a default value of NIL." `(let ((,db-var (connect ,connection-spec :database-type ,database-type :if-exists ,if-exists :pool ,pool :make-default ,make-default :encoding ,encoding))) (unwind-protect (let ((,db-var ,db-var)) (progn ,@body)) (disconnect :database ,db-var)))) (defmacro with-default-database ((database) &rest body) "Perform BODY with DATABASE bound as *default-database*." `(progv '(*default-database*) (list ,database) ,@body)) cl-sql-6.4.1/sql/ansi-loop.lisp0000644000175000017500000031467310667176647015362 0ustar kevinkevin;;; -*- Mode: LISP; Package: ANSI-LOOP; Syntax: Common-lisp; Base: 10; Lowercase:T -*- ;;; ;;; This file is included with CLSQL to be used by CLISP which does not ;;; have an extensible LOOP macro. It was copied from the CMUCL 19c source. ;;; Minor porting changes have been made Copyright (c) 2006 Kevin M. Rosenberg ;;; ;;;> ;;;> Portions of LOOP are Copyright (c) 1986 by the Massachusetts Institute of Technology. ;;;> All Rights Reserved. ;;;> ;;;> Permission to use, copy, modify and distribute this software and its ;;;> documentation for any purpose and without fee is hereby granted, ;;;> provided that the M.I.T. copyright notice appear in all copies and that ;;;> both that copyright notice and this permission notice appear in ;;;> supporting documentation. The names "M.I.T." and "Massachusetts ;;;> Institute of Technology" may not be used in advertising or publicity ;;;> pertaining to distribution of the software without specific, written ;;;> prior permission. Notice must be given in supporting documentation that ;;;> copying distribution is by permission of M.I.T. M.I.T. makes no ;;;> representations about the suitability of this software for any purpose. ;;;> It is provided "as is" without express or implied warranty. ;;;> ;;;> Massachusetts Institute of Technology ;;;> 77 Massachusetts Avenue ;;;> Cambridge, Massachusetts 02139 ;;;> United States of America ;;;> +1-617-253-1000 ;;;> ;;;> Portions of LOOP are Copyright (c) 1989, 1990, 1991, 1992 by Symbolics, Inc. ;;;> All Rights Reserved. ;;;> ;;;> Permission to use, copy, modify and distribute this software and its ;;;> documentation for any purpose and without fee is hereby granted, ;;;> provided that the Symbolics copyright notice appear in all copies and ;;;> that both that copyright notice and this permission notice appear in ;;;> supporting documentation. The name "Symbolics" may not be used in ;;;> advertising or publicity pertaining to distribution of the software ;;;> without specific, written prior permission. Notice must be given in ;;;> supporting documentation that copying distribution is by permission of ;;;> Symbolics. Symbolics makes no representations about the suitability of ;;;> this software for any purpose. It is provided "as is" without express ;;;> or implied warranty. ;;;> ;;;> Symbolics, CLOE Runtime, and Minima are trademarks, and CLOE, Genera, ;;;> and Zetalisp are registered trademarks of Symbolics, Inc. ;;;> ;;;> Symbolics, Inc. ;;;> 8 New England Executive Park, East ;;;> Burlington, Massachusetts 01803 ;;;> United States of America ;;;> +1-617-221-1000 ;; $aclHeader: loop.cl,v 1.5 91/12/04 01:13:48 cox acl4_1 $ #+cmu (ext:file-comment "$Header: /project/cmucl/cvsroot/src/code/loop.lisp,v 1.27 2004/10/21 02:31:08 rtoy Exp $") ;;;; LOOP Iteration Macro #+clisp (eval-when (:compile-toplevel :load-toplevel :execute) (setf (ext:package-lock (find-package "COMMON-LISP")) nil)) (defpackage ansi-loop (:use :common-lisp) (:shadowing-import-from "COMMON-LISP" "LOOP" "LOOP-FINISH")) (in-package ansi-loop) ;;; Technology. ;;; ;;; The LOOP iteration macro is one of a number of pieces of code ;;; originally developed at MIT and licensed as set out above. This ;;; version of LOOP, which is almost entirely rewritten both as a ;;; clean-up and to conform with the ANSI Lisp LOOP standard, started ;;; life as MIT LOOP version 829 (which was a part of NIL, possibly ;;; never released). ;;; ;;; A "light revision" was performed by Glenn Burke while at Palladian ;;; Software in April 1986, to make the code run in Common Lisp. This ;;; revision was informally distributed to a number of people, and was ;;; sort of the "MIT" version of LOOP for running in Common Lisp. ;;; ;;; A later more drastic revision was performed at Palladian perhaps a ;;; year later. This version was more thoroughly Common Lisp in ;;; style, with a few miscellaneous internal improvements and ;;; extensions. Glenn Burke lost track of this source, apparently ;;; never having moved it to the MIT distribution point; and does not ;;; remember if it was ever distributed. ;;; ;;; This revision for the ANSI standard is based on the code of Glenn ;;; Burke's April 1986 version, with almost everything redesigned ;;; and/or rewritten. ;;; The design of this LOOP is intended to permit, using mostly the same ;;; kernel of code, up to three different "loop" macros: ;;; ;;; (1) The unextended, unextensible ANSI standard LOOP; ;;; ;;; (2) A clean "superset" extension of the ANSI LOOP which provides ;;; functionality similar to that of the old LOOP, but "in the style of" ;;; the ANSI LOOP. For instance, user-definable iteration paths, with a ;;; somewhat cleaned-up interface. ;;; ;;; (3) Extensions provided in another file which can make this LOOP ;;; kernel behave largely compatibly with the Genera-vintage LOOP macro, ;;; with only a small addition of code (instead of two whole, separate, ;;; LOOP macros). ;;; ;;; Each of the above three LOOP variations can coexist in the same LISP ;;; environment. ;;; ;;;; Miscellaneous Environment Things ;;;@@@@The LOOP-Prefer-POP feature makes LOOP generate code which "prefers" to use POP or ;;; its obvious expansion (prog1 (car x) (setq x (cdr x))). Usually this involves ;;; shifting fenceposts in an iteration or series of carcdr operations. This is ;;; primarily recognized in the list iterators (FOR .. {IN,ON}), and LOOP's ;;; destructuring setq code. (eval-when (compile load eval) #+(or Genera Minima) (pushnew :LOOP-Prefer-POP *features*) ) ;;; The uses of this macro are retained in the CL version of loop, in ;;; case they are needed in a particular implementation. Originally ;;; dating from the use of the Zetalisp COPYLIST* function, this is used ;;; in situations where, were cdr-coding in use, having cdr-NIL at the ;;; end of the list might be suboptimal because the end of the list will ;;; probably be RPLACDed and so cdr-normal should be used instead. (defmacro loop-copylist* (l) #+Genera `(lisp:copy-list ,l nil t) ; arglist = (list &optional area force-dotted) ;;@@@@Explorer?? #-Genera `(copy-list ,l) ) (defvar *loop-gentemp* t) (defun loop-gentemp (&optional (pref 'loopvar-)) (if *loop-gentemp* (gensym (string pref)) (gensym))) (eval-when (:compile-toplevel :load-toplevel :execute) (defvar *loop-real-data-type* 'real)) (defun loop-optimization-quantities (env) ;;@@@@ The ANSI conditionalization here is for those lisps that implement ;; DECLARATION-INFORMATION (from cleanup SYNTACTIC-ENVIRONMENT-ACCESS). ;; It is really commentary on how this code could be written. I don't ;; actually expect there to be an ANSI #+-conditional -- it should be ;; replaced with the appropriate conditional name for your ;; implementation/dialect. (declare #-ANSI (ignore env) #+Genera (values speed space safety compilation-speed debug)) #+ANSI (let ((stuff (declaration-information 'optimize env))) (values (or (cdr (assoc 'speed stuff)) 1) (or (cdr (assoc 'space stuff)) 1) (or (cdr (assoc 'safety stuff)) 1) (or (cdr (assoc 'compilation-speed stuff)) 1) (or (cdr (assoc 'debug stuff)) 1))) #+CLOE-Runtime (values compiler::time compiler::space compiler::safety compiler::compilation-speed 1) #-(or ANSI CLOE-Runtime) (values 1 1 1 1 1)) ;;;@@@@ The following form takes a list of variables and a form which presumably ;;; references those variables, and wraps it somehow so that the compiler does not ;;; consider those variables have been referenced. The intent of this is that ;;; iteration variables can be flagged as unused by the compiler, e.g. I in ;;; (loop for i from 1 to 10 do (print t)), since we will tell it when a usage ;;; of it is "invisible" or "not to be considered". ;;;We implicitly assume that a setq does not count as a reference. That is, the ;;; kind of form generated for the above loop construct to step I, simplified, is ;;; `(SETQ I ,(HIDE-VARIABLE-REFERENCES '(I) '(1+ I))). (defun hide-variable-references (variable-list form) (declare #-Genera (ignore variable-list)) #+Genera (if variable-list `(compiler:invisible-references ,variable-list ,form) form) #-Genera form) ;;;@@@@ The following function takes a flag, a variable, and a form which presumably ;;; references that variable, and wraps it somehow so that the compiler does not ;;; consider that variable to have been referenced. The intent of this is that ;;; iteration variables can be flagged as unused by the compiler, e.g. I in ;;; (loop for i from 1 to 10 do (print t)), since we will tell it when a usage ;;; of it is "invisible" or "not to be considered". ;;;We implicitly assume that a setq does not count as a reference. That is, the ;;; kind of form generated for the above loop construct to step I, simplified, is ;;; `(SETQ I ,(HIDE-VARIABLE-REFERENCES T 'I '(1+ I))). ;;;Certain cases require that the "invisibility" of the reference be conditional upon ;;; something. This occurs in cases of "named" variables (the USING clause). For instance, ;;; we want IDX in (LOOP FOR E BEING THE VECTOR-ELEMENTS OF V USING (INDEX IDX) ...) ;;; to be "invisible" when it is stepped, so that the user gets informed if IDX is ;;; not referenced. However, if no USING clause is present, we definitely do not ;;; want to be informed that some random gensym is not used. ;;;It is easier for the caller to do this conditionally by passing a flag (which ;;; happens to be the second value of NAMED-VARIABLE, q.v.) to this function than ;;; for all callers to contain the conditional invisibility construction. (defun hide-variable-reference (really-hide variable form) (declare #-Genera (ignore really-hide variable)) #+Genera (if (and really-hide variable (atom variable)) ;Punt on destructuring patterns `(compiler:invisible-references (,variable) ,form) form) #-Genera form) ;;;; List Collection Macrology (defmacro with-loop-list-collection-head ((head-var tail-var &optional user-head-var) &body body) ;;@@@@ TI? Exploder? #+LISPM (let ((head-place (or user-head-var head-var))) `(let* ((,head-place nil) (,tail-var ,(hide-variable-reference user-head-var user-head-var `(progn #+Genera (scl:locf ,head-place) #-Genera (system:variable-location ,head-place))))) ,@body)) #-LISPM (let ((l (and user-head-var (list (list user-head-var nil))))) #+CLOE `(sys::with-stack-list* (,head-var nil nil) (let ((,tail-var ,head-var) ,@l) ,@body)) #-CLOE `(let* ((,head-var (list nil)) (,tail-var ,head-var) ,@l) ,@body))) (defmacro loop-collect-rplacd (&environment env (head-var tail-var &optional user-head-var) form) (declare #+LISPM (ignore head-var user-head-var) ;use locatives, unconditionally update through the tail. ) (setq form (macroexpand form env)) (flet ((cdr-wrap (form n) (declare (fixnum n)) (do () ((<= n 4) (setq form `(,(case n (1 'cdr) (2 'cddr) (3 'cdddr) (4 'cddddr)) ,form))) (setq form `(cddddr ,form) n (- n 4))))) (let ((tail-form form) (ncdrs nil)) ;;Determine if the form being constructed is a list of known length. (when (consp form) (cond ((eq (car form) 'list) (setq ncdrs (1- (length (cdr form)))) ;;@@@@ Because the last element is going to be RPLACDed, ;; we don't want the cdr-coded implementations to use ;; cdr-nil at the end (which would just force copying ;; the whole list again). #+LISPM (setq tail-form `(list* ,@(cdr form) nil))) ((member (car form) '(list* cons)) (when (and (cddr form) (member (car (last form)) '(nil 'nil))) (setq ncdrs (- (length (cdr form)) 2)))))) (let ((answer (cond ((null ncdrs) `(when (setf (cdr ,tail-var) ,tail-form) (setq ,tail-var (last (cdr ,tail-var))))) ((< ncdrs 0) (return-from loop-collect-rplacd nil)) ((= ncdrs 0) ;;@@@@ Here we have a choice of two idioms: ;; (rplacd tail (setq tail tail-form)) ;; (setq tail (setf (cdr tail) tail-form)). ;;Genera and most others I have seen do better with the former. `(rplacd ,tail-var (setq ,tail-var ,tail-form))) (t `(setq ,tail-var ,(cdr-wrap `(setf (cdr ,tail-var) ,tail-form) ncdrs)))))) ;;If not using locatives or something similar to update the user's ;; head variable, we've got to set it... It's harmless to repeatedly set it ;; unconditionally, and probably faster than checking. #-LISPM (when user-head-var (setq answer `(progn ,answer (setq ,user-head-var (cdr ,head-var))))) answer)))) (defmacro loop-collect-answer (head-var &optional user-head-var) (or user-head-var (progn ;;If we use locatives to get tail-updating to update the head var, ;; then the head var itself contains the answer. Otherwise we ;; have to cdr it. #+LISPM head-var #-LISPM `(cdr ,head-var)))) ;;;; Maximization Technology #| The basic idea of all this minimax randomness here is that we have to have constructed all uses of maximize and minimize to a particular "destination" before we can decide how to code them. The goal is to not have to have any kinds of flags, by knowing both that (1) the type is something which we can provide an initial minimum or maximum value for and (2) know that a MAXIMIZE and MINIMIZE are not being combined. SO, we have a datastructure which we annotate with all sorts of things, incrementally updating it as we generate loop body code, and then use a wrapper and internal macros to do the coding when the loop has been constructed. |# (defstruct (loop-minimax (:constructor make-loop-minimax-internal) (:copier nil) (:predicate nil)) answer-variable type temp-variable flag-variable operations infinity-data) (defvar *loop-minimax-type-infinities-alist* ;;@@@@ This is the sort of value this should take on for a Lisp that has ;; "eminently usable" infinities. n.b. there are neither constants nor ;; printed representations for infinities defined by CL. ;;@@@@ This grotesque read-from-string below is to help implementations ;; which croak on the infinity character when it appears in a token, even ;; conditionalized out. #+Genera '#.(read-from-string "((fixnum most-positive-fixnum most-negative-fixnum) (short-float +1s -1s) (single-float +1f -1f) (double-float +1d -1d) (long-float +1l -1l))") ;;This is how the alist should look for a lisp that has no infinities. In ;; that case, MOST-POSITIVE-x-FLOAT really IS the most positive. #+(or CLOE-Runtime Minima) '((fixnum most-positive-fixnum most-negative-fixnum) (short-float most-positive-short-float most-negative-short-float) (single-float most-positive-single-float most-negative-single-float) (double-float most-positive-double-float most-negative-double-float) (long-float most-positive-long-float most-negative-long-float)) ;; CMUCL has infinities so let's use them. #+CMU '((fixnum most-positive-fixnum most-negative-fixnum) (short-float ext:single-float-positive-infinity ext:single-float-negative-infinity) (single-float ext:single-float-positive-infinity ext:single-float-negative-infinity) (double-float ext:double-float-positive-infinity ext:double-float-negative-infinity) (long-float ext:long-float-positive-infinity ext:long-float-negative-infinity)) ;; If we don't know, then we cannot provide "infinite" initial values for any of the ;; types but FIXNUM: #-(or Genera CLOE-Runtime Minima CMU) '((fixnum most-positive-fixnum most-negative-fixnum)) ) (defun make-loop-minimax (answer-variable type) (let ((infinity-data (cdr (assoc type *loop-minimax-type-infinities-alist* :test #'subtypep)))) (make-loop-minimax-internal :answer-variable answer-variable :type type :temp-variable (loop-gentemp 'loop-maxmin-temp-) :flag-variable (and (not infinity-data) (loop-gentemp 'loop-maxmin-flag-)) :operations nil :infinity-data infinity-data))) (defun loop-note-minimax-operation (operation minimax) (pushnew (the symbol operation) (loop-minimax-operations minimax)) (when (and (cdr (loop-minimax-operations minimax)) (not (loop-minimax-flag-variable minimax))) (setf (loop-minimax-flag-variable minimax) (loop-gentemp 'loop-maxmin-flag-))) operation) (defmacro with-minimax-value (lm &body body) (let ((init (loop-typed-init (loop-minimax-type lm))) (which (car (loop-minimax-operations lm))) (infinity-data (loop-minimax-infinity-data lm)) (answer-var (loop-minimax-answer-variable lm)) (temp-var (loop-minimax-temp-variable lm)) (flag-var (loop-minimax-flag-variable lm)) (type (loop-minimax-type lm))) (if flag-var `(let ((,answer-var ,init) (,temp-var ,init) (,flag-var nil)) (declare (type ,type ,answer-var ,temp-var)) ,@body) `(let ((,answer-var ,(if (eq which 'min) (first infinity-data) (second infinity-data))) (,temp-var ,init)) (declare (type ,type ,answer-var ,temp-var)) ,@body)))) (defmacro loop-accumulate-minimax-value (lm operation form) (let* ((answer-var (loop-minimax-answer-variable lm)) (temp-var (loop-minimax-temp-variable lm)) (flag-var (loop-minimax-flag-variable lm)) (test (hide-variable-reference t (loop-minimax-answer-variable lm) `(,(ecase operation (min '<) (max '>)) ,temp-var ,answer-var)))) `(progn (setq ,temp-var ,form) (when ,(if flag-var `(or (not ,flag-var) ,test) test) (setq ,@(and flag-var `(,flag-var t)) ,answer-var ,temp-var))))) ;;;; Loop Keyword Tables #| LOOP keyword tables are hash tables string keys and a test of EQUAL. The actual descriptive/dispatch structure used by LOOP is called a "loop universe" contains a few tables and parameterizations. The basic idea is that we can provide a non-extensible ANSI-compatible loop environment, an extensible ANSI-superset loop environment, and (for such environments as CLOE) one which is "sufficiently close" to the old Genera-vintage LOOP for use by old user programs without requiring all of the old LOOP code to be loaded. |# ;;;; Token Hackery ;;;Compare two "tokens". The first is the frob out of *LOOP-SOURCE-CODE*, ;;; the second a symbol to check against. (defun loop-tequal (x1 x2) (and (symbolp x1) (string= x1 x2))) (defun loop-tassoc (kwd alist) (and (symbolp kwd) (assoc kwd alist :test #'string=))) (defun loop-tmember (kwd list) (and (symbolp kwd) (member kwd list :test #'string=))) (defun loop-lookup-keyword (loop-token table) (and (symbolp loop-token) (values (gethash (symbol-name loop-token) table)))) (defmacro loop-store-table-data (symbol table datum) `(setf (gethash (symbol-name ,symbol) ,table) ,datum)) (defstruct (loop-universe (:print-function print-loop-universe) (:copier nil) (:predicate nil)) keywords ;hash table, value = (fn-name . extra-data). iteration-keywords ;hash table, value = (fn-name . extra-data). for-keywords ;hash table, value = (fn-name . extra-data). path-keywords ;hash table, value = (fn-name . extra-data). type-symbols ;hash table of type SYMBOLS, test EQ, value = CL type specifier. type-keywords ;hash table of type STRINGS, test EQUAL, value = CL type spec. ansi ;NIL, T, or :EXTENDED. implicit-for-required ;see loop-hack-iteration ) (eval-when (:compile-toplevel :load-toplevel :execute) (defun print-loop-universe (u stream level) (declare (ignore level)) (let ((str (case (loop-universe-ansi u) ((nil) "Non-ANSI") ((t) "ANSI") (:extended "Extended-ANSI") (t (loop-universe-ansi u))))) ;;Cloe could be done with the above except for bootstrap lossage... #+CLOE (format stream "#<~S ~A ~X>" (type-of u) str (sys::address-of u)) (print-unreadable-object (u stream :type t :identity t) (princ str stream)) ))) ;;;This is the "current" loop context in use when we are expanding a ;;;loop. It gets bound on each invocation of LOOP. (defvar *loop-universe*) (eval-when (:compile-toplevel :load-toplevel :execute) (defun make-standard-loop-universe (&key keywords for-keywords iteration-keywords path-keywords type-keywords type-symbols ansi) #-(and CLOE Source-Bootstrap) (check-type ansi (member nil t :extended)) (flet ((maketable (entries) (let* ((size (length entries)) (ht (make-hash-table :size (if (< size 10) 10 size) :test #'equal))) (dolist (x entries) (setf (gethash (symbol-name (car x)) ht) (cadr x))) ht))) (make-loop-universe :keywords (maketable keywords) :for-keywords (maketable for-keywords) :iteration-keywords (maketable iteration-keywords) :path-keywords (maketable path-keywords) :ansi ansi :implicit-for-required (not (null ansi)) :type-keywords (maketable type-keywords) :type-symbols (let* ((size (length type-symbols)) (ht (make-hash-table :size (if (< size 10) 10 size) :test #'eq))) (dolist (x type-symbols) (if (atom x) (setf (gethash x ht) x) (setf (gethash (car x) ht) (cadr x)))) ht))))) ;;;; Setq Hackery (defvar *loop-destructuring-hooks* nil "If not NIL, this must be a list of two things: a LET-like macro, and a SETQ-like macro, which perform LOOP-style destructuring.") (defun loop-make-psetq (frobs) (and frobs (loop-make-desetq (list (car frobs) (if (null (cddr frobs)) (cadr frobs) `(prog1 ,(cadr frobs) ,(loop-make-psetq (cddr frobs)))))))) (defun loop-make-desetq (var-val-pairs) (if (null var-val-pairs) nil (cons (if *loop-destructuring-hooks* (cadr *loop-destructuring-hooks*) 'loop-really-desetq) var-val-pairs))) (defvar *loop-desetq-temporary* (make-symbol "LOOP-DESETQ-TEMP")) (defmacro loop-really-desetq (&environment env &rest var-val-pairs) (labels ((find-non-null (var) ;; see if there's any non-null thing here ;; recurse if the list element is itself a list (do ((tail var)) ((not (consp tail)) tail) (when (find-non-null (pop tail)) (return t)))) (loop-desetq-internal (var val &optional temp) ;; returns a list of actions to be performed (typecase var (null (when (consp val) ;; don't lose possible side-effects (if (eq (car val) 'prog1) ;; these can come from psetq or desetq below. ;; throw away the value, keep the side-effects. ;;Special case is for handling an expanded POP. (mapcan #'(lambda (x) (and (consp x) (or (not (eq (car x) 'car)) (not (symbolp (cadr x))) (not (symbolp (setq x (macroexpand x env))))) (cons x nil))) (cdr val)) `(,val)))) (cons (let* ((car (car var)) (cdr (cdr var)) (car-non-null (find-non-null car)) (cdr-non-null (find-non-null cdr))) (when (or car-non-null cdr-non-null) (if cdr-non-null (let* ((temp-p temp) (temp (or temp *loop-desetq-temporary*)) (body #+LOOP-Prefer-POP `(,@(loop-desetq-internal car `(prog1 (car ,temp) (setq ,temp (cdr ,temp)))) ,@(loop-desetq-internal cdr temp temp)) #-LOOP-Prefer-POP `(,@(loop-desetq-internal car `(car ,temp)) (setq ,temp (cdr ,temp)) ,@(loop-desetq-internal cdr temp temp)))) (if temp-p `(,@(unless (eq temp val) `((setq ,temp ,val))) ,@body) `((let ((,temp ,val)) ,@body)))) ;; no cdring to do (loop-desetq-internal car `(car ,val) temp))))) (otherwise (unless (eq var val) `((setq ,var ,val))))))) (do ((actions)) ((null var-val-pairs) (if (null (cdr actions)) (car actions) `(progn ,@(nreverse actions)))) (setq actions (revappend (loop-desetq-internal (pop var-val-pairs) (pop var-val-pairs)) actions))))) ;;;; LOOP-local variables ;;;This is the "current" pointer into the LOOP source code. (defvar *loop-source-code*) ;;;This is the pointer to the original, for things like NAMED that ;;;insist on being in a particular position (defvar *loop-original-source-code*) ;;;This is *loop-source-code* as of the "last" clause. It is used ;;;primarily for generating error messages (see loop-error, loop-warn). (defvar *loop-source-context*) ;;;List of names for the LOOP, supplied by the NAMED clause. (defvar *loop-names*) ;;;The macroexpansion environment given to the macro. (defvar *loop-macro-environment*) ;;;This holds variable names specified with the USING clause. ;;; See LOOP-NAMED-VARIABLE. (defvar *loop-named-variables*) ;;; LETlist-like list being accumulated for one group of parallel bindings. (defvar *loop-variables*) ;;;List of declarations being accumulated in parallel with ;;;*loop-variables*. (defvar *loop-declarations*) ;;;Used by LOOP for destructuring binding, if it is doing that itself. ;;; See loop-make-variable. (defvar *loop-desetq-crocks*) ;;; List of wrapping forms, innermost first, which go immediately inside ;;; the current set of parallel bindings being accumulated in ;;; *loop-variables*. The wrappers are appended onto a body. E.g., ;;; this list could conceivably has as its value ((with-open-file (g0001 ;;; g0002 ...))), with g0002 being one of the bindings in ;;; *loop-variables* (this is why the wrappers go inside of the variable ;;; bindings). (defvar *loop-wrappers*) ;;;This accumulates lists of previous values of *loop-variables* and the ;;;other lists above, for each new nesting of bindings. See ;;;loop-bind-block. (defvar *loop-bind-stack*) ;;;This is a LOOP-global variable for the (obsolete) NODECLARE clause ;;;which inhibits LOOP from actually outputting a type declaration for ;;;an iteration (or any) variable. (defvar *loop-nodeclare*) ;;;This is simply a list of LOOP iteration variables, used for checking ;;;for duplications. (defvar *loop-iteration-variables*) ;;;List of prologue forms of the loop, accumulated in reverse order. (defvar *loop-prologue*) (defvar *loop-before-loop*) (defvar *loop-body*) (defvar *loop-after-body*) ;;;This is T if we have emitted any body code, so that iteration driving ;;;clauses can be disallowed. This is not strictly the same as ;;;checking *loop-body*, because we permit some clauses such as RETURN ;;;to not be considered "real" body (so as to permit the user to "code" ;;;an abnormal return value "in loop"). (defvar *loop-emitted-body*) ;;;List of epilogue forms (supplied by FINALLY generally), accumulated ;;; in reverse order. (defvar *loop-epilogue*) ;;;List of epilogue forms which are supplied after the above "user" ;;;epilogue. "normal" termination return values are provide by putting ;;;the return form in here. Normally this is done using ;;;loop-emit-final-value, q.v. (defvar *loop-after-epilogue*) ;;;The "culprit" responsible for supplying a final value from the loop. ;;;This is so loop-emit-final-value can moan about multiple return ;;;values being supplied. (defvar *loop-final-value-culprit*) ;;;If not NIL, we are in some branch of a conditional. Some clauses may ;;;be disallowed. (defvar *loop-inside-conditional*) ;;;If not NIL, this is a temporary bound around the loop for holding the ;;;temporary value for "it" in things like "when (f) collect it". It ;;;may be used as a supertemporary by some other things. (defvar *loop-when-it-variable*) ;;;Sometimes we decide we need to fold together parts of the loop, but ;;;some part of the generated iteration code is different for the first ;;;and remaining iterations. This variable will be the temporary which ;;;is the flag used in the loop to tell whether we are in the first or ;;;remaining iterations. (defvar *loop-never-stepped-variable*) ;;;List of all the value-accumulation descriptor structures in the loop. ;;; See loop-get-collection-info. (defvar *loop-collection-cruft*) ; for multiple COLLECTs (etc) ;;;; Code Analysis Stuff (defun loop-constant-fold-if-possible (form &optional expected-type) #+Genera (declare (values new-form constantp constant-value)) (let ((new-form form) (constantp nil) (constant-value nil)) #+Genera (setq new-form (compiler:optimize-form form *loop-macro-environment* :repeat t :do-macro-expansion t :do-named-constants t :do-inline-forms t :do-optimizers t :do-constant-folding t :do-function-args t) constantp (constantp new-form *loop-macro-environment*) constant-value (and constantp (lt:evaluate-constant new-form *loop-macro-environment*))) #-Genera (when (setq constantp (constantp new-form)) (setq constant-value (eval new-form))) (when (and constantp expected-type) (unless (typep constant-value expected-type) (loop-warn "The form ~S evaluated to ~S, which was not of the anticipated type ~S." form constant-value expected-type) (setq constantp nil constant-value nil))) (values new-form constantp constant-value))) (defun loop-constantp (form) #+Genera (constantp form *loop-macro-environment*) #-Genera (constantp form)) ;;;; LOOP Iteration Optimization (defvar *loop-duplicate-code* nil) (defvar *loop-iteration-flag-variable* (make-symbol "LOOP-NOT-FIRST-TIME")) (defun loop-code-duplication-threshold (env) (multiple-value-bind (speed space) (loop-optimization-quantities env) (+ 40 (* (- speed space) 10)))) (defmacro loop-body (&environment env prologue before-loop main-body after-loop epilogue &aux rbefore rafter flagvar) (unless (= (length before-loop) (length after-loop)) (error "LOOP-BODY called with non-synched before- and after-loop lists.")) ;;All our work is done from these copies, working backwards from the end: (setq rbefore (reverse before-loop) rafter (reverse after-loop)) (labels ((psimp (l) (let ((ans nil)) (dolist (x l) (when x (push x ans) (when (and (consp x) (member (car x) '(go return return-from))) (return nil)))) (nreverse ans))) (pify (l) (if (null (cdr l)) (car l) `(progn ,@l))) (makebody () (let ((form `(tagbody ;; ANSI CL 6.1.7.2 says that initially clauses are ;; evaluated in the loop prologue, which precedes ;; all loop code except for the initial settings ;; provided by with, for, or as. ,@(psimp (append (nreverse rbefore) prologue)) next-loop ,@(psimp (append main-body (nreconc rafter `((go next-loop))))) end-loop ,@(psimp epilogue)))) (if flagvar `(let ((,flagvar nil)) ,form) form)))) (when (or *loop-duplicate-code* (not rbefore)) (return-from loop-body (makebody))) ;; This outer loop iterates once for each not-first-time flag test generated ;; plus once more for the forms that don't need a flag test (do ((threshold (loop-code-duplication-threshold env))) (nil) (declare (fixnum threshold)) ;; Go backwards from the ends of before-loop and after-loop merging all the equivalent ;; forms into the body. (do () ((or (null rbefore) (not (equal (car rbefore) (car rafter))))) (push (pop rbefore) main-body) (pop rafter)) (unless rbefore (return (makebody))) ;; The first forms in rbefore & rafter (which are the chronologically ;; last forms in the list) differ, therefore they cannot be moved ;; into the main body. If everything that chronologically precedes ;; them either differs or is equal but is okay to duplicate, we can ;; just put all of rbefore in the prologue and all of rafter after ;; the body. Otherwise, there is something that is not okay to ;; duplicate, so it and everything chronologically after it in ;; rbefore and rafter must go into the body, with a flag test to ;; distinguish the first time around the loop from later times. ;; What chronologically precedes the non-duplicatable form will ;; be handled the next time around the outer loop. (do ((bb rbefore (cdr bb)) (aa rafter (cdr aa)) (lastdiff nil) (count 0) (inc nil)) ((null bb) (return-from loop-body (makebody))) ;Did it. (cond ((not (equal (car bb) (car aa))) (setq lastdiff bb count 0)) ((or (not (setq inc (estimate-code-size (car bb) env))) (> (incf count inc) threshold)) ;; Ok, we have found a non-duplicatable piece of code. Everything ;; chronologically after it must be in the central body. ;; Everything chronologically at and after lastdiff goes into the ;; central body under a flag test. (let ((then nil) (else nil)) (do () (nil) (push (pop rbefore) else) (push (pop rafter) then) (when (eq rbefore (cdr lastdiff)) (return))) (unless flagvar (push `(setq ,(setq flagvar *loop-iteration-flag-variable*) t) else)) (push `(if ,flagvar ,(pify (psimp then)) ,(pify (psimp else))) main-body)) ;; Everything chronologically before lastdiff until the non-duplicatable form (car bb) ;; is the same in rbefore and rafter so just copy it into the body (do () (nil) (pop rafter) (push (pop rbefore) main-body) (when (eq rbefore (cdr bb)) (return))) (return))))))) (defun duplicatable-code-p (expr env) (if (null expr) 0 (let ((ans (estimate-code-size expr env))) (declare (fixnum ans)) ;;@@@@ Use (DECLARATION-INFORMATION 'OPTIMIZE ENV) here to get an alist of ;; optimize quantities back to help quantify how much code we are willing to ;; duplicate. ans))) (defvar *special-code-sizes* '((return 0) (progn 0) (null 1) (not 1) (eq 1) (car 1) (cdr 1) (when 1) (unless 1) (if 1) (caar 2) (cadr 2) (cdar 2) (cddr 2) (caaar 3) (caadr 3) (cadar 3) (caddr 3) (cdaar 3) (cdadr 3) (cddar 3) (cdddr 3) (caaaar 4) (caaadr 4) (caadar 4) (caaddr 4) (cadaar 4) (cadadr 4) (caddar 4) (cadddr 4) (cdaaar 4) (cdaadr 4) (cdadar 4) (cdaddr 4) (cddaar 4) (cddadr 4) (cdddar 4) (cddddr 4))) (defvar *estimate-code-size-punt* '(block do do* dolist flet labels lambda let let* locally macrolet multiple-value-bind prog prog* symbol-macrolet tagbody unwind-protect with-open-file)) (defun destructuring-size (x) (do ((x x (cdr x)) (n 0 (+ (destructuring-size (car x)) n))) ((atom x) (+ n (if (null x) 0 1))))) (defun estimate-code-size (x env) (catch 'estimate-code-size (estimate-code-size-1 x env))) (defun estimate-code-size-1 (x env) (flet ((list-size (l) (let ((n 0)) (declare (fixnum n)) (dolist (x l n) (incf n (estimate-code-size-1 x env)))))) ;;@@@@ ???? (declare (function list-size (list) fixnum)) (cond ((constantp x #+Genera env) 1) ((symbolp x) (multiple-value-bind (new-form expanded-p) (macroexpand-1 x env) (if expanded-p (estimate-code-size-1 new-form env) 1))) ((atom x) 1) ;??? self-evaluating??? ((symbolp (car x)) (let ((fn (car x)) (tem nil) (n 0)) (declare (symbol fn) (fixnum n)) (macrolet ((f (overhead &optional (args nil args-p)) `(the fixnum (+ (the fixnum ,overhead) (the fixnum (list-size ,(if args-p args '(cdr x)))))))) (cond ((setq tem (get fn 'estimate-code-size)) (typecase tem (fixnum (f tem)) (t (funcall tem x env)))) ((setq tem (assoc fn *special-code-sizes*)) (f (second tem))) #+Genera ((eq fn 'compiler:invisible-references) (list-size (cddr x))) ((eq fn 'cond) (dolist (clause (cdr x) n) (incf n (list-size clause)) (incf n))) ((eq fn 'desetq) (do ((l (cdr x) (cdr l))) ((null l) n) (setq n (+ n (destructuring-size (car l)) (estimate-code-size-1 (cadr l) env))))) ((member fn '(setq psetq)) (do ((l (cdr x) (cdr l))) ((null l) n) (setq n (+ n (estimate-code-size-1 (cadr l) env) 1)))) ((eq fn 'go) 1) ((eq fn 'function) ;;This skirts the issue of implementationally-defined lambda macros ;; by recognizing CL function names and nothing else. #-cmu 1 #+cmu (if (ext:valid-function-name-p (cadr x)) 1 (throw 'duplicatable-code-p nil))) ((eq fn 'multiple-value-setq) (f (length (second x)) (cddr x))) ((eq fn 'return-from) (1+ (estimate-code-size-1 (third x) env))) ((or (special-operator-p fn) (member fn *estimate-code-size-punt*)) (throw 'estimate-code-size nil)) (t (multiple-value-bind (new-form expanded-p) (macroexpand-1 x env) (if expanded-p (estimate-code-size-1 new-form env) (f 3)))))))) (t (throw 'estimate-code-size nil))))) ;;;; Loop Errors (defun loop-context () (do ((l *loop-source-context* (cdr l)) (new nil (cons (car l) new))) ((eq l (cdr *loop-source-code*)) (nreverse new)))) (defun loop-error (format-string &rest format-args) #+(or Genera CLOE) (declare (dbg:error-reporter)) #+Genera (setq format-args (copy-list format-args)) ;Don't ask. #+cmu (kernel:simple-program-error "~?~%Current LOOP context:~{ ~S~}." format-string format-args (loop-context)) #-cmu (error "~?~%Current LOOP context:~{ ~S~}." format-string format-args (loop-context))) (defun loop-warn (format-string &rest format-args) (warn "~?~%Current LOOP context:~{ ~S~}." format-string format-args (loop-context))) (defun loop-check-data-type (specified-type required-type &optional (default-type required-type)) (if (null specified-type) default-type (multiple-value-bind (a b) (subtypep specified-type required-type) (cond ((not b) (loop-warn "LOOP couldn't verify that ~S is a subtype of the required type ~S." specified-type required-type)) ((not a) (loop-error "Specified data type ~S is not a subtype of ~S." specified-type required-type))) specified-type))) ;;;INTERFACE: Traditional, ANSI, Lucid. (defmacro loop-finish () "Causes the iteration to terminate \"normally\", the same as implicit termination by an iteration driving clause, or by use of WHILE or UNTIL -- the epilogue code (if any) will be run, and any implicitly collected result will be returned as the value of the LOOP." '(go end-loop)) (defun subst-gensyms-for-nil (tree) (declare (special *ignores*)) (cond ((null tree) (car (push (loop-gentemp) *ignores*))) ((atom tree) tree) (t (cons (subst-gensyms-for-nil (car tree)) (subst-gensyms-for-nil (cdr tree)))))) (defun loop-build-destructuring-bindings (crocks forms) (if crocks (let ((*ignores* ())) (declare (special *ignores*)) `((destructuring-bind ,(subst-gensyms-for-nil (car crocks)) ,(cadr crocks) (declare (ignore ,@*ignores*)) ,@(loop-build-destructuring-bindings (cddr crocks) forms)))) forms)) (defun loop-translate (*loop-source-code* *loop-macro-environment* *loop-universe*) (let ((*loop-original-source-code* *loop-source-code*) (*loop-source-context* nil) (*loop-iteration-variables* nil) (*loop-variables* nil) (*loop-nodeclare* nil) (*loop-named-variables* nil) (*loop-declarations* nil) (*loop-desetq-crocks* nil) (*loop-bind-stack* nil) (*loop-prologue* nil) (*loop-wrappers* nil) (*loop-before-loop* nil) (*loop-body* nil) (*loop-emitted-body* nil) (*loop-after-body* nil) (*loop-epilogue* nil) (*loop-after-epilogue* nil) (*loop-final-value-culprit* nil) (*loop-inside-conditional* nil) (*loop-when-it-variable* nil) (*loop-never-stepped-variable* nil) (*loop-names* nil) (*loop-collection-cruft* nil)) (loop-iteration-driver) (loop-bind-block) (let ((answer `(loop-body ,(nreverse *loop-prologue*) ,(nreverse *loop-before-loop*) ,(nreverse *loop-body*) ,(nreverse *loop-after-body*) ,(nreconc *loop-epilogue* (nreverse *loop-after-epilogue*))))) (dolist (entry *loop-bind-stack*) (let ((vars (first entry)) (dcls (second entry)) (crocks (third entry)) (wrappers (fourth entry))) (dolist (w wrappers) (setq answer (append w (list answer)))) (when (or vars dcls crocks) (let ((forms (list answer))) ;;(when crocks (push crocks forms)) (when dcls (push `(declare ,@dcls) forms)) (setq answer `(,(cond ((not vars) 'locally) (*loop-destructuring-hooks* (first *loop-destructuring-hooks*)) (t 'let)) ,vars ,@(loop-build-destructuring-bindings crocks forms))))))) (if *loop-names* (do () ((null (car *loop-names*)) answer) (setq answer `(block ,(pop *loop-names*) ,answer))) `(block nil ,answer))))) (defun loop-iteration-driver () (do () ((null *loop-source-code*)) (let ((keyword (car *loop-source-code*)) (tem nil)) (cond ((not (symbolp keyword)) (loop-error "~S found where LOOP keyword expected." keyword)) (t (setq *loop-source-context* *loop-source-code*) (loop-pop-source) (cond ((setq tem (loop-lookup-keyword keyword (loop-universe-keywords *loop-universe*))) ;;It's a "miscellaneous" toplevel LOOP keyword (do, collect, named, etc.) (apply (symbol-function (first tem)) (rest tem))) ((setq tem (loop-lookup-keyword keyword (loop-universe-iteration-keywords *loop-universe*))) (loop-hack-iteration tem)) ((loop-tmember keyword '(and else)) ;; Alternative is to ignore it, ie let it go around to the next keyword... (loop-error "Secondary clause misplaced at top level in LOOP macro: ~S ~S ~S ..." keyword (car *loop-source-code*) (cadr *loop-source-code*))) (t (loop-error "~S is an unknown keyword in LOOP macro." keyword)))))))) (defun loop-pop-source () (if *loop-source-code* (pop *loop-source-code*) (loop-error "LOOP source code ran out when another token was expected."))) (defun loop-get-compound-form () (let ((form (loop-get-form))) (unless (consp form) (loop-error "Compound form expected, but found ~A." form)) form)) (defun loop-get-progn () (do ((forms (list (loop-get-compound-form)) (cons (loop-get-compound-form) forms)) (nextform (car *loop-source-code*) (car *loop-source-code*))) ((atom nextform) (if (null (cdr forms)) (car forms) (cons 'progn (nreverse forms)))))) (defun loop-get-form () (if *loop-source-code* (loop-pop-source) (loop-error "LOOP code ran out where a form was expected."))) (defun loop-construct-return (form) `(return-from ,(car *loop-names*) ,form)) (defun loop-pseudo-body (form) (cond ((or *loop-emitted-body* *loop-inside-conditional*) (push form *loop-body*)) (t (push form *loop-before-loop*) (push form *loop-after-body*)))) (defun loop-emit-body (form) (setq *loop-emitted-body* t) (loop-pseudo-body form)) (defun loop-emit-final-value (&optional (form nil form-supplied-p)) (when form-supplied-p (push (loop-construct-return form) *loop-after-epilogue*)) (when *loop-final-value-culprit* (loop-warn "LOOP clause is providing a value for the iteration,~@ however one was already established by a ~S clause." *loop-final-value-culprit*)) (setq *loop-final-value-culprit* (car *loop-source-context*))) (defun loop-disallow-conditional (&optional kwd) #+(or Genera CLOE) (declare (dbg:error-reporter)) (when *loop-inside-conditional* (loop-error "~:[This LOOP~;The LOOP ~:*~S~] clause is not permitted inside a conditional." kwd))) (defun loop-disallow-anonymous-collectors () (when (find-if-not 'loop-collector-name *loop-collection-cruft*) (loop-error "This LOOP clause is not permitted with anonymous collectors."))) (defun loop-disallow-aggregate-booleans () (when (loop-tmember *loop-final-value-culprit* '(always never thereis)) (loop-error "This anonymous collection LOOP clause is not permitted with aggregate booleans."))) ;;;; Loop Types (defun loop-typed-init (data-type) (when (and data-type (subtypep data-type 'number)) (if (or (subtypep data-type 'float) (subtypep data-type '(complex float))) (coerce 0 data-type) 0))) (defun loop-optional-type (&optional variable) ;;No variable specified implies that no destructuring is permissible. (and *loop-source-code* ;Don't get confused by NILs... (let ((z (car *loop-source-code*))) (cond ((loop-tequal z 'of-type) ;;This is the syntactically unambigous form in that the form of the ;; type specifier does not matter. Also, it is assumed that the ;; type specifier is unambiguously, and without need of translation, ;; a common lisp type specifier or pattern (matching the variable) thereof. (loop-pop-source) (loop-pop-source)) ((symbolp z) ;;This is the (sort of) "old" syntax, even though we didn't used to support all of ;; these type symbols. (let ((type-spec (or (gethash z (loop-universe-type-symbols *loop-universe*)) (gethash (symbol-name z) (loop-universe-type-keywords *loop-universe*))))) (when type-spec (loop-pop-source) type-spec))) (t ;;This is our sort-of old syntax. But this is only valid for when we are destructuring, ;; so we will be compulsive (should we really be?) and require that we in fact be ;; doing variable destructuring here. We must translate the old keyword pattern typespec ;; into a fully-specified pattern of real type specifiers here. (if (consp variable) (unless (consp z) (loop-error "~S found where a LOOP keyword, LOOP type keyword, or LOOP type pattern expected." z)) (loop-error "~S found where a LOOP keyword or LOOP type keyword expected." z)) (loop-pop-source) (labels ((translate (k v) (cond ((null k) nil) ((atom k) (replicate (or (gethash k (loop-universe-type-symbols *loop-universe*)) (gethash (symbol-name k) (loop-universe-type-keywords *loop-universe*)) (loop-error "Destructuring type pattern ~S contains unrecognized type keyword ~S." z k)) v)) ((atom v) (loop-error "Destructuring type pattern ~S doesn't match variable pattern ~S." z variable)) (t (cons (translate (car k) (car v)) (translate (cdr k) (cdr v)))))) (replicate (typ v) (if (atom v) typ (cons (replicate typ (car v)) (replicate typ (cdr v)))))) (translate z variable))))))) ;;;; Loop Variables (defun loop-bind-block () (when (or *loop-variables* *loop-declarations* *loop-wrappers*) (push (list (nreverse *loop-variables*) *loop-declarations* *loop-desetq-crocks* *loop-wrappers*) *loop-bind-stack*) (setq *loop-variables* nil *loop-declarations* nil *loop-desetq-crocks* nil *loop-wrappers* nil))) (defun loop-variable-p (name) (do ((entry *loop-bind-stack* (cdr entry))) (nil) (cond ((null entry) (return nil)) ((assoc name (caar entry) :test #'eq) (return t))))) (defun loop-make-variable (name initialization dtype &optional iteration-variable-p) (cond ((null name) (cond ((not (null initialization)) (push (list (setq name (loop-gentemp 'loop-ignore-)) initialization) *loop-variables*) (push `(ignore ,name) *loop-declarations*)))) ((atom name) (cond (iteration-variable-p (if (member name *loop-iteration-variables*) (loop-error "Duplicated LOOP iteration variable ~S." name) (push name *loop-iteration-variables*))) ((assoc name *loop-variables*) (loop-error "Duplicated variable ~S in LOOP parallel binding." name))) (unless (symbolp name) (loop-error "Bad variable ~S somewhere in LOOP." name)) (loop-declare-variable name dtype) ;; We use ASSOC on this list to check for duplications (above), ;; so don't optimize out this list: (push (list name (or initialization (loop-typed-init dtype))) *loop-variables*)) (initialization (cond (*loop-destructuring-hooks* (loop-declare-variable name dtype) (push (list name initialization) *loop-variables*)) (t (let ((newvar (loop-gentemp 'loop-destructure-))) (loop-declare-variable name dtype) (push (list newvar initialization) *loop-variables*) ;; *LOOP-DESETQ-CROCKS* gathered in reverse order. (setq *loop-desetq-crocks* (list* name newvar *loop-desetq-crocks*)) #+ignore (loop-make-variable name nil dtype iteration-variable-p))))) (t (let ((tcar nil) (tcdr nil)) (if (atom dtype) (setq tcar (setq tcdr dtype)) (setq tcar (car dtype) tcdr (cdr dtype))) (loop-make-variable (car name) nil tcar iteration-variable-p) (loop-make-variable (cdr name) nil tcdr iteration-variable-p)))) name) (defun loop-make-iteration-variable (name initialization dtype) (when (and name (loop-variable-p name)) (loop-error "Variable ~S has already been used" name)) (loop-make-variable name initialization dtype t)) (defun loop-declare-variable (name dtype) (cond ((or (null name) (null dtype) (eq dtype t)) nil) ((symbolp name) (unless (or (eq dtype t) (member (the symbol name) *loop-nodeclare*)) (let ((dtype (let ((init (loop-typed-init dtype))) (if (typep init dtype) dtype `(or (member ,init) ,dtype))))) (push `(type ,dtype ,name) *loop-declarations*)))) ((consp name) (cond ((consp dtype) (loop-declare-variable (car name) (car dtype)) (loop-declare-variable (cdr name) (cdr dtype))) (t (loop-declare-variable (car name) dtype) (loop-declare-variable (cdr name) dtype)))) (t (error "Invalid LOOP variable passed in: ~S." name)))) (defun loop-maybe-bind-form (form data-type) (if (loop-constantp form) form (loop-make-variable (loop-gentemp 'loop-bind-) form data-type))) (defun loop-do-if (for negatep) (let ((form (loop-get-form)) (it-p nil) (first-clause-p t) then else) (let ((*loop-inside-conditional* t)) (flet ((get-clause (for) (do ((body nil)) (nil) (let ((key (car *loop-source-code*)) (*loop-body* nil) data) (cond ((not (symbolp key)) (loop-error "~S found where keyword expected getting LOOP clause after ~S." key for)) (t (setq *loop-source-context* *loop-source-code*) (loop-pop-source) (when (and (loop-tequal (car *loop-source-code*) 'it) first-clause-p) (setq *loop-source-code* (cons (or it-p (setq it-p (loop-when-it-variable))) (cdr *loop-source-code*)))) (cond ((or (not (setq data (loop-lookup-keyword key (loop-universe-keywords *loop-universe*)))) (progn (apply (symbol-function (car data)) (cdr data)) (null *loop-body*))) (loop-error "~S does not introduce a LOOP clause that can follow ~S." key for)) (t (setq body (nreconc *loop-body* body))))))) (setq first-clause-p nil) (if (loop-tequal (car *loop-source-code*) :and) (loop-pop-source) (return (if (cdr body) `(progn ,@(nreverse body)) (car body))))))) (setq then (get-clause for)) (setq else (when (loop-tequal (car *loop-source-code*) :else) (loop-pop-source) (list (get-clause :else))))) (when (loop-tequal (car *loop-source-code*) :end) (loop-pop-source)) (when it-p (setq form `(setq ,it-p ,form)))) (loop-pseudo-body `(if ,(if negatep `(not ,form) form) ,then ,@else)))) (defun loop-do-initially () (loop-disallow-conditional :initially) (push (loop-get-progn) *loop-prologue*)) (defun loop-do-finally () (loop-disallow-conditional :finally) (push (loop-get-progn) *loop-epilogue*)) (defun loop-do-do () (loop-emit-body (loop-get-progn))) (defun loop-do-named () (let ((name (loop-pop-source))) (unless (symbolp name) (loop-error "~S is an invalid name for your LOOP." name)) (when (or *loop-before-loop* *loop-body* *loop-after-epilogue* *loop-inside-conditional*) (loop-error "The NAMED ~S clause occurs too late." name)) (when *loop-names* (loop-error "You may only use one NAMED clause in your loop: NAMED ~S ... NAMED ~S." (car *loop-names*) name)) (setq *loop-names* (list name nil)))) (defun loop-do-return () (loop-pseudo-body (loop-construct-return (loop-get-form)))) ;;;; Value Accumulation: List (defstruct (loop-collector (:copier nil) (:predicate nil)) name class (history nil) (tempvars nil) dtype (data nil)) ;collector-specific data (defun loop-get-collection-info (collector class default-type) (let ((form (loop-get-form)) (dtype (and (not (loop-universe-ansi *loop-universe*)) (loop-optional-type))) (name (when (loop-tequal (car *loop-source-code*) 'into) (loop-pop-source) (loop-pop-source)))) (when (not (symbolp name)) (loop-error "Value accumulation recipient name, ~S, is not a symbol." name)) (unless name (loop-disallow-aggregate-booleans)) (unless dtype (setq dtype (or (loop-optional-type) default-type))) (let ((cruft (find (the symbol name) *loop-collection-cruft* :key #'loop-collector-name))) (cond ((not cruft) (when (and name (loop-variable-p name)) (loop-error "Variable ~S cannot be used in INTO clause" name)) (push (setq cruft (make-loop-collector :name name :class class :history (list collector) :dtype dtype)) *loop-collection-cruft*)) (t (unless (eq (loop-collector-class cruft) class) (loop-error "Incompatible kinds of LOOP value accumulation specified for collecting~@ ~:[as the value of the LOOP~;~:*INTO ~S~]: ~S and ~S." name (car (loop-collector-history cruft)) collector)) (unless (equal dtype (loop-collector-dtype cruft)) (loop-warn "Unequal datatypes specified in different LOOP value accumulations~@ into ~S: ~S and ~S." name dtype (loop-collector-dtype cruft)) (when (eq (loop-collector-dtype cruft) t) (setf (loop-collector-dtype cruft) dtype))) (push collector (loop-collector-history cruft)))) (values cruft form)))) (defun loop-list-collection (specifically) ;NCONC, LIST, or APPEND (multiple-value-bind (lc form) (loop-get-collection-info specifically 'list 'list) (let ((tempvars (loop-collector-tempvars lc))) (unless tempvars (setf (loop-collector-tempvars lc) (setq tempvars (list* (loop-gentemp 'loop-list-head-) (loop-gentemp 'loop-list-tail-) (and (loop-collector-name lc) (list (loop-collector-name lc)))))) (push `(with-loop-list-collection-head ,tempvars) *loop-wrappers*) (unless (loop-collector-name lc) (loop-emit-final-value `(loop-collect-answer ,(car tempvars) ,@(cddr tempvars))))) (ecase specifically (list (setq form `(list ,form))) (nconc nil) (append (unless (and (consp form) (eq (car form) 'list)) (setq form `(loop-copylist* ,form))))) (loop-emit-body `(loop-collect-rplacd ,tempvars ,form))))) ;;;; Value Accumulation: max, min, sum, count. (defun loop-sum-collection (specifically required-type default-type) ;SUM, COUNT (multiple-value-bind (lc form) (loop-get-collection-info specifically 'sum default-type) (loop-check-data-type (loop-collector-dtype lc) required-type) (let ((tempvars (loop-collector-tempvars lc))) (unless tempvars (setf (loop-collector-tempvars lc) (setq tempvars (list (loop-make-variable (or (loop-collector-name lc) (loop-gentemp 'loop-sum-)) nil (loop-collector-dtype lc))))) (unless (loop-collector-name lc) (loop-emit-final-value (car (loop-collector-tempvars lc))))) (loop-emit-body (if (eq specifically 'count) `(when ,form (setq ,(car tempvars) ,(hide-variable-reference t (car tempvars) `(1+ ,(car tempvars))))) `(setq ,(car tempvars) (+ ,(hide-variable-reference t (car tempvars) (car tempvars)) ,form))))))) (defun loop-maxmin-collection (specifically) (multiple-value-bind (lc form) (loop-get-collection-info specifically 'maxmin *loop-real-data-type*) (loop-check-data-type (loop-collector-dtype lc) *loop-real-data-type*) (let ((data (loop-collector-data lc))) (unless data (setf (loop-collector-data lc) (setq data (make-loop-minimax (or (loop-collector-name lc) (loop-gentemp 'loop-maxmin-)) (loop-collector-dtype lc)))) (unless (loop-collector-name lc) (loop-emit-final-value (loop-minimax-answer-variable data)))) (loop-note-minimax-operation specifically data) (push `(with-minimax-value ,data) *loop-wrappers*) (loop-emit-body `(loop-accumulate-minimax-value ,data ,specifically ,form)) ))) ;;;; Value Accumulation: Aggregate Booleans ;;;ALWAYS and NEVER. ;;; Under ANSI these are not permitted to appear under conditionalization. (defun loop-do-always (restrictive negate) (let ((form (loop-get-form))) (when restrictive (loop-disallow-conditional)) (loop-disallow-anonymous-collectors) (loop-emit-body `(,(if negate 'when 'unless) ,form ,(loop-construct-return nil))) (loop-emit-final-value t))) ;;;THERIS. ;;; Under ANSI this is not permitted to appear under conditionalization. (defun loop-do-thereis (restrictive) (when restrictive (loop-disallow-conditional)) (loop-disallow-anonymous-collectors) (loop-emit-final-value) (loop-emit-body `(when (setq ,(loop-when-it-variable) ,(loop-get-form)) ,(loop-construct-return *loop-when-it-variable*)))) (defun loop-do-while (negate kwd &aux (form (loop-get-form))) (loop-disallow-conditional kwd) (loop-pseudo-body `(,(if negate 'when 'unless) ,form (go end-loop)))) (defun loop-do-with () (loop-disallow-conditional :with) (do ((var) (val) (dtype)) (nil) (setq var (loop-pop-source) dtype (loop-optional-type var) val (cond ((loop-tequal (car *loop-source-code*) :=) (loop-pop-source) (loop-get-form)) (t nil))) (when (and var (loop-variable-p var)) (loop-error "Variable ~S has already been used" var)) (loop-make-variable var val dtype) (if (loop-tequal (car *loop-source-code*) :and) (loop-pop-source) (return (loop-bind-block))))) ;;;; The iteration driver (defun loop-hack-iteration (entry) (flet ((make-endtest (list-of-forms) (cond ((null list-of-forms) nil) ((member t list-of-forms) '(go end-loop)) (t `(when ,(if (null (cdr (setq list-of-forms (nreverse list-of-forms)))) (car list-of-forms) (cons 'or list-of-forms)) (go end-loop)))))) (do ((pre-step-tests nil) (steps nil) (post-step-tests nil) (pseudo-steps nil) (pre-loop-pre-step-tests nil) (pre-loop-steps nil) (pre-loop-post-step-tests nil) (pre-loop-pseudo-steps nil) (tem) (data)) (nil) ;; Note we collect endtests in reverse order, but steps in correct ;; order. MAKE-ENDTEST does the nreverse for us. (setq tem (setq data (apply (symbol-function (first entry)) (rest entry)))) (and (car tem) (push (car tem) pre-step-tests)) (setq steps (nconc steps (loop-copylist* (car (setq tem (cdr tem)))))) (and (car (setq tem (cdr tem))) (push (car tem) post-step-tests)) (setq pseudo-steps (nconc pseudo-steps (loop-copylist* (car (setq tem (cdr tem)))))) (setq tem (cdr tem)) (when *loop-emitted-body* (loop-error "Iteration in LOOP follows body code.")) (unless tem (setq tem data)) (when (car tem) (push (car tem) pre-loop-pre-step-tests)) (setq pre-loop-steps (nconc pre-loop-steps (loop-copylist* (car (setq tem (cdr tem)))))) (when (car (setq tem (cdr tem))) (push (car tem) pre-loop-post-step-tests)) (setq pre-loop-pseudo-steps (nconc pre-loop-pseudo-steps (loop-copylist* (cadr tem)))) (unless (loop-tequal (car *loop-source-code*) :and) (setq *loop-before-loop* (list* (loop-make-desetq pre-loop-pseudo-steps) (make-endtest pre-loop-post-step-tests) (loop-make-psetq pre-loop-steps) (make-endtest pre-loop-pre-step-tests) *loop-before-loop*) *loop-after-body* (list* (loop-make-desetq pseudo-steps) (make-endtest post-step-tests) (loop-make-psetq steps) (make-endtest pre-step-tests) *loop-after-body*)) (loop-bind-block) (return nil)) (loop-pop-source) ; flush the "AND" (when (and (not (loop-universe-implicit-for-required *loop-universe*)) (setq tem (loop-lookup-keyword (car *loop-source-code*) (loop-universe-iteration-keywords *loop-universe*)))) ;;Latest ANSI clarification is that the FOR/AS after the AND must NOT be supplied. (loop-pop-source) (setq entry tem))))) ;;;; Main Iteration Drivers ;FOR variable keyword ..args.. (defun loop-do-for () (let* ((var (or (loop-pop-source) (loop-gentemp 'loop-do-for-anon-))) (data-type (loop-optional-type var)) (keyword (loop-pop-source)) (first-arg nil) (tem nil)) (setq first-arg (loop-get-form)) (unless (and (symbolp keyword) (setq tem (loop-lookup-keyword keyword (loop-universe-for-keywords *loop-universe*)))) (loop-error "~S is an unknown keyword in FOR or AS clause in LOOP." keyword)) (apply (car tem) var first-arg data-type (cdr tem)))) (defun loop-do-repeat () (loop-disallow-conditional :repeat) (let ((form (loop-get-form)) (type 'real)) (let ((var (loop-make-variable (loop-gentemp) form type))) (push `(when (minusp (decf ,var)) (go end-loop)) *loop-before-loop*) (push `(when (minusp (decf ,var)) (go end-loop)) *loop-after-body*) ;; FIXME: What should ;; (loop count t into a ;; repeat 3 ;; count t into b ;; finally (return (list a b))) ;; return: (3 3) or (4 3)? PUSHes above are for the former ;; variant, L-P-B below for the latter. #+nil (loop-pseudo-body `(when (minusp (decf ,var)) (go end-loop)))))) (defun loop-when-it-variable () (or *loop-when-it-variable* (setq *loop-when-it-variable* (loop-make-variable (loop-gentemp 'loop-it-) nil nil)))) ;;;; Various FOR/AS Subdispatches ;;;ANSI "FOR x = y [THEN z]" is sort of like the old Genera one when the THEN ;;; is omitted (other than being more stringent in its placement), and like ;;; the old "FOR x FIRST y THEN z" when the THEN is present. I.e., the first ;;; initialization occurs in the loop body (first-step), not in the variable binding ;;; phase. (defun loop-ansi-for-equals (var val data-type) (loop-make-iteration-variable var nil data-type) (cond ((loop-tequal (car *loop-source-code*) :then) ;;Then we are the same as "FOR x FIRST y THEN z". (loop-pop-source) `(() (,var ,(loop-get-form)) () () () (,var ,val) () ())) (t ;;We are the same as "FOR x = y". ;; Let me document here what this is returning. Look at ;; loop-hack-iteration for more info. But anyway, we return a list of ;; 8 items, in this order: PRE-STEP-TESTS, STEPS, POST-STEP-TESTS, ;; PSEUDO-STEPS, PRE-LOOP-PRE-STEP-TESTS, PRE-LOOP-STEPS, ;; PRE-LOOP-POST-STEP-TESTS, PRE-LOOP-PSEUDO-STEPS. (We should add ;; something to make it easier to figure out what these args are!) ;; ;; For a "FOR x = y" clause without the THEN, we want the STEPS item to ;; step the variable VAR with the value VAL. This gets placed in the ;; body of the loop. The original code just did that. It seems that ;; the STEPS form is placed in *loop-before-loop* and in ;; *loop-after-loop*. Loop optimization would then see the same form ;; in both, and move them into the beginning of body. This is ok, ;; except that if there are :initially forms that were placed into the ;; loop prologue, the :initially forms might refer to incorrectly ;; initialized variables, because the optimizer moved STEPS from from ;; *loop-before-loop* into the body. ;; ;; To solve this, we add a PRE-LOOP-PSEUDO-STEP form that is identical ;; to the STEPS form. This gets placed in *loop-before-loop*. But ;; this won't match any *loop-after-loop* form, so it won't get moved, ;; and we maintain the proper sequencing such that the ;; PRE-LOOP-PSEUDO-STEP form is in *loop-before-loop*, before any ;; :initially clauses that might refer to this. So all is well. Whew. ;; ;; I hope this doesn't break anything else. `(() (,var ,val) () () () () () (,var ,val)) ))) (defun loop-for-across (var val data-type) (loop-make-iteration-variable var nil data-type) (let ((vector-var (loop-gentemp 'loop-across-vector-)) (index-var (loop-gentemp 'loop-across-index-))) (multiple-value-bind (vector-form constantp vector-value) (loop-constant-fold-if-possible val 'vector) (loop-make-variable vector-var vector-form (if (and (consp vector-form) (eq (car vector-form) 'the)) (cadr vector-form) 'vector)) #+Genera (push `(system:array-register ,vector-var) *loop-declarations*) (loop-make-variable index-var 0 'fixnum) (let* ((length 0) (length-form (cond ((not constantp) (let ((v (loop-gentemp 'loop-across-limit-))) ;; This used to just push the length ;; computation into the prologue code. I ;; (rtoy) don't think that's right, ;; especially since the prologue is supposed ;; to happen AFTER other initializations. ;; So, this puts the computation in ;; *loop-before-body*. We need a matching ;; entry for *loop-after-body*, so stuff a ;; NIL there. (push `(setq ,v (length ,vector-var)) *loop-before-loop*) (push nil *loop-after-body*) (loop-make-variable v 0 'fixnum))) (t (setq length (length vector-value))))) (first-test `(>= ,index-var ,length-form)) (other-test first-test) (step `(,var (aref ,vector-var ,index-var))) (pstep `(,index-var (1+ ,index-var)))) (declare (fixnum length)) (when constantp (setq first-test (= length 0)) (when (<= length 1) (setq other-test t))) `(,other-test ,step () ,pstep ,@(and (not (eq first-test other-test)) `(,first-test ,step () ,pstep))))))) ;;;; List Iteration (defun loop-list-step (listvar) ;;We are not equipped to analyze whether 'FOO is the same as #'FOO here in any ;; sensible fashion, so let's give an obnoxious warning whenever 'FOO is used ;; as the stepping function. ;;While a Discerning Compiler may deal intelligently with (funcall 'foo ...), not ;; recognizing FOO may defeat some LOOP optimizations. (let ((stepper (cond ((loop-tequal (car *loop-source-code*) :by) (loop-pop-source) (loop-get-form)) (t '(function cdr))))) (cond ((and (consp stepper) (eq (car stepper) 'quote)) (loop-warn "Use of QUOTE around stepping function in LOOP will be left verbatim.") (values `(funcall ,stepper ,listvar) nil)) ((and (consp stepper) (eq (car stepper) 'function)) (values (list (cadr stepper) listvar) (cadr stepper))) (t (values `(funcall ,(loop-make-variable (loop-gentemp 'loop-fn-) stepper 'function) ,listvar) nil))))) (defun loop-for-on (var val data-type) (multiple-value-bind (list constantp list-value) (loop-constant-fold-if-possible val) (let ((listvar var)) (cond ((and var (symbolp var)) (loop-make-iteration-variable var list data-type)) (t (loop-make-variable (setq listvar (loop-gentemp)) list 't) (loop-make-iteration-variable var nil data-type))) (multiple-value-bind (list-step step-function) (loop-list-step listvar) (declare #+(and (not LOOP-Prefer-POP) (not CLOE)) (ignore step-function)) ;;@@@@ The CLOE problem above has to do with bug in macroexpansion of multiple-value-bind. (let* ((first-endtest (hide-variable-reference (eq var listvar) listvar ;; the following should use `atom' instead of `endp', per ;; [bug2428] `(atom ,listvar))) (other-endtest first-endtest)) (when (and constantp (listp list-value)) (setq first-endtest (null list-value))) (cond ((eq var listvar) ;;Contour of the loop is different because we use the user's variable... `(() (,listvar ,(hide-variable-reference t listvar list-step)) ,other-endtest () () () ,first-endtest ())) #+LOOP-Prefer-POP ((and step-function (let ((n (cdr (assoc step-function '((cdr . 1) (cddr . 2) (cdddr . 3) (cddddr . 4)))))) (and n (do ((l var (cdr l)) (i 0 (1+ i))) ((atom l) (and (null l) (= i n))) (declare (fixnum i)))))) (let ((step (mapcan #'(lambda (x) (list x `(pop ,listvar))) var))) `(,other-endtest () () ,step ,first-endtest () () ,step))) (t (let ((step `(,var ,listvar)) (pseudo `(,listvar ,list-step))) `(,other-endtest ,step () ,pseudo ,@(and (not (eq first-endtest other-endtest)) `(,first-endtest ,step () ,pseudo))))))))))) (defun loop-for-in (var val data-type) (multiple-value-bind (list constantp list-value) (loop-constant-fold-if-possible val) (let ((listvar (loop-gentemp 'loop-list-))) (loop-make-iteration-variable var nil data-type) (loop-make-variable listvar list 'list) (multiple-value-bind (list-step step-function) (loop-list-step listvar) #-LOOP-Prefer-POP (declare (ignore step-function)) (let* ((first-endtest `(endp ,listvar)) (other-endtest first-endtest) (step `(,var (car ,listvar))) (pseudo-step `(,listvar ,list-step))) (when (and constantp (listp list-value)) (setq first-endtest (null list-value))) #+LOOP-Prefer-POP (when (eq step-function 'cdr) (setq step `(,var (pop ,listvar)) pseudo-step nil)) `(,other-endtest ,step () ,pseudo-step ,@(and (not (eq first-endtest other-endtest)) `(,first-endtest ,step () ,pseudo-step)))))))) ;;;; Iteration Paths (defstruct (loop-path (:copier nil) (:predicate nil)) names preposition-groups inclusive-permitted function user-data) (eval-when (:compile-toplevel :load-toplevel :execute) (defun add-loop-path (names function universe &key preposition-groups inclusive-permitted user-data) (unless (listp names) (setq names (list names))) ;; Can't do this due to CLOS bootstrapping problems. #-(or Genera (and CLOE Source-Bootstrap)) (check-type universe loop-universe) (let ((ht (loop-universe-path-keywords universe)) (lp (make-loop-path :names (mapcar #'symbol-name names) :function function :user-data user-data :preposition-groups (mapcar #'(lambda (x) (if (listp x) x (list x))) preposition-groups) :inclusive-permitted inclusive-permitted))) (dolist (name names) (setf (gethash (symbol-name name) ht) lp)) lp))) ;;; Note: path functions are allowed to use loop-make-variable, hack ;;; the prologue, etc. (defun loop-for-being (var val data-type) ;; FOR var BEING each/the pathname prep-phrases using-stuff... ;; each/the = EACH or THE. Not clear if it is optional, so I guess we'll warn. (let ((path nil) (data nil) (inclusive nil) (stuff nil) (initial-prepositions nil)) (cond ((loop-tmember val '(:each :the)) (setq path (loop-pop-source))) ((loop-tequal (car *loop-source-code*) :and) (loop-pop-source) (setq inclusive t) (unless (loop-tmember (car *loop-source-code*) '(:its :each :his :her)) (loop-error "~S found where ITS or EACH expected in LOOP iteration path syntax." (car *loop-source-code*))) (loop-pop-source) (setq path (loop-pop-source)) (setq initial-prepositions `((:in ,val)))) (t (loop-error "Unrecognizable LOOP iteration path syntax. Missing EACH or THE?"))) (cond ((not (symbolp path)) (loop-error "~S found where a LOOP iteration path name was expected." path)) ((not (setq data (loop-lookup-keyword path (loop-universe-path-keywords *loop-universe*)))) (loop-error "~S is not the name of a LOOP iteration path." path)) ((and inclusive (not (loop-path-inclusive-permitted data))) (loop-error "\"Inclusive\" iteration is not possible with the ~S LOOP iteration path." path))) (let ((fun (loop-path-function data)) (preps (nconc initial-prepositions (loop-collect-prepositional-phrases (loop-path-preposition-groups data) t))) (user-data (loop-path-user-data data))) (when (symbolp fun) (setq fun (symbol-function fun))) (setq stuff (if inclusive (apply fun var data-type preps :inclusive t user-data) (apply fun var data-type preps user-data)))) (when *loop-named-variables* (loop-error "Unused USING variables: ~S." *loop-named-variables*)) ;; STUFF is now (bindings prologue-forms . stuff-to-pass-back). Protect the system from the user ;; and the user from himself. (unless (member (length stuff) '(6 10)) (loop-error "Value passed back by LOOP iteration path function for path ~S has invalid length." path)) (do ((l (car stuff) (cdr l)) (x)) ((null l)) (if (atom (setq x (car l))) (loop-make-iteration-variable x nil nil) (loop-make-iteration-variable (car x) (cadr x) (caddr x)))) (setq *loop-prologue* (nconc (reverse (cadr stuff)) *loop-prologue*)) (cddr stuff))) ;;;INTERFACE: Lucid, exported. ;;; i.e., this is part of our extended ansi-loop interface. (defun named-variable (name) (let ((tem (loop-tassoc name *loop-named-variables*))) (declare (list tem)) (cond ((null tem) (values (loop-gentemp) nil)) (t (setq *loop-named-variables* (delete tem *loop-named-variables*)) (values (cdr tem) t))))) (defun loop-collect-prepositional-phrases (preposition-groups &optional USING-allowed initial-phrases) (flet ((in-group-p (x group) (car (loop-tmember x group)))) (do ((token nil) (prepositional-phrases initial-phrases) (this-group nil nil) (this-prep nil nil) (disallowed-prepositions (mapcan #'(lambda (x) (loop-copylist* (find (car x) preposition-groups :test #'in-group-p))) initial-phrases)) (used-prepositions (mapcar #'car initial-phrases))) ((null *loop-source-code*) (nreverse prepositional-phrases)) (declare (symbol this-prep)) (setq token (car *loop-source-code*)) (dolist (group preposition-groups) (when (setq this-prep (in-group-p token group)) (return (setq this-group group)))) (cond (this-group (when (member this-prep disallowed-prepositions) (loop-error (if (member this-prep used-prepositions) "A ~S prepositional phrase occurs multiply for some LOOP clause." "Preposition ~S used when some other preposition has subsumed it.") token)) (setq used-prepositions (if (listp this-group) (append this-group used-prepositions) (cons this-group used-prepositions))) (loop-pop-source) (push (list this-prep (loop-get-form)) prepositional-phrases)) ((and USING-allowed (loop-tequal token 'using)) (loop-pop-source) (do ((z (loop-pop-source) (loop-pop-source)) (tem)) (nil) (when (cadr z) (if (setq tem (loop-tassoc (car z) *loop-named-variables*)) (loop-error "The variable substitution for ~S occurs twice in a USING phrase,~@ with ~S and ~S." (car z) (cadr z) (cadr tem)) (push (cons (car z) (cadr z)) *loop-named-variables*))) (when (or (null *loop-source-code*) (symbolp (car *loop-source-code*))) (return nil)))) (t (return (nreverse prepositional-phrases))))))) ;;;; Master Sequencer Function (defun loop-sequencer (indexv indexv-type indexv-user-specified-p variable variable-type sequence-variable sequence-type step-hack default-top prep-phrases) (let ((endform nil) ;Form (constant or variable) with limit value. (sequencep nil) ;T if sequence arg has been provided. (testfn nil) ;endtest function (test nil) ;endtest form. (stepby (1+ (or (loop-typed-init indexv-type) 0))) ;Our increment. (stepby-constantp t) (step nil) ;step form. (dir nil) ;Direction of stepping: NIL, :UP, :DOWN. (inclusive-iteration nil) ;T if include last index. (start-given nil) ;T when prep phrase has specified start (start-value nil) (start-constantp nil) (limit-given nil) ;T when prep phrase has specified end (limit-constantp nil) (limit-value nil) ) (when variable (loop-make-iteration-variable variable nil variable-type)) (do ((l prep-phrases (cdr l)) (prep) (form) (odir)) ((null l)) (setq prep (caar l) form (cadar l)) (case prep ((:of :in) (setq sequencep t) (loop-make-variable sequence-variable form sequence-type)) ((:from :downfrom :upfrom) (setq start-given t) (cond ((eq prep :downfrom) (setq dir ':down)) ((eq prep :upfrom) (setq dir ':up))) (multiple-value-setq (form start-constantp start-value) (loop-constant-fold-if-possible form indexv-type)) (loop-make-iteration-variable indexv form indexv-type)) ((:upto :to :downto :above :below) (cond ((loop-tequal prep :upto) (setq inclusive-iteration (setq dir ':up))) ((loop-tequal prep :to) (setq inclusive-iteration t)) ((loop-tequal prep :downto) (setq inclusive-iteration (setq dir ':down))) ((loop-tequal prep :above) (setq dir ':down)) ((loop-tequal prep :below) (setq dir ':up))) (setq limit-given t) (multiple-value-setq (form limit-constantp limit-value) (loop-constant-fold-if-possible form indexv-type)) (setq endform (if limit-constantp `',limit-value (loop-make-variable (loop-gentemp 'loop-limit-) form indexv-type)))) (:by (multiple-value-setq (form stepby-constantp stepby) (loop-constant-fold-if-possible form indexv-type)) (unless stepby-constantp (loop-make-variable (setq stepby (loop-gentemp 'loop-step-by-)) form indexv-type))) (t (loop-error "~S invalid preposition in sequencing or sequence path.~@ Invalid prepositions specified in iteration path descriptor or something?" prep))) (when (and odir dir (not (eq dir odir))) (loop-error "Conflicting stepping directions in LOOP sequencing path")) (setq odir dir)) (when (and sequence-variable (not sequencep)) (loop-error "Missing OF or IN phrase in sequence path")) ;; Now fill in the defaults. (unless start-given (loop-make-iteration-variable indexv (setq start-constantp t start-value (or (loop-typed-init indexv-type) 0)) indexv-type)) (cond ((member dir '(nil :up)) (when (or limit-given default-top) (unless limit-given (loop-make-variable (setq endform (loop-gentemp 'loop-seq-limit-)) nil indexv-type) (push `(setq ,endform ,default-top) *loop-prologue*)) (setq testfn (if inclusive-iteration '> '>=))) (setq step (if (eql stepby 1) `(1+ ,indexv) `(+ ,indexv ,stepby)))) (t (unless start-given (unless default-top (loop-error "Don't know where to start stepping.")) (push `(setq ,indexv (1- ,default-top)) *loop-prologue*)) (when (and default-top (not endform)) (setq endform (loop-typed-init indexv-type) inclusive-iteration t)) (when endform (setq testfn (if inclusive-iteration '< '<=))) (setq step (if (eql stepby 1) `(1- ,indexv) `(- ,indexv ,stepby))))) (when testfn (setq test (hide-variable-reference t indexv `(,testfn ,indexv ,endform)))) (when step-hack (setq step-hack `(,variable ,(hide-variable-reference indexv-user-specified-p indexv step-hack)))) (let ((first-test test) (remaining-tests test)) (when (and stepby-constantp start-constantp limit-constantp) (when (setq first-test (funcall (symbol-function testfn) start-value limit-value)) (setq remaining-tests t))) `(() (,indexv ,(hide-variable-reference t indexv step)) ,remaining-tests ,step-hack () () ,first-test ,step-hack)))) ;;;; Interfaces to the Master Sequencer (defun loop-for-arithmetic (var val data-type kwd) (loop-sequencer var (loop-check-data-type data-type 'number) t nil nil nil nil nil nil (loop-collect-prepositional-phrases '((:from :upfrom :downfrom) (:to :upto :downto :above :below) (:by)) nil (list (list kwd val))))) (defun loop-sequence-elements-path (variable data-type prep-phrases &key fetch-function size-function sequence-type element-type) (multiple-value-bind (indexv indexv-user-specified-p) (named-variable 'index) (let ((sequencev (named-variable 'sequence))) #+Genera (when (and sequencev (symbolp sequencev) sequence-type (subtypep sequence-type 'vector) (not (member (the symbol sequencev) *loop-nodeclare*))) (push `(sys:array-register ,sequencev) *loop-declarations*)) (list* nil nil ; dummy bindings and prologue (loop-sequencer indexv 'fixnum indexv-user-specified-p variable (or data-type element-type) sequencev sequence-type `(,fetch-function ,sequencev ,indexv) `(,size-function ,sequencev) prep-phrases))))) ;;;; Builtin LOOP Iteration Paths #|| (loop for v being the hash-values of ht do (print v)) (loop for k being the hash-keys of ht do (print k)) (loop for v being the hash-values of ht using (hash-key k) do (print (list k v))) (loop for k being the hash-keys of ht using (hash-value v) do (print (list k v))) ||# (defun loop-hash-table-iteration-path (variable data-type prep-phrases &key which) (check-type which (member hash-key hash-value)) (cond ((or (cdr prep-phrases) (not (member (caar prep-phrases) '(:in :of)))) (loop-error "Too many prepositions!")) ((null prep-phrases) (loop-error "Missing OF or IN in ~S iteration path."))) (let ((ht-var (loop-gentemp 'loop-hashtab-)) (next-fn (loop-gentemp 'loop-hashtab-next-)) (dummy-predicate-var nil) (post-steps nil)) (multiple-value-bind (other-var other-p) (named-variable (if (eq which 'hash-key) 'hash-value 'hash-key)) ;;@@@@ named-variable returns a second value of T if the name was actually ;; specified, so clever code can throw away the gensym'ed up variable if ;; it isn't really needed. ;;The following is for those implementations in which we cannot put dummy NILs ;; into multiple-value-setq variable lists. #-Genera (setq other-p t dummy-predicate-var (loop-when-it-variable)) (let* ((key-var nil) (val-var nil) (temp-val-var (loop-gentemp 'loop-hash-val-temp-)) (temp-key-var (loop-gentemp 'loop-hash-key-temp-)) (temp-predicate-var (loop-gentemp 'loop-hash-predicate-var-)) (variable (or variable (loop-gentemp))) (bindings `((,variable nil ,data-type) (,ht-var ,(cadar prep-phrases)) ,@(and other-p other-var `((,other-var nil)))))) (if (eq which 'hash-key) (setq key-var variable val-var (and other-p other-var)) (setq key-var (and other-p other-var) val-var variable)) (push `(with-hash-table-iterator (,next-fn ,ht-var)) *loop-wrappers*) (when (consp key-var) (setq post-steps `(,key-var ,(setq key-var (loop-gentemp 'loop-hash-key-temp-)) ,@post-steps)) (push `(,key-var nil) bindings)) (when (consp val-var) (setq post-steps `(,val-var ,(setq val-var (loop-gentemp 'loop-hash-val-temp-)) ,@post-steps)) (push `(,val-var nil) bindings)) `(,bindings ;bindings () ;prologue () ;pre-test () ;parallel steps (not (multiple-value-bind (,temp-predicate-var ,temp-key-var ,temp-val-var) (,next-fn) ;; We use M-V-BIND instead of M-V-SETQ because we only ;; want to assign values to the key and val vars when we ;; are in the hash table. When we reach the end, ;; TEMP-PREDICATE-VAR is NIL, and so are temp-key-var and ;; temp-val-var. This might break any type declarations ;; on the key and val vars. (when ,temp-predicate-var (setq ,val-var ,temp-val-var) (setq ,key-var ,temp-key-var)) (setq ,dummy-predicate-var ,temp-predicate-var) )) ;post-test ,post-steps))))) (defun loop-package-symbols-iteration-path (variable data-type prep-phrases &key symbol-types) (cond ((and prep-phrases (cdr prep-phrases)) (loop-error "Too many prepositions!")) ((and prep-phrases (not (member (caar prep-phrases) '(:in :of)))) (loop-error "Unknow preposition ~S" (caar prep-phrases)))) (unless (symbolp variable) (loop-error "Destructuring is not valid for package symbol iteration.")) (let ((pkg-var (loop-gentemp 'loop-pkgsym-)) (next-fn (loop-gentemp 'loop-pkgsym-next-)) (variable (or variable (loop-gentemp))) (pkg (or (cadar prep-phrases) '*package*))) (push `(with-package-iterator (,next-fn ,pkg-var ,@symbol-types)) *loop-wrappers*) `(((,variable nil ,data-type) (,pkg-var ,pkg)) () () () (not (multiple-value-setq (,(progn ;;@@@@ If an implementation can get away without actually ;; using a variable here, so much the better. #+Genera NIL #-Genera (loop-when-it-variable)) ,variable) (,next-fn))) ()))) ;;;; ANSI Loop (eval-when (:compile-toplevel :load-toplevel :execute) (defun make-ansi-loop-universe (extended-p) (let ((w (make-standard-loop-universe :keywords `((named (loop-do-named)) (initially (loop-do-initially)) (finally (loop-do-finally)) (do (loop-do-do)) (doing (loop-do-do)) (return (loop-do-return)) (collect (loop-list-collection list)) (collecting (loop-list-collection list)) (append (loop-list-collection append)) (appending (loop-list-collection append)) (nconc (loop-list-collection nconc)) (nconcing (loop-list-collection nconc)) (count (loop-sum-collection count ,*loop-real-data-type* fixnum)) (counting (loop-sum-collection count ,*loop-real-data-type* fixnum)) (sum (loop-sum-collection sum number number)) (summing (loop-sum-collection sum number number)) (maximize (loop-maxmin-collection max)) (minimize (loop-maxmin-collection min)) (maximizing (loop-maxmin-collection max)) (minimizing (loop-maxmin-collection min)) (always (loop-do-always t nil)) ; Normal, do always (never (loop-do-always t t)) ; Negate the test on always. (thereis (loop-do-thereis t)) (while (loop-do-while nil :while)) ; Normal, do while (until (loop-do-while t :until)) ; Negate the test on while (when (loop-do-if when nil)) ; Normal, do when (if (loop-do-if if nil)) ; synonymous (unless (loop-do-if unless t)) ; Negate the test on when (with (loop-do-with)) (repeat (loop-do-repeat))) :for-keywords '((= (loop-ansi-for-equals)) (across (loop-for-across)) (in (loop-for-in)) (on (loop-for-on)) (from (loop-for-arithmetic :from)) (downfrom (loop-for-arithmetic :downfrom)) (upfrom (loop-for-arithmetic :upfrom)) (below (loop-for-arithmetic :below)) (above (loop-for-arithmetic :above)) (to (loop-for-arithmetic :to)) (upto (loop-for-arithmetic :upto)) (downto (loop-for-arithmetic :downto)) (by (loop-for-arithmetic :by)) (being (loop-for-being))) :iteration-keywords '((for (loop-do-for)) (as (loop-do-for))) :type-symbols '(array atom bignum bit bit-vector character compiled-function complex cons double-float fixnum float function hash-table integer keyword list long-float nil null number package pathname random-state ratio rational readtable sequence short-float simple-array simple-bit-vector simple-string simple-vector single-float standard-char stream string base-char symbol t vector) :type-keywords nil :ansi (if extended-p :extended t)))) (add-loop-path '(hash-key hash-keys) 'loop-hash-table-iteration-path w :preposition-groups '((:of :in)) :inclusive-permitted nil :user-data '(:which hash-key)) (add-loop-path '(hash-value hash-values) 'loop-hash-table-iteration-path w :preposition-groups '((:of :in)) :inclusive-permitted nil :user-data '(:which hash-value)) (add-loop-path '(symbol symbols) 'loop-package-symbols-iteration-path w :preposition-groups '((:of :in)) :inclusive-permitted nil :user-data '(:symbol-types (:internal :external :inherited))) (add-loop-path '(external-symbol external-symbols) 'loop-package-symbols-iteration-path w :preposition-groups '((:of :in)) :inclusive-permitted nil :user-data '(:symbol-types (:external))) (add-loop-path '(present-symbol present-symbols) 'loop-package-symbols-iteration-path w :preposition-groups '((:of :in)) :inclusive-permitted nil :user-data '(:symbol-types (:internal :external))) w)) (defparameter *loop-ansi-universe* (make-ansi-loop-universe nil)) (defun loop-standard-expansion (keywords-and-forms environment universe) (if (and keywords-and-forms (symbolp (car keywords-and-forms))) (loop-translate keywords-and-forms environment universe) (let ((tag (gensym))) `(block nil (tagbody ,tag (progn ,@keywords-and-forms) (go ,tag)))))) ) ;; eval-when ;;;INTERFACE: ANSI (defmacro loop (&environment env &rest keywords-and-forms) #+Genera (declare (compiler:do-not-record-macroexpansions) (zwei:indentation . zwei:indent-loop)) (loop-standard-expansion keywords-and-forms env *loop-ansi-universe*)) #+allegro (defun excl::complex-loop-expander (body env) (loop-standard-expansion body env *loop-ansi-universe*)) ;; Replace the CL::LOOP macro with this macro for use with CLSQL ;; LOOP extensions #+clisp (eval-when (:compile-toplevel :load-toplevel :execute) (shadowing-import '(loop loop-finish) (find-package "COMMON-LISP")) (setf (ext:package-lock (find-package "COMMON-LISP")) t)) cl-sql-6.4.1/sql/metaclasses.lisp0000644000175000017500000006051512064366222015735 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; ;;;; CLSQL metaclass for standard-db-objects created in the OODDL. ;;;; ;;;; This file is part of CLSQL. ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* (in-package #:clsql-sys) (eval-when (:compile-toplevel :load-toplevel :execute) (when (>= (length (generic-function-lambda-list (ensure-generic-function 'compute-effective-slot-definition))) 3) (pushnew :kmr-normal-cesd cl:*features*)) (when (>= (length (generic-function-lambda-list (ensure-generic-function 'direct-slot-definition-class))) 3) (pushnew :kmr-normal-dsdc cl:*features*)) (when (>= (length (generic-function-lambda-list (ensure-generic-function 'effective-slot-definition-class))) 3) (pushnew :kmr-normal-esdc cl:*features*))) ;; ------------------------------------------------------------ ;; metaclass: view-class (defclass standard-db-class (standard-class) ((view-table :accessor view-table :initarg :view-table) (definition :accessor object-definition :initarg :definition :initform nil) (key-slots :accessor key-slots :initform nil) (normalizedp :accessor normalizedp :initform nil) (class-qualifier :accessor view-class-qualifier :initarg :qualifier :initform nil)) (:documentation "Metaclass for all CLSQL View Classes.")) ;;; Lispworks 4.2 and before requires special processing of extra slot and class options (defvar +extra-slot-options+ '(:column :db-kind :db-type :db-reader :void-value :db-constraints :db-writer :db-info)) (defvar +extra-class-options+ '(:base-table)) #+lispworks (dolist (slot-option +extra-slot-options+) (eval `(process-slot-option standard-db-class ,slot-option))) #+lispworks (dolist (class-option +extra-class-options+) (eval `(process-class-option standard-db-class ,class-option))) (defmethod validate-superclass ((class standard-db-class) (superclass standard-class)) t) (defun table-name-from-arg (arg) (cond ((symbolp arg) (intern (sql-escape arg))) ((typep arg 'sql-ident) (if (symbolp (slot-value arg 'name)) (intern (sql-escape (slot-value arg 'name))) (sql-escape (slot-value arg 'name)))) ((stringp arg) (sql-escape arg)))) (defun remove-keyword-arg (arglist akey) (let ((mylist arglist) (newlist ())) (labels ((pop-arg (alist) (let ((arg (pop alist)) (val (pop alist))) (unless (equal arg akey) (setf newlist (append (list arg val) newlist))) (when alist (pop-arg alist))))) (pop-arg mylist)) newlist)) (defun set-view-table-slot (class base-table) (setf (view-table class) (table-name-from-arg (or (and base-table (if (listp base-table) (car base-table) base-table)) (class-name class))))) (defmethod initialize-instance :around ((class standard-db-class) &rest all-keys &key direct-superclasses base-table qualifier normalizedp &allow-other-keys) (let ((root-class (find-class 'standard-db-object nil)) (vmc 'standard-db-class)) (setf (view-class-qualifier class) (car qualifier)) (if root-class (if (some #'(lambda (super) (typep super vmc)) direct-superclasses) (call-next-method) (apply #'call-next-method class :direct-superclasses (append (list root-class) direct-superclasses) (remove-keyword-arg all-keys :direct-superclasses))) (call-next-method)) (set-view-table-slot class base-table) (setf (normalizedp class) (car normalizedp)) (register-metaclass class (nth (1+ (position :direct-slots all-keys)) all-keys)))) (defmethod reinitialize-instance :around ((class standard-db-class) &rest all-keys &key base-table normalizedp direct-superclasses qualifier &allow-other-keys) (let ((root-class (find-class 'standard-db-object nil)) (vmc 'standard-db-class)) (set-view-table-slot class base-table) (setf (normalizedp class) (car normalizedp)) (setf (view-class-qualifier class) (car qualifier)) (if (and root-class (not (equal class root-class))) (if (some #'(lambda (super) (typep super vmc)) direct-superclasses) (call-next-method) (apply #'call-next-method class :direct-superclasses (append (list root-class) direct-superclasses) (remove-keyword-arg all-keys :direct-superclasses))) (call-next-method))) (register-metaclass class (nth (1+ (position :direct-slots all-keys)) all-keys))) (defun get-keywords (keys list) (flet ((extract (key) (let ((pos (position key list))) (when pos (nth (1+ pos) list))))) (mapcar #'extract keys))) (defun describe-db-layout (class) (flet ((not-db-col (col) (not (member (nth 2 col) '(nil :base :key)))) (frob-slot (slot) (let ((type (slot-definition-type slot))) (if (eq type t) (setq type nil)) (list (slot-value slot 'name) type (slot-value slot 'db-kind) (and (slot-boundp slot 'column) (slot-value slot 'column)))))) (let ((all-slots (mapcar #'frob-slot (ordered-class-slots class)))) (setq all-slots (remove-if #'not-db-col all-slots)) (setq all-slots (stable-sort all-slots #'string< :key #'car)) ;;(mapcar #'dink-type all-slots) all-slots))) (defun register-metaclass (class slots) (labels ((not-db-col (col) (not (member (nth 2 col) '(nil :base :key)))) (frob-slot (slot) (get-keywords '(:name :type :db-kind :column) slot))) (let ((all-slots (mapcar #'frob-slot slots))) (setq all-slots (remove-if #'not-db-col all-slots)) (setq all-slots (stable-sort all-slots #'string< :key #'car)) (setf (object-definition class) all-slots)) #-(or sbcl allegro) (setf (key-slots class) (remove-if-not (lambda (slot) (eql (slot-value slot 'db-kind) :key)) (slots-for-possibly-normalized-class class))))) #+(or sbcl allegro) (defmethod finalize-inheritance :after ((class standard-db-class)) (setf (key-slots class) (remove-if-not (lambda (slot) (eql (slot-value slot 'db-kind) :key)) (slots-for-possibly-normalized-class class)))) ;; return the deepest view-class ancestor for a given view class (defun base-db-class (classname) (let* ((class (find-class classname)) (db-class (find-class 'standard-db-object))) (loop (let ((cds (class-direct-superclasses class))) (cond ((null cds) (error "not a db class")) ((member db-class cds) (return (class-name class)))) (setq class (car cds)))))) (defun db-ancestors (classname) (let ((class (find-class classname)) (db-class (find-class 'standard-db-object))) (labels ((ancestors (class) (let ((scs (class-direct-superclasses class))) (if (member db-class scs) (list class) (append (list class) (mapcar #'ancestors scs)))))) (ancestors class)))) (defclass view-class-slot-definition-mixin () ((column :accessor view-class-slot-column :initarg :column :documentation "The name of the SQL column this slot is stored in. Defaults to the slot name.") (db-kind :accessor view-class-slot-db-kind :initarg :db-kind :initform :base ;; openmcl 0.14.2 stores the value as list in the DSD ;; :type (or list keyword) #-openmcl :type #-openmcl keyword :documentation "The kind of DB mapping which is performed for this slot. :base indicates the slot maps to an ordinary column of the DB view. :key indicates that this slot corresponds to part of the unique keys for this view, :join indicates ... and :virtual indicates that this slot is an ordinary CLOS slot. Defaults to :base.") (db-reader :accessor view-class-slot-db-reader :initarg :db-reader :initform nil :documentation "If a string, then when reading values from the DB, the string will be used for a format string, with the only value being the value from the database. The resulting string will be used as the slot value. If a function then it will take one argument, the value from the database, and return the value that should be put into the slot.") (db-writer :accessor view-class-slot-db-writer :initarg :db-writer :initform nil :documentation "If a string, then when reading values from the slot for the DB, the string will be used for a format string, with the only value being the value of the slot. The resulting string will be used as the column value in the DB. If a function then it will take one argument, the value of the slot, and return the value that should be put into the database.") (db-type :accessor view-class-slot-db-type :initarg :db-type :initform nil :documentation "A string which will be used as the type specifier for this slots column definition in the database.") (db-constraints :accessor view-class-slot-db-constraints :initarg :db-constraints :initform nil :documentation "A keyword symbol representing a single SQL column constraint or list of such symbols.") (void-value :accessor view-class-slot-void-value :initarg :void-value :initform nil :documentation "Value to store if the SQL value is NULL. Default is NIL.") (db-info :accessor view-class-slot-db-info :initarg :db-info :documentation "Description of the join.") (specified-type :accessor specified-type :initarg specified-type :initform nil :documentation "Internal slot storing the :type specified by user.") (autoincrement-sequence :accessor view-class-slot-autoincrement-sequence :initarg :autoincrement-sequence :initform nil :documentation "A string naming the (possibly automatically generated) sequence for a slot with an :auto-increment constraint."))) (defparameter *db-info-lambda-list* '(&key join-class home-key foreign-key (key-join nil) (target-slot nil) (retrieval :immmediate) (set nil))) (defun parse-db-info (db-info-list) (destructuring-bind (&key join-class home-key key-join foreign-key (delete-rule nil) (target-slot nil) (retrieval :deferred) (set t)) db-info-list (let ((ih (make-hash-table :size 6))) (if join-class (setf (gethash :join-class ih) join-class) (error "Must specify :join-class in :db-info")) (if home-key (setf (gethash :home-key ih) home-key) (error "Must specify :home-key in :db-info")) (when delete-rule (setf (gethash :delete-rule ih) delete-rule)) (if foreign-key (setf (gethash :foreign-key ih) foreign-key) (error "Must specify :foreign-key in :db-info")) (when key-join (setf (gethash :key-join ih) t)) (when target-slot (setf (gethash :target-slot ih) target-slot)) (when set (setf (gethash :set ih) set)) (when retrieval (progn (setf (gethash :retrieval ih) retrieval) (if (eql retrieval :immediate) (setf (gethash :set ih) nil)))) ih))) (defclass view-class-direct-slot-definition (view-class-slot-definition-mixin standard-direct-slot-definition) ()) (defclass view-class-effective-slot-definition (view-class-slot-definition-mixin standard-effective-slot-definition) ()) (defmethod direct-slot-definition-class ((class standard-db-class) #+kmr-normal-dsdc &rest initargs) (declare (ignore initargs)) (find-class 'view-class-direct-slot-definition)) (defmethod effective-slot-definition-class ((class standard-db-class) #+kmr-normal-esdc &rest initargs) (declare (ignore initargs)) (find-class 'view-class-effective-slot-definition)) #+openmcl (when (not (symbol-function 'compute-class-precedence-list)) (eval (defun compute-class-precedence-list (class) (class-precedence-list class)))) #-mop-slot-order-reversed (defmethod compute-slots ((class standard-db-class)) "Need to sort order of class slots so they are the same across implementations." (let ((slots (call-next-method)) desired-sequence output-slots) (dolist (c (compute-class-precedence-list class)) (dolist (s (class-direct-slots c)) (let ((name (slot-definition-name s))) (unless (find name desired-sequence) (push name desired-sequence))))) (dolist (desired desired-sequence) (let ((slot (find desired slots :key #'slot-definition-name))) (assert slot) (push slot output-slots))) output-slots)) (defun compute-lisp-type-from-specified-type (specified-type db-constraints) "Computes the Lisp type for a user-specified type." (let ((type (cond ((consp specified-type) (let* ((first (first specified-type)) (name (etypecase first (symbol (symbol-name first)) (string first)))) (cond ((or (string-equal name "string") (string-equal name "varchar") (string-equal name "char")) 'string) (t specified-type)))) ((eq (ensure-keyword specified-type) :bigint) 'integer) ((eq (ensure-keyword specified-type) :char) 'character) ((eq (ensure-keyword specified-type) :varchar) 'string) (t specified-type)))) (if (and type (not (member :not-null (listify db-constraints)))) `(or null ,type) (or type t)))) ;; Compute the slot definition for slots in a view-class. Figures out ;; what kind of database value (if any) is stored there, generates and ;; verifies the column name. (declaim (inline delistify)) (defun delistify (list) "Some MOPs, like openmcl 0.14.2, cons attribute values in a list." (if (listp list) (car list) list)) (declaim (inline delistify-dsd)) ;; there is an :after method below too (defmethod initialize-instance :around ((obj view-class-direct-slot-definition) &rest initargs &key db-constraints db-kind type &allow-other-keys) (when (and (not db-kind) (member :primary-key (listify db-constraints))) (warn "Slot ~S constrained to be :primary-key, but not marked as :db-kind :key" (slot-definition-name obj))) (apply #'call-next-method obj 'specified-type type :type (if (and (eql db-kind :virtual) (null type)) t (compute-lisp-type-from-specified-type type db-constraints)) initargs)) (defun compute-column-name (arg) (database-identifier arg nil)) (defun %convert-db-info-to-hash (slot-def) ;; I wonder if this slot option and the previous could be merged, ;; so that :base and :key remain keyword options, but :db-kind ;; :join becomes :db-kind (:join )? (setf (slot-value slot-def 'db-info) (when (slot-boundp slot-def 'db-info) (let ((info (view-class-slot-db-info slot-def))) (etypecase info (hash-table info) (atom info) (list (cond ((and (> (length info) 1) (atom (car info))) (parse-db-info info)) ((and (= 1 (length info)) (listp (car info))) (parse-db-info (car info))) (t info)))))))) (defmethod initialize-instance :after ((obj view-class-direct-slot-definition) &key &allow-other-keys) (setf (view-class-slot-column obj) (compute-column-name obj) (view-class-slot-autoincrement-sequence obj) (dequote (view-class-slot-autoincrement-sequence obj))) (%convert-db-info-to-hash obj)) (defmethod compute-effective-slot-definition ((class standard-db-class) #+kmr-normal-cesd slot-name direct-slots) #+kmr-normal-cesd (declare (ignore slot-name)) ;; KMR: store the user-specified type and then compute ;; real Lisp type and store it (let ((dsd (car direct-slots))) (let ((esd (call-next-method))) (typecase dsd (view-class-slot-definition-mixin (setf (slot-value esd 'column) (compute-column-name dsd)) (macrolet ((safe-copy-value (name &optional default) (let ((fn (intern (format nil "~A~A" 'view-class-slot- name )))) `(setf (slot-value esd ',name) (or (when (slot-boundp dsd ',name) (delistify-dsd (,fn dsd))) ,default))))) (safe-copy-value autoincrement-sequence) (safe-copy-value db-type) (safe-copy-value void-value) (safe-copy-value db-reader) (safe-copy-value db-writer) ;; :db-kind slot value defaults to :base (store slot value in ;; database) (safe-copy-value db-kind :base) (safe-copy-value db-constraints) (safe-copy-value db-info) (%convert-db-info-to-hash esd)) (setf (specified-type esd) (delistify-dsd (specified-type dsd))) ;; In older SBCL's the type-check-function is computed at ;; defclass expansion, which is too early for the CLSQL type ;; conversion to take place. This gets rid of it. It's ugly ;; but it's better than nothing -wcp10/4/10. #+(and sbcl #.(cl:if (cl:and (cl:find-package :sb-pcl) (cl:find-symbol "%TYPE-CHECK-FUNCTION" :sb-pcl)) '(cl:and) '(cl:or))) (setf (slot-value esd 'sb-pcl::%type-check-function) nil) ) ;; all other slots (t (unless (typep esd 'view-class-effective-slot-definition) (warn "Non view-class-direct-slot object with non-view-class-effective-slot-definition in compute-effective-slot-definition") (let ((type-predicate #+openmcl (slot-value esd 'ccl::type-predicate))) #-openmcl (declare (ignore type-predicate)) #-(or clisp sbcl) (change-class esd 'view-class-effective-slot-definition #+allegro :name #+allegro (slot-definition-name dsd)) #+openmcl (setf (slot-value esd 'ccl::type-predicate) type-predicate))) ;; has no column name if it is not a database column (setf (slot-value esd 'column) nil) (setf (slot-value esd 'db-info) nil) (setf (slot-value esd 'db-kind) :virtual) (setf (specified-type esd) (slot-definition-type dsd))) ) esd))) (defun slotdefs-for-slots-with-class (slots class) (let ((result nil)) (dolist (s slots) (let ((c (slotdef-for-slot-with-class s class))) (if c (setf result (cons c result))))) result)) (defun slotdef-for-slot-with-class (slot class) (typecase slot (standard-slot-definition slot) (symbol (find-slot-by-name class slot)))) #+ignore (eval-when (:compile-toplevel :load-toplevel :execute) #+kmr-normal-cesd (setq cl:*features* (delete :kmr-normal-cesd cl:*features*)) #+kmr-normal-dsdc (setq cl:*features* (delete :kmr-normal-dsdc cl:*features*)) #+kmr-normal-esdc (setq cl:*features* (delete :kmr-normal-esdc cl:*features*)) ) (defmethod database-identifier ( (name standard-db-class) &optional database find-class-p) "the majority of this function is in expressions.lisp this is here to make loading be less painful (try-recompiles) in SBCL" (declare (ignore find-class-p)) (database-identifier (view-table name) database)) (defmethod database-identifier ((name view-class-slot-definition-mixin) &optional database find-class-p) (declare (ignore find-class-p)) (database-identifier (if (slot-boundp name 'column) (delistify-dsd (view-class-slot-column name)) (slot-definition-name name)) database)) (defun find-standard-db-class (name &aux cls) (and (setf cls (ignore-errors (find-class name))) (typep cls 'standard-db-class) cls)) (defun slots-for-possibly-normalized-class (class) "Get the slots for this class, if normalized this is only the direct slots otherwiese its all the slots" (if (normalizedp class) (ordered-class-direct-slots class) (ordered-class-slots class))) (defun key-slot-p (slot-def) "takes a slot def and returns whether or not it is a key" (eql :key (view-class-slot-db-kind slot-def))) (defun join-slot-p (slot-def) "takes a slot def and returns whether or not it is a join slot" (eql :join (view-class-slot-db-kind slot-def))) (defun join-slot-info-value (slot-def key) "Get the join-slot db-info value associated with a key" (when (join-slot-p slot-def) (let ((dbi (view-class-slot-db-info slot-def))) (when dbi (gethash key dbi))))) (defun join-slot-retrieval-method (slot-def) "if this is a join slot return the retrieval param in the db-info" (join-slot-info-value slot-def :retrieval)) (defun join-slot-class-name (slot-def) "get the join class name for a given join slot" (join-slot-info-value slot-def :join-class)) (defun join-slot-class (slot-def) "Get the join class for a given join slot" (let ((c (join-slot-class-name slot-def))) (when c (find-class c)))) (defun key-or-base-slot-p (slot-def) "takes a slot def and returns whether or not it is a key" (member (view-class-slot-db-kind slot-def) '(:key :base))) (defun direct-normalized-slot-p (class slot-name) "Is this a normalized class and if so is the slot one of our direct slots?" (setf slot-name (to-slot-name slot-name)) (and (typep class 'standard-db-class) (normalizedp class) (member slot-name (ordered-class-direct-slots class) :key #'slot-definition-name))) (defun not-direct-normalized-slot-p (class slot-name) "Is this a normalized class and if so is the slot not one of our direct slots?" (setf slot-name (to-slot-name slot-name)) (and (typep class 'standard-db-class) (normalizedp class) (not (member slot-name (ordered-class-direct-slots class) :key #'slot-definition-name)))) (defun slot-has-default-p (slot) "returns nil if the slot does not have a default constraint" (let* ((constraints (when (typep slot '(or view-class-direct-slot-definition view-class-effective-slot-definition)) (listify (view-class-slot-db-constraints slot))))) (member :default constraints))) cl-sql-6.4.1/sql/cmucl-compat.lisp0000644000175000017500000000575411335067642016025 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; FILE IDENTIFICATION ;;;; ;;;; Name: cmucl-compat.lisp ;;;; Purpose: Compatiblity library for CMUCL functions ;;;; Programmer: Kevin M. Rosenberg ;;;; Date Started: Feb 2002 ;;;; ;;;; This file, part of CLSQL, is Copyright (c) 2002-2010 by Kevin M. Rosenberg ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* (in-package #:cl-user) (defpackage #:cmucl-compat (:use #:common-lisp) (:export #:shrink-vector #:make-sequence-of-type #:result-type-or-lose #:required-argument )) (in-package #:cmucl-compat) #+(or cmu scl) (defmacro required-argument () `(ext:required-argument)) #-(or cmu scl) (defun required-argument () (error "~&A required keyword argument was not supplied")) #+(or cmu scl) (defmacro shrink-vector (vec len) `(lisp::shrink-vector ,vec ,len)) #+sbcl (defmacro shrink-vector (vec len) `(sb-kernel::shrink-vector ,vec ,len)) #-(or cmu sbcl scl) (defmacro shrink-vector (vec len) "Shrinks a vector. Optimized if vector has a fill pointer. Needs to be a macro to overwrite value of VEC." (let ((new-vec (gensym))) `(cond ((adjustable-array-p ,vec) (adjust-array ,vec ,len)) ((typep ,vec 'simple-array) (let ((,new-vec (make-array ,len :element-type (array-element-type ,vec)))) (check-type ,len fixnum) (locally (declare (optimize (speed 3) (safety 0) (space 0)) ) (dotimes (i ,len) (declare (fixnum i)) (setf (aref ,new-vec i) (aref ,vec i)))) (setq ,vec ,new-vec))) ((typep ,vec 'vector) (setf (fill-pointer ,vec) ,len) ,vec) (t (error "Unable to shrink vector ~S which is type-of ~S" ,vec (type-of ,vec))) ))) #-(or cmu scl) (defun make-sequence-of-type (type length) "Returns a sequence of the given TYPE and LENGTH." (make-sequence type length)) #+(or cmu scl) (if (fboundp 'lisp::make-sequence-of-type) (defun make-sequence-of-type (type len) (lisp::make-sequence-of-type type len)) (defun make-sequence-of-type (type len) (common-lisp::make-sequence-of-type type len))) #-(or cmu scl) (defun result-type-or-lose (type nil-ok) (unless (or type nil-ok) (error "NIL output type invalid for this sequence function")) (case type ((list cons) 'list) ((string simple-string base-string simple-base-string) 'string) (simple-vector 'simple-vector) (vector 'vector) (t (error "~S is a bad type specifier for sequence functions." type)) )) #+(or cmu scl) (defun result-type-or-lose (type nil-ok) (lisp::result-type-or-lose type nil-ok)) cl-sql-6.4.1/sql/command-object.lisp0000644000175000017500000000601612064366222016307 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; FILE IDENTIFICATION ;;;; ;;;; Name: postgresql-socket-sql.sql ;;;; Purpose: High-level PostgreSQL interface using socket ;;;; Authors: Russ Tyndall (at Acceleration.net) based on original code by ;;;; Kevin M. Rosenberg based on original code by Pierre R. Mai ;;;; Created: Sep 2009 ;;;; ;;;; ;;;; $Id$ ;;;; ;;;; This file, part of CLSQL, is Copyright (c) 2002-2007 by Kevin M. Rosenberg ;;;; and Copyright (c) 1999-2001 by Pierre R. Mai ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ;;;; ************************************************************************* (in-package #:clsql-sys) (defclass command-object () ((expression :accessor expression :initarg :expression :initform nil :documentation "query that refers to parameters using \"$1\", \"$2\", \"$n\". These match positions in the parameters list.") (parameters :accessor parameters :initarg :parameters :initform nil :documentation "list of parameters") (prepared-name :accessor prepared-name :initarg :prepared-name :initform "" :documentation "If we want this to be a prepared statement, give it a name to identify it to this session") (has-been-prepared :accessor has-been-prepared :initarg :has-been-prepared :initform nil :documentation "Have we already prepared this command object?") )) (defgeneric prepare-sql-parameter (sql-parameter) (:documentation "This method is responsible for formatting parameters as the database expects them (eg: :false is nil, nil is :null, dates are iso8601 strings)") (:method (sql-parameter) (typecase sql-parameter (null :null) (symbol (if (member sql-parameter (list :false :F)) nil (princ-to-string sql-parameter))) (clsql-sys:date (format-date nil sql-parameter :format :iso8601)) (clsql-sys:wall-time (format-time nil sql-parameter :format :iso8601)) (t sql-parameter)))) (defmethod initialize-instance :after ((o command-object) &key &allow-other-keys ) ;; Inits parameter value coersion (setf (parameters o) (parameters o))) (defmethod (setf parameters) (new (o command-object)) " This causes the semantics to match cl-sql instead of cl-postgresql " (setf (slot-value o 'parameters) (loop for p in new collecting (prepare-sql-parameter p)))) (defun reset-command-object (co) "Resets the command object to have no name and to be unprepared (This is useful if you want to run a command against a second database)" (setf (prepared-name co) "" (has-been-prepared co) nil)) (defun command-object (expression &optional parameters (prepared-name "")) (make-instance 'command-object :expression expression :parameters parameters :prepared-name prepared-name)) cl-sql-6.4.1/sql/pool.lisp0000644000175000017500000001676411616055736014420 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; FILE IDENTIFICATION ;;;; ;;;; Name: pool.lisp ;;;; Purpose: Support function for connection pool ;;;; Programmers: Kevin M. Rosenberg, Marc Battyani ;;;; Date Started: Apr 2002 ;;;; ;;;; This file, part of CLSQL, is Copyright (c) 2002-2010 by Kevin M. Rosenberg ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* (in-package #:clsql-sys) (defparameter *db-pool-max-free-connections* 4 "Threshold of free-connections in the pool before we disconnect a database rather than returning it to the pool. NIL for no limit. This is really a heuristic that should, on avg keep the free connections about this size.") (defvar *db-pool* (make-hash-table :test #'equal)) (defvar *db-pool-lock* (make-process-lock "DB Pool lock")) (defclass conn-pool () ((connection-spec :accessor connection-spec :initarg :connection-spec) (database-type :accessor pool-database-type :initarg :pool-database-type) (free-connections :accessor free-connections :initform nil) (all-connections :accessor all-connections :initform nil) (lock :accessor conn-pool-lock :initform (make-process-lock "Connection pool")))) (defun acquire-from-pool (connection-spec database-type &optional pool encoding) "Try to find a working database connection in the pool or create a new one if needed. This performs 1 query against the DB to ensure it's still valid. When possible (postgres, mssql) that query will be a reset command to put the connection back into its default state." (unless (typep pool 'conn-pool) (setf pool (find-or-create-connection-pool connection-spec database-type))) (or (loop for pconn = (with-process-lock ((conn-pool-lock pool) "Acquire") (pop (free-connections pool))) always pconn thereis ;; test if connection still valid. ;; (e.g. db reboot -> invalid connection ) (handler-case (progn (database-acquire-from-conn-pool pconn) pconn) (sql-database-error (e) ;; we could check for a specific error, ;; but, it's safer just to disconnect the pooled conn for any error ? (warn "Database connection ~S had an error while acquiring from the pool: ~S Disconnecting.~%" pconn e) ;;run database disconnect to give chance for cleanup ;;there, then remove it from the lists of connected ;;databases. (%pool-force-disconnect pconn) (with-process-lock ((conn-pool-lock pool) "remove dead conn") (setf (all-connections pool) (delete pconn (all-connections pool)))) nil))) (let ((conn (connect (connection-spec pool) :database-type (pool-database-type pool) :if-exists :new :make-default nil :encoding encoding))) (setf (conn-pool conn) pool) (with-process-lock ((conn-pool-lock pool) "new conection") (push conn (all-connections pool))) conn))) (defun release-to-pool (database &optional (pool (conn-pool database))) "Release a database connection to the pool. The backend will have a chance to do cleanup." (unless (conn-pool database) (setf (conn-pool database) pool)) (cond ;;We read the list of free-connections outside the lock. This ;;should be fine as long as that list is never dealt with ;;destructively (push and pop destructively modify the place, ;;not the list). Multiple threads getting to this test at the ;;same time might result in the free-connections getting ;;longer... meh. ((or (and *db-pool-max-free-connections* (>= (length (free-connections pool)) *db-pool-max-free-connections*))) (%pool-force-disconnect database) (with-process-lock ((conn-pool-lock pool) "Remove extra Conn") (setf (all-connections pool) (delete database (all-connections pool))))) (t ;;let it do cleanup (database-release-to-conn-pool database) (with-process-lock ((conn-pool-lock pool) "Release to pool") (push database (free-connections pool)))))) (defmethod database-acquire-from-conn-pool (database) (case (database-underlying-type database) (:postgresql (database-execute-command "RESET ALL" database)) (:mysql (database-query "SHOW ERRORS LIMIT 1" database nil nil)) (:mssql ;; rpc escape sequence since this can't be called as a normal sp. ;;http://msdn.microsoft.com/en-us/library/aa198358%28SQL.80%29.aspx (database-execute-command "{rpc sp_reset_connection}" database)) (T (database-query "SELECT 1;" database '(integer) nil)))) (defmethod database-release-to-conn-pool (database) (case (database-underlying-type database) (:postgresql (ignore-errors ;;http://www.postgresql.org/docs/current/static/sql-discard.html ;;this was introduced relatively recently, wrap in ignore-errors ;;so that it doesn't choke older versions. (database-execute-command "DISCARD ALL" database))))) (defun clear-conn-pool (pool) "Be careful this function will disconnect connections without regard to whether another thread is actively using them." (with-process-lock ((conn-pool-lock pool) "Clear pool") (mapc #'%pool-force-disconnect (all-connections pool)) (setf (all-connections pool) nil (free-connections pool) nil)) nil) (defun find-or-create-connection-pool (connection-spec database-type) "Find connection pool in hash table, creates a new connection pool if not found" (let ((key (list connection-spec database-type))) (with-process-lock (*db-pool-lock* "Find-or-create connection") (or (gethash key *db-pool*) (setf (gethash key *db-pool*) (make-instance 'conn-pool :connection-spec connection-spec :pool-database-type database-type)))))) (defun disconnect-pooled (&optional clear) "Disconnects all connections in the pool. When clear, also deletes the pool objects." (with-process-lock (*db-pool-lock* "Disconnect pooled") (maphash #'(lambda (key conn-pool) (declare (ignore key)) (clear-conn-pool conn-pool)) *db-pool*) (when clear (clrhash *db-pool*))) t) (defun %pool-force-disconnect (database) "Force disconnection of a connection from the pool." ;;so it isn't just returned to pool (setf (conn-pool database) nil) ;; disconnect may error if remote side closed connection (ignore-errors (disconnect :database database))) ;(defun pool-start-sql-recording (pool &key (types :command)) ; "Start all stream in the pool recording actions of TYPES" ; (dolist (con (pool-connections pool)) ; (start-sql-recording :type types ; :database (connection-database con)))) ;(defun pool-stop-sql-recording (pool &key (types :command)) ; "Start all stream in the pool recording actions of TYPES" ; (dolist (con (pool-connections pool)) ; (stop-sql-recording :type types ; :database (connection-database con)))) ;(defmacro with-database-connection (pool &body body) ; `(let ((connection (obtain-connection ,pool)) ; (results nil)) ; (unwind-protect ; (with-database ((connection-database connection)) ; (setq results (multiple-value-list (progn ,@body)))) ; (release-connection connection)) ; (values-list results))) cl-sql-6.4.1/sql/utils.lisp0000644000175000017500000004071612134025465014571 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; FILE IDENTIFICATION ;;;; ;;;; Name: utils.lisp ;;;; Purpose: SQL utility functions ;;;; Programmer: Kevin M. Rosenberg ;;;; Date Started: Mar 2002 ;;;; ;;;; This file, part of CLSQL, is Copyright (c) 2002-2010 by Kevin M. Rosenberg ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* (in-package #:clsql-sys) (defmacro defaulting (&rest place-value-plist) "for places and values (as an &rest plist) if place-n is null set it to value-n" `(progn ,@(loop for (place value . rest) on place-value-plist by #'cddr collect `(unless ,place (setf ,place ,value))))) (defmacro pop-n (place &optional (n 1)) "pops n items off of a list in place and returns their values in a new list if n > the length of the list in place, then we return the full list, setting the place to nil" `(loop repeat ,n while ,place collect (pop ,place))) (defun %get-int (v) (etypecase v (string (parse-integer v :junk-allowed t)) (integer v) (number (truncate v)))) (defun dequote (it) (if (and (listp it) (eql (first it) 'quote)) (second it) it)) (defvar +whitespace-chars+ '(#\space #\tab #\newline #\return ;; Tested: sbcl unicode, allegrocl, openmcl,clisp use #\no-break_space ;; lispworks uses #\no-break-space ;; sbcl non-unicode doesn't support no break space ;; AllegroCL 8-bit strings don't fail on reading #\no-break_space, ;; but can't represent such a character ;; CMUCL errors when trying to read #\no-break_space #+(and lispworks unicode) #\no-break-space #+(or (and sbcl sb-unicode) (and allegro ics) (and clisp i18n) (and openmcl openmcl-unicode-strings)) #\no-break_space ) "List of whitespace characters for this lisp implementation.") (defun number-to-sql-string (num) (etypecase num (integer (princ-to-string num)) (rational (float-to-sql-string (coerce num 'double-float))) (number (float-to-sql-string num)))) (defun float-to-sql-string (num) "Convert exponent character for SQL" (let ((str (write-to-string num :readably t))) (declare (type string str)) (cond ((find #\f str) (substitute #\e #\f str)) ((find #\d str) (substitute #\e #\d str)) ((find #\l str) (substitute #\e #\l str)) ((find #\s str) (substitute #\e #\S str)) ((find #\F str) (substitute #\e #\F str)) ((find #\D str) (substitute #\e #\D str)) ((find #\L str) (substitute #\e #\L str)) ((find #\S str) (substitute #\e #\S str)) (t str)))) (defun sql-escape (identifier) "Change hyphens to underscores, ensure string" (let ((unescaped (etypecase identifier (symbol (symbol-name identifier)) (string identifier)))) (substitute #\_ #\- unescaped))) #+lispworks (defvar +lw-has-without-preemption+ #+lispworks6 nil #-lispworks6 t) #+lispworks (defvar +lw-global-lock+ (unless +lw-has-without-preemption+ (mp:make-lock :name "CLSQL" :important-p nil :safep t :recursivep nil :sharing t))) (defmacro without-interrupts (&body body) #+allegro `(mp:without-scheduling ,@body) #+clisp `(progn ,@body) #+cmu `(system:without-interrupts ,@body) #+lispworks (if +lw-has-without-preemption+ `(mp:without-preemption ,@body) `(mp:with-exclusive-lock (+lw-global-lock+) ,@body)) #+openmcl `(ccl:without-interrupts ,@body) #+sbcl `(sb-sys::without-interrupts ,@body)) (defun make-process-lock (name) #+allegro (mp:make-process-lock :name name) #+cmu (mp:make-lock name) #+lispworks (mp:make-lock :name name) #+openmcl (ccl:make-lock name) #+sb-thread (sb-thread:make-mutex :name name) #+scl (thread:make-lock name) #-(or allegro cmu lispworks openmcl sb-thread scl) (declare (ignore name)) #-(or allegro cmu lispworks openmcl sb-thread scl) nil) (defmacro with-process-lock ((lock desc) &body body) #+(or cmu allegro lispworks openmcl sb-thread) (declare (ignore desc)) #+(or allegro cmu lispworks openmcl sb-thread) (let ((l (gensym))) `(let ((,l ,lock)) #+allegro (mp:with-process-lock (,l) ,@body) #+cmu (mp:with-lock-held (,l) ,@body) #+openmcl (ccl:with-lock-grabbed (,l) ,@body) #+lispworks (mp:with-lock (,l) ,@body) #+sb-thread (sb-thread:with-recursive-lock (,l) ,@body) )) #+scl `(thread:with-lock-held (,lock ,desc) ,@body) #-(or cmu allegro lispworks openmcl sb-thread scl) (declare (ignore lock desc)) #-(or cmu allegro lispworks openmcl sb-thread scl) `(progn ,@body)) (defun sql-escape-quotes (s) "Escape quotes for SQL string writing" (substitute-string-for-char s #\' "''")) (defun substitute-string-for-char (procstr match-char subst-str) "Substitutes a string for a single matching character of a string" (when procstr (locally (declare (type string procstr)) (let ((pos (position match-char procstr))) (if pos (concatenate 'string (subseq procstr 0 pos) subst-str (substitute-string-for-char (subseq procstr (1+ pos)) match-char subst-str)) procstr))))) (defun position-char (char string start max) "From KMRCL." (declare (optimize (speed 3) (safety 0) (space 0)) (fixnum start max) (simple-string string)) (do* ((i start (1+ i))) ((= i max) nil) (declare (fixnum i)) (when (char= char (schar string i)) (return i)))) (defun delimited-string-to-list (string &optional (separator #\space) skip-terminal) "Split a string with delimiter, from KMRCL." (declare (optimize (speed 3) (safety 0) (space 0) (compilation-speed 0)) (type string string) (type character separator)) (do* ((len (length string)) (output '()) (pos 0) (end (position-char separator string pos len) (position-char separator string pos len))) ((null end) (if (< pos len) (push (subseq string pos) output) (when (or (not skip-terminal) (zerop len)) (push "" output))) (nreverse output)) (declare (type fixnum pos len) (type (or null fixnum) end)) (push (subseq string pos end) output) (setq pos (1+ end)))) (defun string-to-list-connection-spec (str) (declare (type string str)) (let ((at-pos (position-char #\@ str 0 (length str)))) (cond ((and at-pos (> (length str) at-pos)) ;; Connection spec is SQL*NET format (cons (subseq str (1+ at-pos)) (delimited-string-to-list (subseq str 0 at-pos) #\/))) (t (delimited-string-to-list str #\/))))) #+allegro (eval-when (:compile-toplevel :load-toplevel :execute) (unless (find-package '#:excl.osi) (require 'osi))) (defun command-output (control-string &rest args) ;; Concatenates output and error since Lispworks combines ;; these, thus CLSQL can't depend upon separate results (multiple-value-bind (output error status) (apply #'%command-output control-string args) (values (concatenate 'string (if output output "") (if error error "")) status))) (defun read-stream-to-string (in) (with-output-to-string (out) (let ((eof (gensym))) (do ((line (read-line in nil eof) (read-line in nil eof))) ((eq line eof)) (format out "~A~%" line))))) ;; From KMRCL (defun %command-output (control-string &rest args) "Interpolate ARGS into CONTROL-STRING as if by FORMAT, and synchronously execute the result using a Bourne-compatible shell, returns (VALUES string-output error-output exit-status)" (let ((command (apply #'format nil control-string args))) #+sbcl (let* ((process (sb-ext:run-program "/bin/sh" (list "-c" command) :input nil :output :stream :error :stream)) (output (read-stream-to-string (sb-impl::process-output process))) (error (read-stream-to-string (sb-impl::process-error process)))) (close (sb-impl::process-output process)) (close (sb-impl::process-error process)) (values output error (sb-impl::process-exit-code process))) #+(or cmu scl) (let* ((process (ext:run-program "/bin/sh" (list "-c" command) :input nil :output :stream :error :stream)) (output (read-stream-to-string (ext::process-output process))) (error (read-stream-to-string (ext::process-error process)))) (close (ext::process-output process)) (close (ext::process-error process)) (values output error (ext::process-exit-code process))) #+allegro (multiple-value-bind (output error status) (excl.osi:command-output command :whole t) (values output error status)) #+lispworks ;; BUG: Lispworks combines output and error streams (let ((output (make-string-output-stream))) (unwind-protect (let ((status (system:call-system-showing-output command :shell-type "/bin/sh" :output-stream output))) (values (get-output-stream-string output) nil status)) (close output))) #+clisp ;; BUG: CLisp doesn't allow output to user-specified stream (values nil nil (ext:run-shell-command command :output :terminal :wait t)) #+openmcl (let* ((process (ccl:run-program "/bin/sh" (list "-c" command) :input nil :output :stream :error :stream :wait t)) (output (read-stream-to-string (ccl::external-process-output-stream process))) (error (read-stream-to-string (ccl::external-process-error-stream process)))) (close (ccl::external-process-output-stream process)) (close (ccl::external-process-error-stream process)) (values output error (nth-value 1 (ccl::external-process-status process)))) #-(or openmcl clisp lispworks allegro scl cmu sbcl) (error "COMMAND-OUTPUT not implemented for this Lisp") )) ;; From KMRCL (defmacro in (obj &rest choices) (let ((insym (gensym))) `(let ((,insym ,obj)) (or ,@(mapcar #'(lambda (c) `(eql ,insym ,c)) choices))))) ;; From KMRCL (defun substitute-char-string (procstr match-char subst-str) "Substitutes a string for a single matching character of a string" (substitute-chars-strings procstr (list (cons match-char subst-str)))) (defun replaced-string-length (str repl-alist) (declare (simple-string str) (optimize (speed 3) (safety 0) (space 0))) (do* ((i 0 (1+ i)) (orig-len (length str)) (new-len orig-len)) ((= i orig-len) new-len) (declare (fixnum i orig-len new-len)) (let* ((c (char str i)) (match (assoc c repl-alist :test #'char=))) (declare (character c)) (when match (incf new-len (1- (length (the simple-string (cdr match))))))))) (defun substitute-chars-strings (str repl-alist) "Replace all instances of a chars with a string. repl-alist is an assoc list of characters and replacement strings." (declare (simple-string str) (optimize (speed 3) (safety 0) (space 0))) (do* ((orig-len (length str)) (new-string (make-string (replaced-string-length str repl-alist))) (spos 0 (1+ spos)) (dpos 0)) ((>= spos orig-len) new-string) (declare (fixnum spos dpos) (simple-string new-string)) (let* ((c (char str spos)) (match (assoc c repl-alist :test #'char=))) (declare (character c)) (if match (let* ((subst (cdr match)) (len (length subst))) (declare (fixnum len) (simple-string subst)) (dotimes (j len) (declare (fixnum j)) (setf (char new-string dpos) (char subst j)) (incf dpos))) (progn (setf (char new-string dpos) c) (incf dpos)))))) (defun getenv (var) "Return the value of the environment variable." #+allegro (sys::getenv (string var)) #+clisp (ext:getenv (string var)) #+(or cmu scl) (cdr (assoc (string var) ext:*environment-list* :test #'equalp :key #'string)) #+lispworks (lw:environment-variable (string var)) #+mcl (ccl::getenv var) #+sbcl (sb-ext:posix-getenv var)) (eval-when (:compile-toplevel :load-toplevel :execute) (when (char= #\a (schar (symbol-name '#:a) 0)) (pushnew :clsql-lowercase-reader *features*))) (defun symbol-name-default-case (str) #-clsql-lowercase-reader (string-upcase str) #+clsql-lowercase-reader (string-downcase str)) (defun convert-to-db-default-case (str database) (if database (case (db-type-default-case (database-underlying-type database)) (:upper (string-upcase str)) (:lower (string-downcase str)) (t str)) ;; Default CommonSQL behavior is to upcase strings (string-upcase str))) (defun ensure-keyword (name) "Returns keyword for a name." (etypecase name (keyword name) (string (nth-value 0 (intern (symbol-name-default-case name) :keyword))) (symbol (nth-value 0 (intern (symbol-name name) :keyword))))) (eval-when (:compile-toplevel :load-toplevel :execute) (setq cl:*features* (delete :clsql-lowercase-reader cl:*features*))) (defun replace-all (string part replacement &key (test #'char=) stream) "Returns a new string in which all the occurences of the part is replaced with replacement. [FROM http://cl-cookbook.sourceforge.net/strings.html#manip]" (let ((out (or stream (make-string-output-stream)))) (loop with part-length = (length part) for old-pos = 0 then (+ pos part-length) for pos = (search part string :start2 old-pos :test test) do (write-string string out :start old-pos :end (or pos (length string))) when pos do (write-string replacement out) while pos) (unless stream (get-output-stream-string out)))) (defun filter-plist (plist &rest keys-to-remove) "Returns a copy of the given plist with indicated key-value pairs removed. keys are searched with #'MEMBER" (declare (dynamic-extent keys-to-remove)) (when plist (loop for (k v . rest) = plist then rest unless (member k keys-to-remove) collect k and collect v while rest))) (defmacro make-weak-hash-table (&rest args) "Creates a weak hash table for use in a cache." `(progn ;;NB: These are generally used for caches that may not have an alternate ;;clearing mechanism. If you are on an implementation that doesn't support ;;weak hash tables then you're memory may accumulate. #-(or sbcl allegro clisp lispworks ccl) (warn "UNSAFE! use of weak hash on implementation without support. (see clsql/sql/utils.lisp to add)") (make-hash-table #+allegro :values #+allegro :weak #+clisp :weak #+clisp :value #+lispworks :weak-kind #+lispworks :value #+sbcl :weakness #+sbcl :value #+ccl :weak #+ccl :value ,@args) )) (defun to-slot-name (slot) "try to turn what we got representing the slot into a slot name" (etypecase slot (symbol slot) (slot-definition (slot-definition-name slot)))) (defun to-class (it) (etypecase it (class it) (symbol (find-class it)) (standard-object (class-of it)))) (defun to-class-name (o) (etypecase o (symbol o) (standard-class (class-name o)) (standard-object (class-name (class-of o))))) (defun easy-slot-value (obj slot) "like slot-value except it accepts slot-names or defs and returns nil when the slot is unbound" (let ((n (to-slot-name slot))) (when (and obj (slot-boundp obj n)) (slot-value obj n)))) (defun (setf easy-slot-value) (new obj slot) "like slot-value except it accepts slot-names or defs" (setf (slot-value obj (to-slot-name slot)) new)) (defun delist-if-single (x) "if this is a single item in a list return it" (if (and (listp x) (= 1 (length x))) (first x) x)) cl-sql-6.4.1/sql/package.lisp0000644000175000017500000004065012064366222015022 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; FILE IDENTIFICATION ;;;; ;;;; Name: package.lisp ;;;; Purpose: Package definition for SQL interface ;;;; ;;;; This file is part of CLSQL. ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* (in-package #:cl-user) ;;;; This file makes the required package definitions for CLSQL's ;;;; core packages. (eval-when (:compile-toplevel :load-toplevel :execute) #+sbcl (if (find-package 'sb-mop) (pushnew :clsql-sbcl-mop cl:*features*) (pushnew :clsql-sbcl-pcl cl:*features*)) #+cmu (if (eq (symbol-package 'pcl:find-class) (find-package 'common-lisp)) (pushnew :clsql-cmucl-mop cl:*features*) (pushnew :clsql-cmucl-pcl cl:*features*))) (eval-when (:compile-toplevel :load-toplevel :execute) (defpackage #:clsql-sys (:use #:common-lisp #+clsql-sbcl-mop #:sb-mop #+clsql-cmucl-mop #:mop #+allegro #:mop #+clisp #:clos #+lispworks #:clos #+scl #:clos #+openmcl #:openmcl-mop) #+allegro (:shadowing-import-from #:excl) #+clisp (:shadowing-import-from #:clos) #+lispworks (:shadowing-import-from #:clos) #+clsql-sbcl-mop (:shadowing-import-from #:sb-pcl #:generic-function-lambda-list) #+clsql-sbcl-pcl (:shadowing-import-from #:sb-pcl #:name #:class-direct-slots #:class-of #:class-name #:class-slots #:find-class #:slot-boundp #:standard-class #:slot-definition-name #:finalize-inheritance #:standard-direct-slot-definition #:standard-effective-slot-definition #:validate-superclass #:direct-slot-definition-class #:compute-effective-slot-definition #:effective-slot-definition-class #:slot-value-using-class #:class-prototype #:generic-function-method-class #:intern-eql-specializer #:make-method-lambda #:generic-function-lambda-list #:class-precedence-list #:slot-definition-type #:class-direct-superclasses #:compute-class-precedence-list) #+clsql-cmucl-mop (:shadowing-import-from #:pcl #:generic-function-lambda-list) #+clsql-cmucl-pcl (:shadowing-import-from #:pcl #:class-direct-slots #:name #:class-of #:class-name #:class-slots #:find-class #:standard-class #:slot-boundp #:slot-definition-name #:finalize-inheritance #:standard-direct-slot-definition #:standard-effective-slot-definition #:validate-superclass #:direct-slot-definition-class #:effective-slot-definition-class #:compute-effective-slot-definition #:slot-value-using-class #:class-prototype #:generic-function-method-class #:intern-eql-specializer #:make-method-lambda #:generic-function-lambda-list #:class-precedence-list #:slot-definition-type #:class-direct-superclasses #:compute-class-precedence-list) #+scl (:shadowing-import-from #:clos #:class-prototype ;; note: make-method-lambda is not fbound ) (:export ;; "Private" exports for use by interface packages #:check-connection-spec #:database-initialize-database-type #:database-type-load-foreign #:database-connect #:database-disconnect #:database-reconnect #:database-query #:database-execute-command #:database-create-sequence #:database-drop-sequence #:database-sequence-next #:database-set-sequence-position #:database-query-result-set #:database-dump-result-set #:database-store-next-row #:database-list-tables #:database-list-tables-and-sequences #:database-table-exists-p #:database-list-views #:database-view-exists-p #:database-list-indexes #:database-list-table-indexes #:database-index-exists-p #:database-list-sequences #:database-sequence-last #:database-sequence-exists-p #:database-last-auto-increment-id #:database-list-attributes #:database-attribute-type #:database-type-library-loaded #:database-create #:database-destroy #:database-probe #:database-list #:database-acquire-from-conn-pool #:database-release-to-conn-pool #:db-backend-has-create/destroy-db? #:db-type-has-views? #:db-type-has-bigint? #:db-type-has-union? #:db-type-has-prepared-stmt? #:db-type-has-subqueries? #:db-type-has-boolean-where? #:db-type-transaction-capable? #:db-type-has-fancy-math? #:db-type-default-case #:db-type-use-column-on-drop-index? #:db-type-use-fully-qualified-column-on-drop-index? #:db-type-has-intersect? #:db-type-has-except? #:db-type-has-auto-increment? #:database-underlying-type #:database-get-type-specifier #:read-sql-value #:database-output-sql-as-type #:*loaded-database-types* #:reload-database-types #:is-database-open #:*db-pool-max-free-connections* ;; Large objects #:database-create-large-object #:database-write-large-object #:database-read-large-object #:database-delete-large-object #:create-large-object #:write-large-object #:read-large-object #:delete-large-object ;; Prepared statments #:database-prepare #:database-run-prepared #:database-bind-parameter #:database-free-prepared ;; accessors for database class #:name #:connection-spec #:transaction #:transaction-level #:conn-pool #:command-recording-stream #:result-recording-stream #:record-caches #:view-classes #:database-state #:attribute-cache #:database-autocommit #:encoding ;; utils.lisp #:without-interrupts #:make-process-lock #:with-process-lock #:command-output #:symbol-name-default-case #:convert-to-db-default-case #:ensure-keyword #:getenv #:number-to-sql-string #:float-to-sql-string #:sql-escape-quotes #:sql-escape #:in ;; Command-object.lisp #:expression #:parameters #:prepare-sql-parameter #:prepared-name #:has-been-prepared #:command-object #:reset-command-object ;; Generic backends #:generic-postgresql-database #:generic-odbc-database ;; Subclasses of sql-expresssion (expressions.lisp) #:sql-function-exp #:sql-value-exp #:sql-set-exp #:sql-query-modifier-exp #:sql-relational-exp #:sql-upcase-like #:sql-assignment-exp #:sql-typecast-exp #:sql-between-exp #:sql-ident #:sql-ident-attribute #:sql-ident-table . ;; Shared exports for re-export by CLSQL package. #1=( ;; foreign library loading #:*foreign-library-search-paths* #:push-library-path ;; Condition system (conditions.lisp) #:sql-user-error #:sql-database-error #:sql-database-data-error #:sql-connection-error #:sql-temporary-error #:sql-timeout-error #:sql-fatal-error #:sql-error-error-id #:sql-error-secondary-error-id #:sql-error-database-message ;; CLSQL Extensions #:sql-condition #:sql-error #:sql-warning #:sql-database-warning #:sql-error-database #:sql-error-database-type #:sql-error-connection-spec #:sql-error-expression #:sql-warning-database #:sql-user-error-message #:*backend-warning-behavior* ;; Connection/initialisation (base-classes.lisp, database.lisp, ;; initialize.lisp) #:*default-database-type* #:*default-database* #:*initialized-database-types* #:initialize-database-type #:connect #:disconnect #:*connect-if-exists* #:connected-databases #:database #:database-name #:reconnect #:find-database #:status ;; CLSQL Extensions #:database-name-from-spec #:database-type #:with-database #:with-default-database #:disconnect-pooled #:list-databases #:create-database #:destroy-database #:probe-database ;; I/O Recording (recording.lisp) #:add-sql-stream #:delete-sql-stream #:list-sql-streams #:sql-recording-p #:sql-stream #:start-sql-recording #:stop-sql-recording ;; FDDL (fddl.lisp) #:create-table #:drop-table #:list-tables #:table-exists-p #:list-attributes #:attribute-type #:list-attribute-types #:create-view #:drop-view #:create-index #:drop-index ;; CLSQL Extensions #:truncate-database #:list-views #:view-exists-p #:list-indexes #:index-exists-p #:create-sequence #:drop-sequence #:list-sequences #:sequence-exists-p #:sequence-next #:sequence-last #:set-sequence-position #:*old-sequence-names* ;; FDML (fdml.lisp) #:select #:cache-table-queries #:*cache-table-queries-default* #:delete-records #:insert-records #:update-records #:execute-command #:query #:print-query #:do-query #:map-query #:loop ;; CLSQL Extensions #:prepare-sql #:bind-parameter #:run-prepared-sql #:free-prepared-sql ;; Transaction handling (transaction.lisp) #:with-transaction #:commit #:rollback ;; CLSQL Extensions #:add-transaction-commit-hook #:add-transaction-rollback-hook #:start-transaction #:in-transaction-p #:set-autocommit ;; OODDL (ooddl.lisp) #:standard-db-object #:def-view-class #:create-view-from-class #:drop-view-from-class #:list-classes #:universal-time ;; CLSQL Extensions #:view-table #:bigint #:varchar #:generalized-boolean #:mediumint #:smallint #:tinyint #:*default-string-length* ;; OODML (oodml.lisp) #:instance-refreshed #:update-objects-joins #:*default-update-objects-max-len* #:*default-caching* #:update-slot-from-record #:update-instance-from-records #:update-records-from-instance #:update-record-from-slot #:update-record-from-slots #:delete-instance-records ;; CLSQL Extensions #:*db-auto-sync* #:write-instance-to-stream #:read-instance-from-stream ;; Symbolic SQL Syntax (syntax.lisp) #:sql #:sql-expression #:sql-operation #:sql-operator #:disable-sql-reader-syntax #:enable-sql-reader-syntax #:locally-disable-sql-reader-syntax #:locally-enable-sql-reader-syntax #:restore-sql-reader-syntax-state #:file-enable-sql-reader-syntax ;; SQL operations (operations.lisp) #:sql-query #:sql-object-query #:sql-any #:sql-some #:sql-all #:sql-not #:sql-union #:sql-intersect #:sql-minus #:sql-except #:sql-order-by #:sql-null #:sql-* #:sql-+ #:sql-/ #:sql-- #:sql-like #:sql-and #:sql-or #:sql-in #:sql-substr #:sql-concat-op #:sql-= #:sql-< #:sql-> #:sql->= #:sql-<= #:sql-<> #:sql-count #:sql-max #:sql-min #:sql-avg #:sql-sum #:sql-function #:sql-between #:sql-distinct #:sql-nvl #:sql-slot-value #:sql-userenv ;; CLSQL Extensions #:sql-concat #:sql-substring #:sql-limit #:sql-group-by #:sql-having #:sql-not-null #:sql-exists #:sql-uplike #:sql-is #:sql-== #:sql-the #:sql-coalesce #:sql-view-class ;; Time handling (time.lisp) #:bad-component #:current-day #:current-month #:current-year #:day-duration #:db-timestring #:db-datestring #:decode-duration #:decode-time #:decode-date #:duration #:duration+ #:duration< #:duration<= #:duration= #:duration> #:duration>= #:duration-day #:duration-hour #:duration-minute #:duration-month #:duration-second #:duration-year #:duration-reduce #:duration-timestring #:extract-roman #:format-duration #:format-time #:format-date #:get-time #:get-date #:utime->time #:interval-clear #:interval-contained #:interval-data #:interval-edit #:interval-end #:interval-match #:interval-push #:interval-relation #:interval-start #:interval-type #:make-duration #:make-interval #:make-time #:make-date #:merged-time #:midnight #:month-name #:parse-date-time #:parse-timestring #:parse-datestring #:parse-yearstring #:print-date #:roll #:roll-to #:time #:time+ #:time- #:time-by-adding-duration #:time-compare #:time-difference #:time-dow #:time-element #:time-max #:time-min #:time-mjd #:time-msec #:time-p #:time-sec #:time-well-formed #:time-ymd #:time< #:time<= #:time= #:time> #:time>= #:date #:date+ #:date- #:date-difference #:date-compare #:date-dow #:date-element #:date-max #:date-min #:date-mjd #:date-p #:date-ymd #:date< #:date<= #:date= #:date> #:date>= #:timezone #:universal-time #:wall-time #:wall-timestring #:week-containing #:gregorian-to-mjd #:mjd-to-gregorian #:iso-timestring )) (:documentation "This is the INTERNAL SQL-Interface package of CLSQL.")) (defpackage #:clsql (:use #:common-lisp) (:import-from #:clsql-sys . #1#) (:export . #1#) (:documentation "This is the user package with CLSQL symbols.")) (defpackage #:clsql-user (:use #:common-lisp) (:import-from #:clsql-sys . #1#) (:export . #1#) (:documentation "This is the user package with CLSQL symbols.")) ;; This is from USQL's pcl-patch #+(or clsql-sbcl-pcl clsql-cmucl-pcl) (progn ;; Note that this will no longer required for cmucl as of version 19a. (in-package #+cmu :pcl #+sbcl :sb-pcl) (defmacro pv-binding1 ((pv calls pv-table-symbol pv-parameters slot-vars) &body body) `(pv-env (,pv ,calls ,pv-table-symbol ,pv-parameters) (let (,@(mapcar #'(lambda (slot-var p) `(,slot-var (get-slots-or-nil ,p))) slot-vars pv-parameters)) ,@(mapcar #'(lambda (slot-var) `(declare (ignorable ,slot-var))) slot-vars) ,@body)))) ;; see http://thread.gmane.org/gmane.lisp.lispworks.general/681 #+lispworks (setf *packages-for-warn-on-redefinition* (delete "SQL" *packages-for-warn-on-redefinition* :test 'string=)) #+sbcl (if (find-package 'sb-mop) (setq cl:*features* (delete :clsql-sbcl-mop cl:*features*)) (setq cl:*features* (delete :clsql-sbcl-pcl cl:*features*))) #+cmu (if (find-package 'mop) (setq cl:*features* (delete :clsql-cmucl-mop cl:*features*)) (setq cl:*features* (delete :clsql-cmucl-pcl cl:*features*))) ) ;eval-when cl-sql-6.4.1/CONTRIBUTORS0000644000175000017500000000146711330654316013621 0ustar kevinkevinCLSQL Contributors ------------------ Kevin Rosenberg (main author CLSQL) Marcus Pearce (initial port UncommonSQL, co-developer of CLSQL version 3.0) Pierre Mai (original author MaiSQL from which CLSQL was based) Aurelio Bignoli (SQLite backend) Marc Battyani (Large object support for postgresql, initial connection pool code) Nathan Bird (sponsored by http://www.acceleration.net/programming/) USQL Contributors ----------------- This is a list of those individuals who have contributed in some way or other to Uncommonsql. The sources of the attributions are CVS annotation, patch submission, and original authorship, write us if we've missed anybody. Jesse Bouwman Craig Brozefsky Sean Champ Matthew Danish Adam Di Carlo Lyn Headley John Krug Pierre Mai (original author) Christopher J. Vogt cl-sql-6.4.1/db-sqlite/0000755000175000017500000000000012134026703013611 5ustar kevinkevincl-sql-6.4.1/db-sqlite/sqlite-sql.lisp0000644000175000017500000003342611335067642016621 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; FILE IDENTIFICATION ;;;; ;;;; Name: sqlite-sql.lisp ;;;; Purpose: High-level SQLite interface ;;;; Authors: Aurelio Bignoli, Kevin Rosenberg, Marcus Pearce ;;;; Created: Aug 2003 ;;;; ;;;; This file, part of CLSQL, is Copyright (c) 2003 by Aurelio Bignoli and ;;;; Copyright (c) 2003-2010 by Kevin Rosenberg and Marcus Pearce. ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* (in-package #:clsql-sqlite) (defclass sqlite-database (database) ((sqlite-db :initarg :sqlite-db :accessor sqlite-db))) (defmethod database-type ((database sqlite-database)) :sqlite) (defmethod database-initialize-database-type ((database-type (eql :sqlite))) t) (defun check-sqlite-connection-spec (connection-spec) (check-connection-spec connection-spec :sqlite (name))) (defmethod database-name-from-spec (connection-spec (database-type (eql :sqlite))) (check-sqlite-connection-spec connection-spec) (first connection-spec)) (defmethod database-connect (connection-spec (database-type (eql :sqlite))) (check-sqlite-connection-spec connection-spec) (handler-case (make-instance 'sqlite-database :name (database-name-from-spec connection-spec :sqlite) :database-type :sqlite :connection-spec connection-spec :sqlite-db (sqlite:sqlite-open (first connection-spec))) (sqlite:sqlite-error (err) (error 'sql-connection-error :database-type database-type :connection-spec connection-spec :error-id (sqlite:sqlite-error-code err) :message (sqlite:sqlite-error-message err))))) (defmethod database-disconnect ((database sqlite-database)) (sqlite:sqlite-close (sqlite-db database)) (setf (sqlite-db database) nil) t) (defmethod database-execute-command (sql-expression (database sqlite-database)) (handler-case (multiple-value-bind (data row-n col-n) (sqlite:sqlite-get-table (sqlite-db database) sql-expression) (sqlite:sqlite-free-table data) (unless (= row-n 0) (error 'sql-warning :format-control "Result set not empty: ~@(~A~) row~:P, ~@(~A~) column~:P " :format-arguments (list row-n col-n)))) (sqlite:sqlite-error (err) (error 'sql-database-data-error :database database :expression sql-expression :error-id (sqlite:sqlite-error-code err) :message (sqlite:sqlite-error-message err)))) t) (defstruct sqlite-result-set (vm (sqlite:make-null-vm) :type sqlite:sqlite-vm-pointer) (first-row (sqlite:make-null-row) :type sqlite:sqlite-row-pointer-type) (col-names (sqlite:make-null-row) :type sqlite:sqlite-row-pointer-type) (result-types nil) (n-col 0 :type fixnum)) (defmethod database-query (query-expression (database sqlite-database) result-types field-names) (declare (optimize (speed 3) (safety 0) (debug 0) (space 0))) (handler-case (let ((vm (sqlite:sqlite-compile (sqlite-db database) query-expression)) (rows '()) (col-names '())) (unwind-protect ;; Read the first row to get column number and names. (multiple-value-bind (n-col new-row sqlite-col-names) (sqlite:sqlite-step vm) (declare (type sqlite:sqlite-row-pointer-type new-row)) (when (> n-col 0) (when field-names (setf col-names (loop for i from 0 below n-col collect (sqlite:sqlite-aref sqlite-col-names i (encoding database))))) (let ((canonicalized-result-types (canonicalize-result-types result-types n-col sqlite-col-names))) (flet ((extract-row-data (row) (declare (type sqlite:sqlite-row-pointer-type row)) (loop for i from 0 below n-col collect (clsql-uffi:convert-raw-field (sqlite:sqlite-raw-aref row i) (nth i canonicalized-result-types) :encoding (encoding database))))) (push (extract-row-data new-row) rows) ;; Read subsequent rows. (do () (nil) (multiple-value-bind (n-col new-row) (sqlite:sqlite-step vm) (declare (type sqlite:sqlite-row-pointer-type new-row)) (if (> n-col 0) (push (extract-row-data new-row) rows) (return)))))))) (sqlite:sqlite-finalize vm)) (values (nreverse rows) col-names)) (sqlite:sqlite-error (err) (error 'sql-database-data-error :database database :expression query-expression :error-id (sqlite:sqlite-error-code err) :message (sqlite:sqlite-error-message err))))) (defmethod database-query-result-set ((query-expression string) (database sqlite-database) &key result-types full-set) (let ((vm nil)) (handler-case (progn (setf vm (sqlite:sqlite-compile (sqlite-db database) query-expression)) ;;; To obtain column number/datatypes we have to read the first row. (multiple-value-bind (n-col cols col-names) (sqlite:sqlite-step vm) (declare (type sqlite:sqlite-row-pointer-type cols)) (let ((result-set (make-sqlite-result-set :vm vm :first-row cols :n-col n-col :col-names col-names :result-types (canonicalize-result-types result-types n-col col-names)))) (if full-set (values result-set n-col nil) (values result-set n-col))))) (sqlite:sqlite-error (err) (progn (when vm ;; The condition was thrown by sqlite-step, vm must be ;; deallocated. (ignore-errors (sqlite:sqlite-finalize vm))) (error 'sql-database-data-error :database database :expression query-expression :error-id (sqlite:sqlite-error-code err) :message (sqlite:sqlite-error-message err))11))))) (defun canonicalize-result-types (result-types n-col col-names) (when result-types (let ((raw-types (if (eq :auto result-types) (loop for j from n-col below (* 2 n-col) collect (ensure-keyword (sqlite:sqlite-aref col-names j))) result-types))) (loop for type in raw-types collect (case type ((:int :integer :tinyint) :int32) (:long #+(or x86-64 64bit) :int64 #-(or x86-64 64bit) :int32) (:bigint :int64) ((:float :double) :double) ((:numeric) :number) (otherwise :string)))))) (defmethod database-dump-result-set (result-set (database sqlite-database)) (handler-case (sqlite:sqlite-finalize (sqlite-result-set-vm result-set)) (sqlite:sqlite-error (err) (error 'sql-database-error :message (format nil "Error finalizing SQLite VM: ~A" (sqlite:sqlite-error-message err)))))) (defmethod database-store-next-row (result-set (database sqlite-database) list) (let ((n-col (sqlite-result-set-n-col result-set)) (result-types (sqlite-result-set-result-types result-set))) (if (= n-col 0) ;; empty result set nil (let ((row (sqlite-result-set-first-row result-set))) (if (sqlite:null-row-p row) ;; First row already used. fetch another row from DB. (handler-case (multiple-value-bind (n new-row col-names) (sqlite:sqlite-step (sqlite-result-set-vm result-set)) (declare (ignore n col-names) (type sqlite:sqlite-row-pointer-type new-row)) (if (sqlite:null-row-p new-row) (return-from database-store-next-row nil) (setf row new-row))) (sqlite:sqlite-error (err) (error 'sql-database-error :message (format nil "Error in sqlite-step: ~A" (sqlite:sqlite-error-message err))))) ;; Use the row previously read by database-query-result-set. (setf (sqlite-result-set-first-row result-set) (sqlite:make-null-row))) (loop for i = 0 then (1+ i) for rest on list do (setf (car rest) (clsql-uffi:convert-raw-field (sqlite:sqlite-raw-aref row i) (nth i result-types) :encoding (encoding database)))) (sqlite:sqlite-free-row row) t)))) ;;; Object listing (defmethod database-list-tables-and-sequences ((database sqlite-database) &key owner) (declare (ignore owner)) ;; Query is copied from .table command of sqlite comamnd line utility. (mapcar #'car (database-query "SELECT name FROM sqlite_master WHERE type='table' UNION ALL SELECT name FROM sqlite_temp_master WHERE type='table' ORDER BY name" database nil nil))) (defmethod database-list-tables ((database sqlite-database) &key owner) (remove-if #'(lambda (s) (and (>= (length s) 11) (string-equal (subseq s 0 11) "_CLSQL_SEQ_"))) (database-list-tables-and-sequences database :owner owner))) (defmethod database-list-views ((database sqlite-database) &key (owner nil)) (declare (ignore owner)) (mapcar #'car (database-query "SELECT name FROM sqlite_master WHERE type='view' UNION ALL SELECT name FROM sqlite_temp_master WHERE type='view' ORDER BY name" database nil nil))) (defmethod database-list-indexes ((database sqlite-database) &key (owner nil)) (declare (ignore owner)) (mapcar #'car (database-query "SELECT name FROM sqlite_master WHERE type='index' UNION ALL SELECT name FROM sqlite_temp_master WHERE type='index' ORDER BY name" database nil nil))) (defmethod database-list-table-indexes (table (database sqlite-database) &key (owner nil)) (declare (ignore owner)) (let ((*print-circle* nil)) (mapcar #'car (database-query (format nil "SELECT name FROM sqlite_master WHERE type='index' AND tbl_name='~A' UNION ALL SELECT name FROM sqlite_temp_master WHERE type='index' AND tbl_name='~A' ORDER BY name" table table) database nil nil)))) (declaim (inline sqlite-table-info)) (defun sqlite-table-info (table database) (database-query (format nil "PRAGMA table_info('~A')" table) database nil nil)) (defmethod database-list-attributes (table (database sqlite-database) &key (owner nil)) (declare (ignore owner)) (mapcar #'(lambda (table-info) (second table-info)) (sqlite-table-info table database))) (defmethod database-attribute-type (attribute table (database sqlite-database) &key (owner nil)) (declare (ignore owner)) (loop for field-info in (sqlite-table-info table database) when (string= attribute (second field-info)) return (let* ((raw-type (third field-info)) (start-length (position #\( raw-type)) (type (if start-length (subseq raw-type 0 start-length) raw-type)) (length (if start-length (parse-integer (subseq raw-type (1+ start-length)) :junk-allowed t) nil))) (values (when type (ensure-keyword type)) length nil (if (string-equal (fourth field-info) "0") 1 0))))) (defmethod database-create (connection-spec (type (eql :sqlite))) (declare (ignore connection-spec)) ;; databases are created automatically by SQLite t) (defmethod database-destroy (connection-spec (type (eql :sqlite))) (destructuring-bind (name) connection-spec (if (probe-file name) (delete-file name) nil))) (defmethod database-probe (connection-spec (type (eql :sqlite))) (destructuring-bind (name) connection-spec ;; TODO: Add a test that this file is a real sqlite database (or (string-equal ":memory:" name) (and (probe-file name) t)))) ;;; Database capabilities (defmethod db-type-has-boolean-where? ((db-type (eql :sqlite))) nil) cl-sql-6.4.1/db-sqlite/sqlite-api.lisp0000644000175000017500000002365111335067642016572 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; FILE IDENTIFICATION ;;;; ;;;; Name: sqlite-api-uffi.lisp ;;;; Purpose: Low-level SQLite interface using UFFI ;;;; Authors: Aurelio Bignoli and Kevin Rosenberg ;;;; Created: Nov 2003 ;;;; ;;;; This file, part of CLSQL, is Copyright (c) 2003 by Aurelio Bignoli ;;;; and Copyright (c) 2003-2004 by Kevin Rosenberg ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* (in-package #:cl-user) (defpackage #:sqlite (:use #:common-lisp #:uffi) (:export ;;; Conditions #:sqlite-error #:sqlite-error-code #:sqlite-error-message ;;; Core API. #:sqlite-open #:sqlite-close ;;; New API. #:sqlite-compile #:sqlite-step #:sqlite-finalize ;;; Extended API. #:sqlite-get-table #:sqlite-free-table #:sqlite-version ; Defined as constant. #:sqlite-encoding ; Defined as constant. #:sqlite-last-insert-rowid ;;; Utility functions. #:make-null-row #:make-null-vm #:null-row-p #:sqlite-aref #:sqlite-raw-aref #:sqlite-free-row ;;; Types. #:sqlite-row #:sqlite-row-pointer #:sqlite-row-pointer-type #:sqlite-vm-pointer)) (in-package #:sqlite) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;; ;;;; Return values for sqlite_exec() and sqlite_step() ;;;; (defconstant SQLITE-OK 0 "Successful result") (defconstant SQLITE-ERROR 1 "SQL error or missing database") (defconstant SQLITE-ROW 100 "sqlite_step() has another row ready") (defconstant SQLITE-DONE 101 "sqlite_step() has finished executing") ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;; ;;;; Conditions. ;;;; (define-condition sqlite-error () ((message :initarg :message :reader sqlite-error-message :initform "") (code :initarg :code :reader sqlite-error-code)) (:report (lambda (condition stream) (let ((code (sqlite-error-code condition))) (format stream "SQLite error [~A]: ~A" code (sqlite-error-message condition)))))) (defun signal-sqlite-error (code &optional message) (let ((condition (make-condition 'sqlite-error :code code :message (if message message (uffi:convert-from-cstring (sqlite-error-string code)))))) (unless (signal condition) (invoke-debugger condition)))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;; ;;;; Foreign types definitions. ;;;; (def-foreign-type errmsg (* :unsigned-char)) (def-foreign-type sqlite-db :pointer-void) (def-foreign-type sqlite-vm :pointer-void) (def-foreign-type string-pointer (* (* :unsigned-char))) (def-foreign-type sqlite-row-pointer (* (* :unsigned-char))) (defvar +null-errmsg-pointer+ (make-null-pointer 'errmsg)) (defvar +null-string-pointer-pointer+ (make-null-pointer 'string-pointer)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; ;;; Lisp types used in declarations. ;;;; (def-type sqlite-db-type sqlite-db) (def-type sqlite-row string-pointer) (def-type sqlite-row-pointer-type (* string-pointer)) (def-type sqlite-vm-pointer (* sqlite-vm)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;; ;;;; Library functions. ;;;; (defmacro def-sqlite-function (name args &key (returning :void)) `(def-function ,name ,args :module "sqlite" :returning ,returning)) (def-sqlite-function "sqlite_error_string" ((error-code :int)) :returning :cstring) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;; ;;;; Core API. ;;;; (declaim (inline %open)) (def-sqlite-function ("sqlite_open" %open) ((dbname :cstring) (mode :int) (error-message (* errmsg))) :returning sqlite-db) (declaim (inline sqlite-close)) (def-sqlite-function "sqlite_close" ((db sqlite-db))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;; ;;;; New API. ;;;; (declaim (inline %compile)) (def-sqlite-function ("sqlite_compile" %compile) ((db sqlite-db) (sql :cstring) (sql-tail (* (* :unsigned-char))) (vm (* sqlite-vm)) (error-message (* errmsg))) :returning :int) (declaim (inline %step)) (def-sqlite-function ("sqlite_step" %step) ((vm sqlite-vm) (cols-n (* :int)) (cols (* (* (* :unsigned-char)))) (col-names (* (* (* :unsigned-char))))) :returning :int) (declaim (inline %finalize)) (def-sqlite-function ("sqlite_finalize" %finalize) ((vm sqlite-vm) (error-message (* errmsg))) :returning :int) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;; ;;;; Extended API. ;;;; (declaim (inline sqlite-last-insert-rowid)) (def-sqlite-function "sqlite_last_insert_rowid" ((db sqlite-db)) :returning :int) (declaim (inline %get-table)) (def-sqlite-function ("sqlite_get_table" %get-table) ((db sqlite-db) (sql :cstring) (result (* (* (* :unsigned-char)))) (rows-n (* :int)) (cols-n (* :int)) (error-message (* errmsg))) :returning :int) (declaim (inline %free-table)) (def-sqlite-function ("sqlite_free_table" %free-table) ((rows :pointer-void))) (declaim (inline sqlite-libversion)) (def-sqlite-function "sqlite_libversion" () :returning :cstring) (declaim (inline sqlite-libencoding)) (def-sqlite-function "sqlite_libencoding" () :returning :cstring) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;; ;;;; Wrapper functions. ;;;; (defparameter sqlite-version (sqlite-libversion)) (defparameter sqlite-encoding (sqlite-libencoding)) (defun sqlite-open (db-name &optional (mode 0)) (with-cstring (db-name-native db-name) (let ((db (%open db-name-native mode +null-errmsg-pointer+))) (if (null-pointer-p db) (signal-sqlite-error SQLITE-ERROR (format nil "unable to open ~A" db-name)) db)))) (defun sqlite-compile (db sql) (with-cstring (sql-native sql) (let ((vm (allocate-foreign-object 'sqlite-vm))) (with-foreign-object (sql-tail '(* :unsigned-char)) (let ((result (%compile db sql-native sql-tail vm +null-errmsg-pointer+))) (if (= result SQLITE-OK) vm (progn (free-foreign-object vm) (signal-sqlite-error result)))))))) (defun sqlite-step (vm) (declare (type sqlite-vm-pointer vm)) (with-foreign-object (cols-n :int) (let ((cols (allocate-foreign-object '(* (* :unsigned-char)))) (col-names (allocate-foreign-object '(* (* :unsigned-char))))) (declare (type sqlite-row-pointer-type cols col-names)) (let ((result (%step (deref-pointer vm 'sqlite-vm) cols-n cols col-names))) (cond ((= result SQLITE-ROW) (let ((n (deref-pointer cols-n :int))) (values n cols col-names))) ((= result SQLITE-DONE) (free-foreign-object cols) (free-foreign-object col-names) (values 0 +null-string-pointer-pointer+ +null-string-pointer-pointer+)) (t (free-foreign-object cols) (free-foreign-object col-names) (signal-sqlite-error result))))))) (defun sqlite-finalize (vm) (declare (type sqlite-vm-pointer vm)) (let ((result (%finalize (deref-pointer vm 'sqlite-vm) +null-errmsg-pointer+))) (if (= result SQLITE-OK) (progn (free-foreign-object vm) t) (signal-sqlite-error result)))) (defun sqlite-get-table (db sql) (declare (type sqlite-db-type db)) (with-cstring (sql-native sql) (let ((rows (allocate-foreign-object '(* (* :unsigned-char))))) (declare (type sqlite-row-pointer-type rows)) (with-foreign-object (rows-n :int) (with-foreign-object (cols-n :int) (let ((result (%get-table db sql-native rows rows-n cols-n +null-errmsg-pointer+))) (if (= result SQLITE-OK) (let ((cn (deref-pointer cols-n :int)) (rn (deref-pointer rows-n :int))) (values rows rn cn)) (progn (free-foreign-object rows) (signal-sqlite-error result))))))))) (declaim (inline sqlite-free-table)) (defun sqlite-free-table (table) (declare (type sqlite-row-pointer-type table)) (%free-table (deref-pointer table 'sqlite-row-pointer))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;; ;;;; Utility functions. ;;;; (declaim (inline make-null-row)) (defun make-null-row () +null-string-pointer-pointer+) (declaim (inline make-null-vm)) (defun make-null-vm () (uffi:make-null-pointer 'sqlite-vm)) (declaim (inline null-row-p)) (defun null-row-p (row) (null-pointer-p row)) (declaim (inline sqlite-aref)) (defun sqlite-aref (a n encoding) (declare (type sqlite-row-pointer-type a)) (convert-from-foreign-string (deref-array (deref-pointer a 'sqlite-row-pointer) '(:array (* :unsigned-char)) n) :encoding encoding)) (declaim (inline sqlite-raw-aref)) (defun sqlite-raw-aref (a n) (declare (type sqlite-row-pointer-type a)) (deref-array (deref-pointer a 'sqlite-row-pointer) '(:array (* :unsigned-char)) n)) (declaim (inline sqlite-free-row)) (defun sqlite-free-row (row) (declare (type sqlite-row-pointer-type row)) (free-foreign-object row)) cl-sql-6.4.1/db-sqlite/sqlite-package.lisp0000644000175000017500000000151211335067642017404 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; FILE IDENTIFICATION ;;;; ;;;; Name: sqlite-package.lisp ;;;; Purpose: Package definition for low-level SQLite interface ;;;; Programmer: Aurelio Bignoli ;;;; Date Started: Aug 2003 ;;;; ;;;; This file, part of CLSQL, is Copyright (c) 2003 by Aurelio Bignoli ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* (in-package #:cl-user) (defpackage #:clsql-sqlite (:use #:common-lisp #:clsql-sys) (:export #:sqlite-database)) cl-sql-6.4.1/db-sqlite/sqlite-loader.lisp0000644000175000017500000000313511335067642017262 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; FILE IDENTIFICATION ;;;; ;;;; Name: sqlite-loader.lisp ;;;; Purpose: SQLite library loader using UFFI ;;;; Programmer: Aurelio Bignoli ;;;; Date Started: Nov 2003 ;;;; ;;;; This file, part of CLSQL, is Copyright (c) 2003 by Aurelio Bignoli ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* (in-package #:clsql-sqlite) (defvar *sqlite-supporting-libraries* '("c") "Used only by CMU. List of library flags needed to be passed to ld to load the SQLite library succesfully. If this differs at your site, set to the right path before compiling or loading the system.") (defvar *sqlite-library-loaded* nil "T if foreign library was able to be loaded successfully") (defmethod database-type-library-loaded ((database-type (eql :sqlite))) "T if foreign library was able to be loaded successfully. " *sqlite-library-loaded*) (defmethod database-type-load-foreign ((database-type (eql :sqlite))) (clsql-uffi:find-and-load-foreign-library '("libsqlite" "sqlite") :module "sqlite" :supporting-libraries *sqlite-supporting-libraries*) (setq *sqlite-library-loaded* t)) (clsql-sys:database-type-load-foreign :sqlite) cl-sql-6.4.1/db-sqlite/Makefile0000644000175000017500000000126411335067642015265 0ustar kevinkevin#!/usr/bin/make ########################################################################## # FILE IDENTIFICATION # # Name: Makefile # Purpose: Makefile for CLSQL SQLITE interface # Programer: Kevin M. Rosenberg # Date Started: Mar 2002 # # This file, part of CLSQL, is Copyright (c) 2002 by Kevin M. Rosenberg # # CLSQL users are granted the rights to distribute and use this software # as governed by the terms of the Lisp Lesser GNU Public License # (http://opensource.franz.com/preamble.html), also known as the LLGPL. ########################################################################## SUBDIRS= include ../Makefile.common .PHONY: distclean distclean: clean cl-sql-6.4.1/clsql-uffi.asd0000644000175000017500000000674211577723152014510 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; FILE IDENTIFICATION ;;;; ;;;; Name: clsql-uffi.asd ;;;; Purpose: ASDF definition file for CLSQL UFFI Helper package ;;;; Programmer: Kevin M. Rosenberg ;;;; Date Started: Aug 2002 ;;;; ;;;; This file, part of CLSQL, is Copyright (c) 2002-2010 by Kevin M. Rosenberg ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* (in-package cl-user) (defpackage clsql-uffi-system (:use #:asdf #:cl)) (in-package clsql-uffi-system) (defvar *clsql-uffi-library-dir* (merge-pathnames "uffi/" (make-pathname :name nil :type nil :defaults *load-truename*))) (defclass clsql-uffi-source-file (c-source-file) ()) (defmethod output-files ((o compile-op) (c clsql-uffi-source-file)) (let* ((library-file-type (funcall (intern (symbol-name'#:default-foreign-library-type) (symbol-name '#:uffi)))) (found (some #'(lambda (dir) (probe-file (make-pathname :directory dir :name (component-name c) :type library-file-type))) '((:absolute "usr" "lib" "clsql"))))) (list (if found found (make-pathname :name (component-name c) :type library-file-type :defaults *clsql-uffi-library-dir*))))) (defmethod perform ((o load-op) (c clsql-uffi-source-file)) nil) ;;; library will be loaded by a loader file (defmethod operation-done-p ((o load-op) (c clsql-uffi-source-file)) (and (find-package '#:clsql-uffi) (symbol-function (intern (symbol-name '#:atol64) (find-package '#:clsql-uffi))) t)) (defmethod perform ((o compile-op) (c clsql-uffi-source-file)) (unless (operation-done-p o c) #-(or win32 win64 windows mswindows) (unless (zerop (run-shell-command #-(or freebsd netbsd) "cd ~A; make" #+(or freebsd netbsd) "cd ~A; gmake" (namestring *clsql-uffi-library-dir*))) (error 'operation-error :component c :operation o)))) (defmethod operation-done-p ((o compile-op) (c clsql-uffi-source-file)) (or (and (probe-file #p"/usr/lib/clsql/clsql_uffi.so") t) (let ((lib (make-pathname :defaults (component-pathname c) :type (funcall (intern (symbol-name '#:default-foreign-library-type) (find-package '#:uffi)))))) (and (probe-file lib) (probe-file (component-pathname c)) (> (file-write-date lib) (file-write-date (component-pathname c))))))) (defsystem clsql-uffi :name "cl-sql-base" :author "Kevin M. Rosenberg " :maintainer "Kevin M. Rosenberg " :licence "Lessor Lisp General Public License" :description "Common UFFI Helper functions for Common Lisp SQL Interface Library" :long-description "cl-sql-uffi package provides common helper functions using the UFFI for the CLSQL package." :depends-on (clsql #-:clsql-cffi (:version uffi "2.0") #+:clsql-cffi cffi-uffi-compat) :components ((:module :uffi :components ((:file "clsql-uffi-package") (:clsql-uffi-source-file "clsql_uffi" :depends-on ("clsql-uffi-package")) (:file "clsql-uffi-loader" :depends-on ("clsql-uffi-package" "clsql_uffi")) (:file "clsql-uffi" :depends-on ("clsql-uffi-loader")))))) cl-sql-6.4.1/db-oracle/0000755000175000017500000000000012134026703013555 5ustar kevinkevincl-sql-6.4.1/db-oracle/oracle-package.lisp0000644000175000017500000000162011335067642017314 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; FILE IDENTIFICATION ;;;; ;;;; Name: oracle-package.cl ;;;; Purpose: Package definition for CLSQL Oracle interface ;;;; ;;;; This file is part of CLSQL. ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* (in-package #:cl-user) (defpackage #:clsql-oracle (:use #:common-lisp #:clsql-sys #:clsql-uffi) (:export #:oracle-database #:*oracle-server-version* #:*oracle-so-load-path* #:*oracle-so-libraries*) (:documentation "This is the CLSQL interface to Oracle.")) cl-sql-6.4.1/db-oracle/oracle-objects.lisp0000644000175000017500000001110711335067642017353 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; FILE IDENTIFICATION ;;;; ;;;; Name: oracle-objects.lisp ;;;; ;;;; This file is part of CLSQL. ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* (in-package #:clsql-oracle) (defmethod database-get-type-specifier (type args database (db-type (eql :oracle))) (declare (ignore type args database)) (format nil "VARCHAR2(~D)" *default-string-length*)) (defmethod database-get-type-specifier ((type (eql 'integer)) args database (db-type (eql :oracle))) (declare (ignore database)) (if args (format nil "NUMBER(~A,~A)" (or (first args) 38) (or (second args) 0)) "INTEGER")) (defmethod database-get-type-specifier ((type (eql 'bigint)) args database (db-type (eql :oracle))) (declare (ignore args database)) "CHAR(20)") (defmethod database-get-type-specifier ((type (eql 'universal-time)) args database (db-type (eql :oracle))) (declare (ignore args database)) "CHAR(20)") (defmethod database-get-type-specifier ((type (eql 'string)) args database (db-type (eql :oracle))) (declare (ignore database)) (if args (format nil "CHAR(~A)" (car args)) (format nil "VARCHAR2(~D)" *default-string-length*))) (defmethod database-get-type-specifier ((type (eql 'varchar)) args database (db-type (eql :oracle))) (declare (ignore database)) (if args (format nil "VARCHAR2(~A)" (car args)) (format nil "VARCHAR2(~D)" *default-string-length*))) (defmethod database-get-type-specifier ((type (eql 'float)) args database (db-type (eql :oracle))) (declare (ignore database)) (if args (format nil "NUMBER(~A,~A)" (or (first args) 38) (or (second args) 38)) "DOUBLE PRECISION")) (defmethod database-get-type-specifier ((type (eql 'long-float)) args database (db-type (eql :oracle))) (declare (ignore database)) (if args (format nil "NUMBER(~A,~A)" (or (first args) 38) (or (second args) 38)) "DOUBLE PRECISION")) (defmethod database-get-type-specifier ((type (eql 'boolean)) args database (db-type (eql :oracle))) (declare (ignore args database)) "CHAR(1)") (defmethod database-get-type-specifier ((type (eql 'generalized-boolean)) args database (db-type (eql :oracle))) (declare (ignore args database)) "CHAR(1)") (defmethod read-sql-value (val type database (db-type (eql :oracle))) ;;(format t "value is \"~A\" of type ~A~%" val (type-of val)) (declare (ignore type database)) (etypecase val (string (read-from-string val)) (symbol nil))) (defmethod read-sql-value (val (type (eql 'integer)) database (db-type (eql :oracle))) (declare (ignore database)) val) (defmethod read-sql-value (val (type (eql 'float)) database (db-type (eql :oracle))) (declare (ignore database)) val) (defmethod read-sql-value (val (type (eql 'boolean)) database (db-type (eql :oracle))) (declare (ignore database)) (when (char-equal #\t (schar val 0)) t)) (defmethod read-sql-value (val (type (eql 'generalized-boolean)) database (db-type (eql :oracle))) (declare (ignore database)) (when (char-equal #\t (schar val 0)) t)) (defmethod read-sql-value (val (type (eql 'bigint)) database (db-type (eql :oracle))) (declare (ignore database)) (parse-integer val)) (defmethod read-sql-value (val (type (eql 'universal-time)) database (db-type (eql :oracle))) (declare (ignore database)) (parse-integer val)) (defmethod database-get-type-specifier ((type (eql 'wall-time)) args database (db-type (eql :oracle))) (declare (ignore args database)) "DATE") (defmethod database-get-type-specifier ((type (eql 'duration)) args database (db-type (eql :oracle))) (declare (ignore args database)) "NUMBER(38)") cl-sql-6.4.1/db-oracle/oracle-api.lisp0000644000175000017500000002615511335067642016504 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; FILE IDENTIFICATION ;;;; ;;;; Name: oracle.lisp ;;;; Purpose: Package definition for CLSQL Oracle interface ;;;; ;;;; This file is part of CLSQL. ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* (in-package #:clsql-oracle) ;; ;; OCI integer types ;; (uffi:def-foreign-type ub2 :unsigned-short) (uffi:def-foreign-type sb2 :short) (uffi:def-foreign-type ub4 :unsigned-int) (uffi:def-foreign-type sb4 :int) (uffi:def-foreign-type size_t :unsigned-long) ;; ;; Opaque pointer types ;; (uffi:def-foreign-type void-pointer :pointer-void) (uffi:def-foreign-type oci-env :pointer-void) (uffi:def-foreign-type oci-server :pointer-void) (uffi:def-foreign-type oci-error :pointer-void) (uffi:def-foreign-type oci-svc-ctx :pointer-void) (uffi:def-foreign-type oci-stmt :pointer-void) (uffi:def-pointer-var +null-void-pointer+ (uffi:make-null-pointer :void)) (uffi:def-pointer-var +null-void-pointer-pointer+ (uffi:make-null-pointer :pointer-void)) ;;; Check an OCI return code for erroricity and signal a reasonably ;;; informative condition if so. ;;; ;;; ERRHP provides an error handle which can be used to find ;;; subconditions; if it's not provided, subcodes won't be checked. ;;; ;;; NULLS-OK says that a NULL-VALUE-RETURNED subcondition condition is ;;; normal and needn't cause any signal. An error handle is required ;;; to detect this subcondition, so it doesn't make sense to set ERRHP ;;; unless NULLS-OK is set. (defmacro def-oci-routine ((c-oci-symbol lisp-oci-fn) c-return &rest c-parms) (let ((ll (mapcar (lambda (x) (declare (ignore x)) (gensym)) c-parms)) (c-oci-fn (intern (concatenate 'string "%" (symbol-name lisp-oci-fn))))) `(progn (declaim (inline ,c-oci-fn ,lisp-oci-fn)) (uffi:def-function (,c-oci-symbol ,c-oci-fn) ,c-parms :returning ,c-return) (defun ,lisp-oci-fn (,@ll &key database nulls-ok) (let ((result (,c-oci-fn ,@ll))) (if (= result #.+oci-success+) +oci-success+ (handle-oci-result result database nulls-ok))))))) (defmacro def-raw-oci-routine ((c-oci-symbol lisp-oci-fn) c-return &rest c-parms) (let ((ll (mapcar (lambda (x) (declare (ignore x)) (gensym)) c-parms))) `(let ((%lisp-oci-fn (uffi:def-function (,c-oci-symbol ,(intern (concatenate 'string "%" (symbol-name lisp-oci-fn)))) ,c-parms :returning ,c-return))) (defun ,lisp-oci-fn (,@ll &key database nulls-ok) (declare (ignore database nulls-ok)) (funcall %lisp-oci-fn ,@ll))))) (def-oci-routine ("OCIInitialize" oci-initialize) :int (mode ub4) ; ub4 (ctxp :pointer-void) ; dvoid * (malocfp :pointer-void) ; dvoid *(*) (ralocfp :pointer-void) ; dvoid *(*) (mfreefp (* :pointer-void))) ; void *(*) (def-oci-routine ("OCIEnvInit" oci-env-init) :int (envpp :pointer-void) ; OCIEnv ** (mode ub4) ; ub4 (xtramem-sz size_t) ; size_t (usermempp (* :pointer-void))) ; dvoid ** #-oci7 (def-oci-routine ("OCIEnvCreate" oci-env-create) :int (envhpp (* :pointer-void)) (mode ub4) (ctxp :pointer-void) (malocfp :pointer-void) (ralocfp :pointer-void) (mfreefp :pointer-void) (xtramemsz size_t) (usrmempp (* :pointer-void))) (def-oci-routine ("OCIHandleAlloc" oci-handle-alloc) :int (parenth :pointer-void) ; const dvoid * (hndlpp (* :pointer-void)) ; dvoid ** (type ub4) ; ub4 (xtramem_sz size_t) ; size_t (usrmempp (* :pointer-void))) ; dvoid ** (def-oci-routine ("OCIServerAttach" oci-server-attach) :int (srvhp :pointer-void) ; oci-server (errhp :pointer-void) ; oci-error (dblink :cstring) ; :in (dblink-len sb4) ; sb4 (mode ub4)) ; ub4 (def-oci-routine ("OCIHandleFree" oci-handle-free) :int (p0 :pointer-void) ;; handle (p1 ub4)) ;;type (def-oci-routine ("OCILogon" oci-logon) :int (envhp :pointer-void) ; env (errhp :pointer-void) ; err (svchpp (* :pointer-void)) ; svc (username (* :unsigned-char)) ; username (uname-len ub4) ; (passwd (* :unsigned-char)) ; passwd (password-len ub4) ; (dsn (* :unsigned-char)) ; datasource (dsn-len ub4)) ; (def-oci-routine ("OCILogoff" oci-logoff) :int (p0 :pointer-void) ; svc (p1 :pointer-void)) ; err (declaim (inline oci-error-get)) (uffi:def-function ("OCIErrorGet" oci-error-get) ((handlp :pointer-void) (recordno ub4) (sqlstate :cstring) (errcodep (* sb4)) (bufp (* :unsigned-char)) (bufsize ub4) (type ub4)) :returning :void) (def-oci-routine ("OCIStmtPrepare" oci-stmt-prepare) :int (stmtp :pointer-void) (errhp :pointer-void) (stmt (* :unsigned-char)) (stmt_len ub4) (language ub4) (mode ub4)) (def-oci-routine ("OCIStmtExecute" oci-stmt-execute) :int (svchp :pointer-void) (stmtp1 :pointer-void) (errhp :pointer-void) (iters ub4) (rowoff ub4) (snap_in :pointer-void) (snap_out :pointer-void) (mode ub4)) (def-raw-oci-routine ("OCIParamGet" oci-param-get) :int (hndlp :pointer-void) (htype ub4) (errhp :pointer-void) (parmdpp (* :pointer-void)) (pos ub4)) (def-oci-routine ("OCIAttrGet" oci-attr-get) :int (trgthndlp :pointer-void) (trghndltyp ub4) (attributep :pointer-void) (sizep (* ub4)) (attrtype ub4) (errhp :pointer-void)) (def-oci-routine ("OCIAttrSet" oci-attr-set) :int (trgthndlp :pointer-void) (trgthndltyp ub4 :in) (attributep :pointer-void) (size ub4) (attrtype ub4) (errhp oci-error)) (def-oci-routine ("OCIDefineByPos" oci-define-by-pos) :int (stmtp :pointer-void) (defnpp (* :pointer-void)) (errhp :pointer-void) (position ub4) (valuep :pointer-void) (value_sz sb4) (dty ub2) (indp (* sb2)) (rlenp (* ub2)) (rcodep (* ub2)) (mode ub4)) (def-oci-routine ("OCIStmtFetch" oci-stmt-fetch) :int (stmthp :pointer-void) (errhp :pointer-void) (p2 ub4) (p3 ub2) (p4 ub4)) (def-oci-routine ("OCITransStart" oci-trans-start) :int (svchp :pointer-void) (errhp :pointer-void) (p2 :unsigned-short) (p3 :unsigned-short)) (def-oci-routine ("OCITransCommit" oci-trans-commit) :int (svchp :pointer-void) (errhp :pointer-void) (p2 :unsigned-short)) (def-oci-routine ("OCITransRollback" oci-trans-rollback) :int (svchp :pointer-void) (errhp :pointer-void) (p2 :unsigned-short)) (def-oci-routine ("OCIServerVersion" oci-server-version) :int (handlp :pointer-void) (errhp :pointer-void) (bufp (* :unsigned-char)) (bufsz :int) (hndltype :short)) ;;; Low-level routines that don't do error checking. They are used ;;; for setting up global environment. (uffi:def-function "OCIInitialize" ((mode ub4) ; ub4 (ctxp :pointer-void) ; dvoid * (malocfp :pointer-void) ; dvoid *(*) (ralocfp :pointer-void) ; dvoid *(*) (mfreefp (* :pointer-void))) :returning :int) (uffi:def-function "OCIEnvInit" ((envpp :pointer-void) ; OCIEnv ** (mode ub4) ; ub4 (xtramem-sz size_t) ; size_t (usermempp (* :pointer-void))) :returning :int) (uffi:def-function "OCIHandleAlloc" ((parenth :pointer-void) ; const dvoid * (hndlpp (* :pointer-void)) ; dvoid ** (type ub4) ; ub4 (xtramem_sz size_t) ; size_t (usrmempp (* :pointer-void))) :returning :int) (defstruct oci-handle (type :unknown) (pointer (uffi:allocate-foreign-object :pointer-void))) (defvar *oci-initialized* nil) (defvar *oci-env* nil) (defvar *oci-handle-types* '(:error ; error report handle (OCIError) :service-context ; service context handle (OCISvcCtx) :statement ; statement (application request) handle (OCIStmt) :describe ; select list description handle (OCIDescribe) :server ; server context handle (OCIServer) :session ; user session handle (OCISession) :transaction ; transaction context handle (OCITrans) :complex-object ; complex object retrieval handle (OCIComplexObject) :security)) ; security handle (OCISecurity) (defun oci-init (&key (mode +oci-default+)) (let ((x (OCIInitialize mode +null-void-pointer+ +null-void-pointer+ +null-void-pointer+ +null-void-pointer-pointer+))) (if (= x 0) (let ((env (uffi:allocate-foreign-object :pointer-void))) (setq *oci-initialized* mode) (let ((x (OCIEnvInit env +oci-default+ 0 +null-void-pointer+))) (format t ";; OEI: returned ~d~%" x) (setq *oci-env* env)))))) (defun oci-check-return (value) (when (= value +oci-invalid-handle+) (error 'sql-database-error :message "Invalid Handle"))) (defun oci-get-handle (&key type) (if (null *oci-initialized*) (oci-init)) (case type (:error (let ((ptr (uffi:allocate-foreign-object :pointer-void))) (let ((x (OCIHandleAlloc (uffi:deref-pointer *oci-env* void-pointer) ptr +oci-default+ 0 +null-void-pointer-pointer+))) (oci-check-return x) ptr))) (:service-context "OCISvcCtx") (:statement "OCIStmt") (:describe "OCIDescribe") (:server "OCIServer") (:session "OCISession") (:transaction "OCITrans") (:complex-object "OCIComplexObject") (:security "OCISecurity") (t (error 'sql-database-error :message (format nil "'~s' is not a valid OCI handle type" type))))) (defun oci-environment () (let ((envhp (oci-get-handle :type :env))) (oci-env-init envhp 0 0 +null-void-pointer+) envhp)) cl-sql-6.4.1/db-oracle/foreign-resources.lisp0000644000175000017500000000346611335067642020131 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; FILE IDENTIFICATION ;;;; ;;;; This file is part of CLSQL. ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* (in-package #:clsql-oracle) (defparameter *foreign-resource-hash* (make-hash-table :test #'equal)) (defstruct (foreign-resource) (type (error "Missing TYPE.") :read-only t) (sizeof (error "Missing SIZEOF.") :read-only t) (buffer (error "Missing BUFFER.") :read-only t) (in-use nil :type boolean)) (defun %get-resource (type sizeof) (let ((resources (gethash type *foreign-resource-hash*))) (car (member-if #'(lambda (res) (and (= (foreign-resource-sizeof res) sizeof) (not (foreign-resource-in-use res)))) resources)))) (defun %insert-foreign-resource (type res) (let ((resource (gethash type *foreign-resource-hash*))) (setf (gethash type *foreign-resource-hash*) (cons res resource)))) (defmacro acquire-foreign-resource (type &optional size) `(let ((res (%get-resource ,type ,size))) (unless res (setf res (make-foreign-resource :type ,type :sizeof ,size :buffer (uffi:allocate-foreign-object ,type ,size))) (%insert-foreign-resource ',type res)) (claim-foreign-resource res))) (defun free-foreign-resource (ares) (setf (foreign-resource-in-use ares) nil) ares) (defun claim-foreign-resource (ares) (setf (foreign-resource-in-use ares) t) ares) cl-sql-6.4.1/db-oracle/oracle-loader.lisp0000644000175000017500000000413411335067642017172 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; FILE IDENTIFICATION ;;;; ;;;; Name: oracle-loader.lisp ;;;; Purpose: Foreign library loader for CLSQL Oracle interface ;;;; ;;;; This file is part of CLSQL. ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* (in-package #:clsql-oracle) (defparameter *oracle-home* (let ((oracle-home (getenv "ORACLE_HOME"))) (when oracle-home (parse-namestring (concatenate 'string oracle-home "/")))) "Pathname of ORACLE_HOME as set in user environment.") (defparameter *oracle-client-library-filenames* (list "libclntsh" "oci")) (defvar *oracle-supporting-libraries* '("c") "Used only by CMU. List of library flags needed to be passed to ld to load the Oracle client library succesfully. If this differs at your site, set to the right path before compiling or loading the system.") (defvar *oracle-library-loaded* nil "T if foreign library was able to be loaded successfully") (defmethod clsql-sys:database-type-library-loaded ((database-type (eql :oracle))) *oracle-library-loaded*) (defmethod clsql-sys:database-type-load-foreign ((database-type (eql :oracle))) (when *oracle-home* (dolist (dir-name '("lib" "bin")) (dolist (lib-name '("libclntsh" "oci")) (clsql:push-library-path (make-pathname :name lib-name :directory (append (pathname-directory *oracle-home*) (list dir-name))))))) (clsql-uffi:find-and-load-foreign-library *oracle-client-library-filenames* :module "clsql-oracle" :supporting-libraries *oracle-supporting-libraries*) (setq *oracle-library-loaded* t)) (clsql-sys:database-type-load-foreign :oracle) cl-sql-6.4.1/db-oracle/oracle-sql.lisp0000644000175000017500000013216411674245477016542 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; FILE IDENTIFICATION ;;;; ;;;; Name: oracle-sql.lisp ;;;; ;;;; This file is part of CLSQL. ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* (in-package #:clsql-oracle) (defmethod database-initialize-database-type ((database-type (eql :oracle))) t) ;;;; arbitrary parameters, tunable for performance or other reasons (eval-when (:compile-toplevel :load-toplevel :execute) (defconstant +errbuf-len+ 512 "the number of characters that we allocate for an error message buffer") (defconstant +n-buf-rows+ 200 "the number of table rows that we buffer at once when reading a table. CMUCL has a compiled-in limit on how much C data can be allocated (through malloc() and friends) at any given time, typically 8 Mb. Setting this constant to a moderate value should make it less likely that we'll have to worry about the CMUCL limit.")) (uffi:def-type vp-type :pointer-void) (uffi:def-type vpp-type (* :pointer-void)) (defmacro deref-vp (foreign-object) `(the vp-type (uffi:deref-pointer (the vpp-type ,foreign-object) :pointer-void))) (uffi:def-pointer-var +unsigned-char-null-pointer+ (uffi:make-null-pointer :unsigned-char)) (uffi:def-pointer-var +unsigned-short-null-pointer+ (uffi:make-null-pointer :unsigned-short)) (uffi:def-pointer-var +unsigned-int-null-pointer+ (uffi:make-null-pointer :unsigned-int)) ;; constants - from OCI? (defconstant +var-not-in-list+ 1007) (defconstant +no-data-found+ 1403) (defconstant +null-value-returned+ 1405) (defconstant +field-truncated+ 1406) (eval-when (:compile-toplevel :load-toplevel :execute) (defconstant SQLT-NUMBER 2) (defconstant SQLT-INT 3) (defconstant SQLT-FLT 4) (defconstant SQLT-STR 5) (defconstant SQLT-DATE 12)) ;;; Note that despite the suggestive class name (and the way that the ;;; *DEFAULT-DATABASE* variable holds an object of this class), a DB ;;; object is not actually a database but is instead a connection to a ;;; database. Thus, there's no obstacle to having any number of DB ;;; objects referring to the same database. (uffi:def-type pointer-pointer-void (* :pointer-void)) (defclass oracle-database (database) ; was struct db ((envhp :reader envhp :initarg :envhp :type pointer-pointer-void :documentation "OCI environment handle") (errhp :reader errhp :initarg :errhp :type pointer-pointer-void :documentation "OCI error handle") (svchp :reader svchp :initarg :svchp :type pointer-pointer-void :documentation "OCI service context handle") (data-source-name :initarg :dsn :initform nil :documentation "optional data source name (used only for debugging/printing)") (user :initarg :user :reader user :type string :documentation "the \"user\" value given when data source connection was made") (date-format :initarg :date-format :reader date-format :initform "YYYY-MM-DD HH24:MI:SS\".0\"") (date-format-length :type number :documentation "Each database connection can be configured with its own date output format. In order to extract date strings from output buffers holding multiple date strings in fixed-width fields, we need to know the length of that format.") (server-version :type (or null string) :initarg :server-version :reader server-version :documentation "Version string of Oracle server.") (major-server-version :type (or null fixnum) :initarg :major-server-version :reader major-server-version :documentation "The major version number of the Oracle server, should be 8, 9, or 10"))) ;;; Handle a non-successful result from an OCI function. (defun handle-oci-result (result database nulls-ok) (case result (#.+oci-success+ +oci-success+) (#.+oci-error+ (handle-oci-error :database database :nulls-ok nulls-ok)) (#.+oci-no-data+ (error 'sql-database-error :message "OCI No Data Found")) (#.+oci-success-with-info+ (error 'sql-database-error :message "internal error: unexpected +oci-success-with-info")) (#.+oci-invalid-handle+ (error 'sql-database-error :message "OCI Invalid Handle")) (#.+oci-need-data+ (error 'sql-database-error :message "OCI Need Data")) (#.+oci-still-executing+ (error 'sql-temporary-error :message "OCI Still Executing")) (#.+oci-continue+ (error 'sql-database-error :message "OCI Continue")) (1804 (error 'sql-database-error :message "Check ORACLE_HOME and NLS settings.")) (t (error 'sql-database-error :message (format nil "OCI unknown error, code=~A" result))))) ;;; Handle the messy case of return code=+oci-error+, querying the ;;; system for subcodes and reporting them as appropriate. ERRHP and ;;; NULLS-OK are as in the OERR function. (defun handle-oci-error (&key database nulls-ok) (cond (database (with-slots (errhp) database (let ((errcode (uffi:allocate-foreign-object 'sb4)) (errbuf (uffi:allocate-foreign-string #.+errbuf-len+))) ;; ensure errbuf empty string (setf (uffi:deref-array errbuf '(:array :unsigned-char) 0) (uffi:ensure-char-storable (code-char 0))) (setf (uffi:deref-pointer errcode 'sb4) 0) (uffi:with-cstring (sqlstate nil) (oci-error-get (deref-vp errhp) 1 sqlstate errcode (uffi:char-array-to-pointer errbuf) +errbuf-len+ +oci-htype-error+)) (let ((subcode (uffi:deref-pointer errcode 'sb4)) (errstr (uffi:convert-from-foreign-string errbuf :encoding (when database (encoding database))))) (uffi:free-foreign-object errcode) (uffi:free-foreign-object errbuf) (unless (and nulls-ok (= subcode +null-value-returned+)) (error 'sql-database-error :database database :error-id subcode :message errstr)))))) (nulls-ok (error 'sql-database-error :database database :message "can't handle NULLS-OK without ERRHP")) (t (error 'sql-database-error :database database :message "OCI Error (and no ERRHP available to find subcode)")))) ;;; Require an OCI success code. ;;; ;;; (The ordinary OCI error reporting mechanisms uses a fair amount of ;;; machinery (environments and other handles). In order to get to ;;; where we can use these mechanisms, we have to be able to allocate ;;; the machinery. The functions for allocating the machinery can ;;; return errors (e.g. out of memory) but shouldn't. Wrapping this function ;;; around function calls to such have-to-succeed functions enforces ;;; this condition.) (defun osucc (code) (declare (type fixnum code)) (unless (= code +oci-success+) (error 'sql-database-error :message (format nil "unexpected OCI failure, code=~S" code)))) ;;; Enabling this can be handy for low-level debugging. #+nil (progn (trace #-oci7 oci-env-create oci-initialize oci-handle-alloc oci-logon oci-error-get oci-stmt-prepare oci-stmt-execute oci-param-get oci-logon oci-attr-get oci-define-by-pos oci-stmt-fetch) (setf debug::*debug-print-length* nil)) ;; Return the INDEXth string of the OCI array, represented as Lisp ;; SIMPLE-STRING. SIZE is the size of the fixed-width fields used by ;; Oracle to store strings within the array. (uffi:def-type string-pointer (* :unsigned-char)) (defun deref-oci-string (arrayptr string-index size encoding) (declare (type string-pointer arrayptr)) (declare (type (mod #.+n-buf-rows+) string-index)) (declare (type (and unsigned-byte fixnum) size)) (let ((str (uffi:convert-from-foreign-string (uffi:make-pointer (+ (uffi:pointer-address arrayptr) (* string-index size)) :unsigned-char) :encoding encoding))) (if (string-equal str "NULL") nil str))) ;; the OCI library, part Z: no-longer used logic to convert from ;; Oracle's binary date representation to Common Lisp's native date ;; representation #+nil (defvar +oci-date-bytes+ 7) ;;; Return the INDEXth date in the OCI array, represented as ;;; a Common Lisp "universal time" (i.e. seconds since 1900). #+nil (defun deref-oci-date (arrayptr index) (oci-date->universal-time (uffi:pointer-address (uffi:deref-array arrayptr '(:array :unsigned-char) (* index +oci-date-bytes+))))) #+nil (defun oci-date->universal-time (oci-date) (declare (type (alien (* :unsigned-char)) oci-date)) (flet (;; a character from OCI-DATE, interpreted as an unsigned byte (ub (i) (declare (type (mod #.+oci-date-bytes+) i)) (mod (uffi:deref-array oci-date string-array i) 256))) (let* ((century (* (- (ub 0) 100) 100)) (year (+ century (- (ub 1) 100))) (month (ub 2)) (day (ub 3)) (hour (1- (ub 4))) (minute (1- (ub 5))) (second (1- (ub 6)))) (encode-universal-time second minute hour day month year)))) (defmethod database-list-tables ((database oracle-database) &key owner) (let ((query (cond ((null owner) "select table_name from user_tables") ((eq owner :all) "select table_name from all_tables") (t (format nil "select user_tables.table_name from user_tables,all_tables where user_tables.table_name=all_tables.table_name and all_tables.owner='~:@(~A~)'" owner))))) (mapcar #'car (database-query query database nil nil)))) (defmethod database-list-views ((database oracle-database) &key owner) (let ((query (cond ((null owner) "select view_name from user_views") ((eq owner :all) "select view_name from all_views") (t (format nil "select user_views.view_name from user_views,all_views where user_views.view_name=all_views.view_name and all_views.owner='~:@(~A~)'" owner))))) (mapcar #'car (database-query query database nil nil)))) (defmethod database-list-indexes ((database oracle-database) &key (owner nil)) (let ((query (cond ((null owner) "select index_name from user_indexes") ((eq owner :all) "select index_name from all_indexes") (t (format nil "select user_indexes.index_name from user_indexes,all_indexes where user_indexes.index_name=all_indexes.index_name and all_indexes.owner='~:@(~A~)'" owner))))) (mapcar #'car (database-query query database nil nil)))) (defmethod database-list-table-indexes (table (database oracle-database) &key (owner nil)) (let ((query (cond ((null owner) (format nil "select index_name from user_indexes where table_name='~A'" table)) ((eq owner :all) (format nil "select index_name from all_indexes where table_name='~A'" table)) (t (format nil "select user_indexes.index_name from user_indexes,all_indexes where user_indexes.table_name='~A' and user_indexes.index_name=all_indexes.index_name and all_indexes.owner='~:@(~A~)'" table owner))))) (mapcar #'car (database-query query database nil nil)))) (defmethod database-list-attributes (table (database oracle-database) &key owner) (let ((query (cond ((null owner) (format nil "select column_name from user_tab_columns where table_name='~A'" table)) ((eq owner :all) (format nil "select column_name from all_tab_columns where table_name='~A'" table)) (t (format nil "select user_tab_columns.column_name from user_tab_columns,all_tables where user_tab_columns.table_name='~A' and all_tables.table_name=user_tab_columns.table_name and all_tables.owner='~:@(~A~)'" table owner))))) (mapcar #'car (database-query query database nil nil)))) (defmethod database-attribute-type (attribute (table string) (database oracle-database) &key (owner nil)) (let ((query (cond ((null owner) (format nil "select data_type,data_length,data_scale,nullable from user_tab_columns where table_name='~A' and column_name='~A'" table attribute)) ((eq owner :all) (format nil "select data_type,data_length,data_scale,nullable from all_tab_columns where table_name='~A' and column_name='~A'" table attribute)) (t (format nil "select data_type,data_length,data_scale,nullable from user_tab_columns,all_tables where user_tab_columns.table_name='~A' and column_name='~A' and all_tables.table_name=user_tab_columns.table_name and all_tables.owner='~:@(~A~)'" table attribute owner))))) (destructuring-bind (type length scale nullable) (car (database-query query database :auto nil)) (values (ensure-keyword type) length scale (if (char-equal #\Y (schar nullable 0)) 1 0))))) ;; Return one row of the table referred to by QC, represented as a ;; list; or if there are no more rows, signal an error if EOF-ERRORP, ;; or return EOF-VALUE otherwise. ;; KLUDGE: This CASE statement is a strong sign that the code would be ;; cleaner if CD were made into an abstract class, we made variant ;; classes for CD-for-column-of-strings, CD-for-column-of-floats, ;; etc., and defined virtual functions to handle operations like ;; get-an-element-from-column. (For a small special purpose module ;; like this, would arguably be overkill, so I'm not going to do it ;; now, but if this code ends up getting more complicated in ;; maintenance, it would become a really good idea.) ;; Arguably this would be a good place to signal END-OF-FILE, but ;; since the ANSI spec specifically says that END-OF-FILE means a ;; STREAM which has no more data, and QC is not a STREAM, we signal ;; DBI-ERROR instead. (uffi:def-type short-array (* :short)) (uffi:def-type int-array (* :int)) (uffi:def-type double-array (* :double)) (uffi:def-type int-pointer (* :int)) (uffi:def-type double-pointer (* :double)) ;;; the result of a database query: a cursor through a table (defstruct (oracle-result-set (:print-function print-query-cursor) (:conc-name qc-) (:constructor %make-query-cursor)) (db (error "missing DB") ; db conn. this table is associated with :type oracle-database :read-only t) (stmthp (error "missing STMTHP") ; the statement handle used to create ;; :type alien ; this table. owned by the QUERY-CURSOR :read-only t) ; object, deallocated on CLOSE-QUERY (cds) ; (error "missing CDS") ; column descriptors ; :type (simple-array cd 1) ; :read-only t) (n-from-oci 0 ; buffered rows: number of rows recv'd :type (integer 0 #.+n-buf-rows+)) ; from the database on the last read (n-to-dbi 0 ; number of buffered rows returned, i.e. :type (integer 0 #.+n-buf-rows+)) ; the index, within the buffered rows, ; of the next row which hasn't already ; been returned (total-n-from-oci 0 ; total number of bytes recv'd from OCI :type unsigned-byte) ; in all reads (oci-end-seen-p nil)) ; Have we seen the end of OCI ; data, i.e. OCI returning ; less data than we requested? ; OCI doesn't seem to like us ; to try to read more data ; from it after that.. (defun fetch-row (qc &optional (eof-errorp t) eof-value encoding) (declare (optimize (speed 3))) (cond ((zerop (qc-n-from-oci qc)) (if eof-errorp (error 'sql-database-error :message (format nil "no more rows available in ~S" qc)) eof-value)) ((>= (qc-n-to-dbi qc) (qc-n-from-oci qc)) (refill-qc-buffers qc) (fetch-row qc nil eof-value encoding)) (t (let ((cds (qc-cds qc)) (reversed-result nil) (irow (qc-n-to-dbi qc))) (dotimes (icd (length cds)) (let* ((cd (aref cds icd)) (b (foreign-resource-buffer (cd-buffer cd))) (value (let* ((arb (foreign-resource-buffer (cd-indicators cd))) (indicator (uffi:deref-array arb '(:array :short) irow))) (declare (type short-array arb)) (unless (= indicator -1) (ecase (cd-oci-data-type cd) (#.SQLT-STR (deref-oci-string b irow (cd-sizeof cd) encoding)) (#.SQLT-FLT (locally (declare (type double-array b)) (uffi:deref-array b '(:array :double) irow))) (#.SQLT-INT (ecase (cd-sizeof cd) (4 (locally (declare (type int-array b)) (uffi:deref-array b '(:array :int) irow))))) (#.SQLT-DATE (deref-oci-string b irow (cd-sizeof cd) encoding))))))) (when (and (eq :string (cd-result-type cd)) value (not (stringp value))) (setq value (write-to-string value))) (push value reversed-result))) (incf (qc-n-to-dbi qc)) (nreverse reversed-result))))) (defun refill-qc-buffers (qc) (with-slots (errhp) (qc-db qc) (setf (qc-n-to-dbi qc) 0) (cond ((qc-oci-end-seen-p qc) (setf (qc-n-from-oci qc) 0)) (t (let ((oci-code (%oci-stmt-fetch (deref-vp (qc-stmthp qc)) (deref-vp errhp) +n-buf-rows+ +oci-fetch-next+ +oci-default+))) (ecase oci-code (#.+oci-success+ (values)) (#.+oci-no-data+ (setf (qc-oci-end-seen-p qc) t) (values)) (#.+oci-error+ (handle-oci-error :database (qc-db qc) :nulls-ok t)))) (uffi:with-foreign-object (rowcount 'ub4) (oci-attr-get (deref-vp (qc-stmthp qc)) +oci-htype-stmt+ rowcount +unsigned-int-null-pointer+ +oci-attr-row-count+ (deref-vp errhp)) (setf (qc-n-from-oci qc) (- (uffi:deref-pointer rowcount 'ub4) (qc-total-n-from-oci qc))) (when (< (qc-n-from-oci qc) +n-buf-rows+) (setf (qc-oci-end-seen-p qc) t)) (setf (qc-total-n-from-oci qc) (uffi:deref-pointer rowcount 'ub4))))) (values))) ;; the guts of the SQL function ;; ;; (like the SQL function, but with the QUERY argument hardwired to T, so ;; that the return value is always a cursor instead of a list) ;; Is this a SELECT statement? SELECT statements are handled ;; specially by OCIStmtExecute(). (Non-SELECT statements absolutely ;; require a nonzero iteration count, while the ordinary choice for a ;; SELECT statement is a zero iteration count. ;; SELECT statements are the only statements which return tables. We ;; don't free STMTHP in this case, but instead give it to the new ;; QUERY-CURSOR, and the new QUERY-CURSOR becomes responsible for ;; freeing the STMTHP when it is no longer needed. (defun sql-stmt-exec (sql-stmt-string db result-types field-names) (with-slots (envhp svchp errhp) db (uffi:with-foreign-strings ((c-stmt-string sql-stmt-string)) (let ((stmthp (uffi:allocate-foreign-object :pointer-void)) select-p) (uffi:with-foreign-object (stmttype :unsigned-short) (unwind-protect (progn (oci-handle-alloc (deref-vp envhp) stmthp +oci-htype-stmt+ 0 +null-void-pointer-pointer+) (oci-stmt-prepare (deref-vp stmthp) (deref-vp errhp) c-stmt-string (uffi:foreign-string-length c--stmt-string) +oci-ntv-syntax+ +oci-default+ :database db) (oci-attr-get (deref-vp stmthp) +oci-htype-stmt+ stmttype +unsigned-int-null-pointer+ +oci-attr-stmt-type+ (deref-vp errhp) :database db) (setq select-p (= (uffi:deref-pointer stmttype :unsigned-short) 1)) (let ((iters (if select-p 0 1))) (oci-stmt-execute (deref-vp svchp) (deref-vp stmthp) (deref-vp errhp) iters 0 +null-void-pointer+ +null-void-pointer+ +oci-default+ :database db))) ;; free resources unless a query (unless select-p (oci-handle-free (deref-vp stmthp) +oci-htype-stmt+) (uffi:free-foreign-object stmthp)))) (cond (select-p (make-query-cursor db stmthp result-types field-names)) (t nil)))))) ;; Return a QUERY-CURSOR representing the table returned from the OCI ;; operation done through STMTHP. TYPES is the argument of the same ;; name from the external SQL function, controlling type conversion ;; of the returned arguments. (defun make-query-cursor (db stmthp result-types field-names) (let ((qc (%make-query-cursor :db db :stmthp stmthp :cds (make-query-cursor-cds db stmthp result-types field-names)))) (refill-qc-buffers qc) qc)) ;; the hairy part of MAKE-QUERY-CURSOR: Ask OCI for information ;; about table columns, translate the information into a Lisp ;; vector of column descriptors, and return it. ;; Allegro defines several flavors of type conversion, but this ;; implementation only supports the :AUTO flavor. ;; A note of explanation: OCI's internal number format uses 21 ;; bytes (42 decimal digits). 2 separate (?) one-byte fields, ;; scale and precision, are used to deduce the nature of these ;; 21 bytes. See pp. 3-10, 3-26, and 6-13 of OCI documentation ;; for more details. ;; Mac OS X Note: According to table 6-8 in the Oracle 9i OCI ;; documentation, PRECISION may actually be an sb2 instead of a ;; single byte if performing an "implicit describe". Using a ;; signed short instead of an unsigned byte fixes a Mac OS X bug ;; where PRECISION is always zero. -- JJB 20040713 ;; When calling OCI C code to handle the conversion, we have ;; only two numeric types available to pass the return value: ;; double-float and signed-long. It would be possible to ;; bypass the OCI conversion functions and write Lisp code ;; which reads the 21-byte field directly and decodes ;; it. However this is left as an exercise for the reader. :-) ;; The following table describes the mapping, based on the implicit ;; assumption that C's "signed long" type is a 32-bit integer. ;; ;; Internal Values SQL Type C Return Type ;; =============== ======== ============= ;; Precision > 0 SCALE = -127 FLOAT --> double-float ;; Precision > 0 && <=9 SCALE = 0 INTEGER --> signed-long ;; Precision = 0 || > 9 SCALE = 0 BIG INTEGER --> double-float ;; Precision > 0 SCALE > 0 DECIMAL --> double-float ;; (OCI uses 1-based indexing here.) ;; KLUDGE: This should work for all other data types except those ;; which don't actually fit in their fixed-width field (BLOBs and the ;; like). As Winton says, we (Cadabra) don't need to worry much about ;; those, since we can't reason with them, so we don't use them. But ;; for a more general application it'd be good to have a more ;; selective and rigorously correct test here for whether we can ;; actually handle the given DEREF-DTYPE value. -- WHN 20000106 ;; Note: The OCI documentation doesn't seem to say whether the COLNAME ;; value returned here is a newly-allocated copy which we're ;; responsible for freeing, or a pointer into some system copy which ;; will be freed when the system itself is shut down. But judging ;; from the way that the result is used in the cdemodsa.c example ;; program, it looks like the latter: we should make our own copy of ;; the value, but not try to free it. ;; WORKAROUND: OCI seems to return ub2 values for the ;; +oci-attr-data-size+ attribute even though its documentation claims ;; that it returns a ub4, and even though the associated "sizep" value ;; is 4, not 2. In order to make the code here work reliably, without ;; having to patch it later if OCI is ever fixed to match its ;; documentation, we pre-zero COLSIZE before making the call into OCI. ;; To exercise the weird OCI behavior (thereby blowing up the code ;; below, beware!) try setting this value into COLSIZE, calling OCI, ;; then looking at the value in COLSIZE. (setf colsize #x12345678) ;; debugging only ;; Mac OS X Note: This workaround fails on a bigendian platform so ;; I've changed the data type of COLNAME to :unsigned-short as per ;; the Oracle 9i OCI documentation. -- JJB 20040713 (uffi:def-type byte-pointer (* :byte)) (uffi:def-type void-pointer-pointer (* :void-pointer)) (defun make-query-cursor-cds (database stmthp result-types field-names) (declare (optimize (safety 3) #+nil (speed 3)) (type oracle-database database) (type pointer-pointer-void stmthp)) (with-slots (errhp) database (uffi:with-foreign-objects ((dtype-foreign :unsigned-short) (parmdp :pointer-void) (precision :short) (scale :byte) (colname '(* :unsigned-char)) (colnamelen 'ub4) (colsize 'ub2) (defnp ':pointer-void)) (let ((buffer nil) (sizeof nil)) (do ((icolumn 0 (1+ icolumn)) (cds-as-reversed-list nil)) ((not (eql (oci-param-get (deref-vp stmthp) +oci-htype-stmt+ (deref-vp errhp) parmdp (1+ icolumn) :database database) +oci-success+)) (coerce (reverse cds-as-reversed-list) 'simple-vector)) ;; Decode type of ICOLUMNth column into a type we're prepared to ;; handle in Lisp. (oci-attr-get (deref-vp parmdp) +oci-dtype-param+ dtype-foreign +unsigned-int-null-pointer+ +oci-attr-data-type+ (deref-vp errhp)) (let ((dtype (uffi:deref-pointer dtype-foreign :unsigned-short))) (declare (fixnum dtype)) (case dtype (#.SQLT-DATE (setf buffer (acquire-foreign-resource :unsigned-char (* 32 +n-buf-rows+))) (setf sizeof 32 dtype #.SQLT-STR)) (#.SQLT-NUMBER (oci-attr-get (deref-vp parmdp) +oci-dtype-param+ precision +unsigned-int-null-pointer+ +oci-attr-precision+ (deref-vp errhp)) (oci-attr-get (deref-vp parmdp) +oci-dtype-param+ scale +unsigned-int-null-pointer+ +oci-attr-scale+ (deref-vp errhp)) (let ((*scale (uffi:deref-pointer scale :byte)) (*precision (uffi:deref-pointer precision :short))) ;;(format t "scale=~d, precision=~d~%" *scale *precision) (cond ((or (and (minusp *scale) (zerop *precision)) (and (zerop *scale) (plusp *precision))) (setf buffer (acquire-foreign-resource :int +n-buf-rows+) sizeof 4 ;; sizeof(int) dtype #.SQLT-INT)) (t (setf buffer (acquire-foreign-resource :double +n-buf-rows+) sizeof 8 ;; sizeof(double) dtype #.SQLT-FLT))))) ;; Default to SQL-STR (t (setf (uffi:deref-pointer colsize :unsigned-short) 0) (setf dtype #.SQLT-STR) (oci-attr-get (deref-vp parmdp) +oci-dtype-param+ colsize +unsigned-int-null-pointer+ +oci-attr-data-size+ (deref-vp errhp)) (let ((colsize-including-null (1+ (uffi:deref-pointer colsize :unsigned-short)))) (setf buffer (acquire-foreign-resource :unsigned-char (* +n-buf-rows+ colsize-including-null))) (setf sizeof colsize-including-null)))) (let ((retcodes (acquire-foreign-resource :unsigned-short +n-buf-rows+)) (indicators (acquire-foreign-resource :short +n-buf-rows+)) (colname-string "")) (when field-names (oci-attr-get (deref-vp parmdp) +oci-dtype-param+ colname colnamelen +oci-attr-name+ (deref-vp errhp)) (setq colname-string (uffi:convert-from-foreign-string (uffi:deref-pointer colname '(* :unsigned-char)) :length (uffi:deref-pointer colnamelen 'ub4) :encoding (encoding database)))) (push (make-cd :name colname-string :sizeof sizeof :buffer buffer :oci-data-type dtype :retcodes retcodes :indicators indicators :result-type (cond ((consp result-types) (nth icolumn result-types)) ((null result-types) :string) (t result-types))) cds-as-reversed-list) (oci-define-by-pos (deref-vp stmthp) defnp (deref-vp errhp) (1+ icolumn) ; OCI 1-based indexing again (foreign-resource-buffer buffer) sizeof dtype (foreign-resource-buffer indicators) +unsigned-short-null-pointer+ (foreign-resource-buffer retcodes) +oci-default+)))))))) ;; Release the resources associated with a QUERY-CURSOR. (defun close-query (qc) (oci-handle-free (deref-vp (qc-stmthp qc)) +oci-htype-stmt+) (uffi:free-foreign-object (qc-stmthp qc)) (let ((cds (qc-cds qc))) (dotimes (i (length cds)) (release-cd-resources (aref cds i)))) (values)) ;; Release the resources associated with a column description. (defun release-cd-resources (cd) (free-foreign-resource (cd-buffer cd)) (free-foreign-resource (cd-retcodes cd)) (free-foreign-resource (cd-indicators cd)) (values)) (defmethod database-name-from-spec (connection-spec (database-type (eql :oracle))) (check-connection-spec connection-spec database-type (dsn user password)) (destructuring-bind (dsn user password) connection-spec (declare (ignore password)) (concatenate 'string dsn "/" user))) (defmethod database-connect (connection-spec (database-type (eql :oracle))) (check-connection-spec connection-spec database-type (dsn user password)) (destructuring-bind (data-source-name user password) connection-spec (let ((envhp (uffi:allocate-foreign-object :pointer-void)) (errhp (uffi:allocate-foreign-object :pointer-void)) (svchp (uffi:allocate-foreign-object :pointer-void)) (srvhp (uffi:allocate-foreign-object :pointer-void))) ;; Requests to allocate environments and handles should never ;; fail in normal operation, and they're done too early to ;; handle errors very gracefully (since they're part of the ;; error-handling mechanism themselves) so we just assert they ;; work. (setf (deref-vp envhp) +null-void-pointer+) #-oci7 (oci-env-create envhp +oci-default+ +null-void-pointer+ +null-void-pointer+ +null-void-pointer+ +null-void-pointer+ 0 +null-void-pointer-pointer+) #+oci7 (progn (oci-initialize +oci-object+ +null-void-pointer+ +null-void-pointer+ +null-void-pointer+ +null-void-pointer-pointer+) (ignore-errors (oci-handle-alloc +null-void-pointer+ envhp +oci-htype-env+ 0 +null-void-pointer-pointer+)) ;no testing return (oci-env-init envhp +oci-default+ 0 +null-void-pointer-pointer+)) (oci-handle-alloc (deref-vp envhp) errhp +oci-htype-error+ 0 +null-void-pointer-pointer+) (oci-handle-alloc (deref-vp envhp) srvhp +oci-htype-server+ 0 +null-void-pointer-pointer+) (let ((db (make-instance 'oracle-database :name (database-name-from-spec connection-spec database-type) :connection-spec connection-spec :envhp envhp :errhp errhp :database-type :oracle :svchp svchp :dsn data-source-name :user user))) (uffi:with-foreign-strings ((c-user user) (c-password password) (c-data-source-name data-source-name)) (oci-logon (deref-vp envhp) (deref-vp errhp) svchp c-user (length user) c-password (length password) c-data-source-name (length data-source-name) :database db)) ;; :date-format-length (1+ (length date-format))))) (setf (slot-value db 'clsql-sys::state) :open) (database-execute-command (format nil "ALTER SESSION SET NLS_DATE_FORMAT='~A'" (date-format db)) db) (let ((server-version (caar (database-query "SELECT BANNER FROM V$VERSION WHERE BANNER LIKE '%Oracle%'" db nil nil)))) (setf (slot-value db 'server-version) server-version (slot-value db 'major-server-version) (major-client-version-from-string server-version))) db)))) (defun major-client-version-from-string (str) (cond ((search " 10g " str) 10) ((search "Oracle9i " str) 9) ((search "Oracle8" str) 8))) (defun major-server-version-from-string (str) (when (> (length str) 2) (cond ((string= "10." (subseq str 0 3)) 10) ((string= "9." (subseq str 0 2)) 9) ((string= "8." (subseq str 0 2)) 8)))) ;; Close a database connection. (defmethod database-disconnect ((database oracle-database)) (osucc (oci-logoff (deref-vp (svchp database)) (deref-vp (errhp database)))) (osucc (oci-handle-free (deref-vp (envhp database)) +oci-htype-env+)) ;; Note: It's neither required nor allowed to explicitly deallocate the ;; ERRHP handle here, since it's owned by the ENVHP deallocated above, ;; and was therefore automatically deallocated at the same time. t) ;;; Do the database operation described in SQL-STMT-STRING on database ;;; DB and, if the command is a SELECT, return a representation of the ;;; resulting table. The representation of the table is controlled by the ;;; QUERY argument: ;;; * If QUERY is NIL, the table is returned as a list of rows, with ;;; each row represented by a list. ;;; * If QUERY is non-NIL, the result is returned as a QUERY-CURSOR ;;; suitable for FETCH-ROW and CLOSE-QUERY ;;; The TYPES argument controls the type conversion method used ;;; to construct the table. The Allegro version supports several possible ;;; values for this argument, but we only support :AUTO. (defmethod database-query (query-expression (database oracle-database) result-types field-names) (let ((cursor (sql-stmt-exec query-expression database result-types field-names))) ;; (declare (type (or query-cursor null) cursor)) (if (null cursor) ; No table was returned. (values) (do ((reversed-result nil)) (nil) (let* ((eof-value :eof) (row (fetch-row cursor nil eof-value (encoding database)))) (when (eq row eof-value) (close-query cursor) (if field-names (return (values (nreverse reversed-result) (loop for cd across (qc-cds cursor) collect (cd-name cd)))) (return (nreverse reversed-result)))) (push row reversed-result)))))) (defmethod database-create-sequence (sequence-name (database oracle-database)) (execute-command (concatenate 'string "CREATE SEQUENCE " (sql-escape sequence-name)) :database database)) (defmethod database-drop-sequence (sequence-name (database oracle-database)) (execute-command (concatenate 'string "DROP SEQUENCE " (sql-escape sequence-name)) :database database)) (defmethod database-sequence-next (sequence-name (database oracle-database)) (caar (database-query (concatenate 'string "SELECT " (sql-escape sequence-name) ".NEXTVAL FROM dual") database :auto nil))) (defmethod database-sequence-last (sequence-name (database oracle-database)) (caar (database-query (concatenate 'string "SELECT " (sql-escape sequence-name) ".CURRVAL FROM dual") database :auto nil))) (defmethod database-set-sequence-position (name position (database oracle-database)) (without-interrupts (let* ((next (database-sequence-next name database)) (incr (- position next))) (unless (zerop incr) (database-execute-command (format nil "ALTER SEQUENCE ~A INCREMENT BY ~D" name incr) database)) (database-sequence-next name database) (database-execute-command (format nil "ALTER SEQUENCE ~A INCREMENT BY 1" name) database)))) (defmethod database-list-sequences ((database oracle-database) &key owner) (let ((query (cond ((null owner) "select sequence_name from user_sequences") ((eq owner :all) "select sequence_name from all_sequences") (t (format nil "select user_sequences.sequence_name from user_sequences,all_sequences where user_sequences.sequence_name=all_sequences.sequence_name and all_sequences.sequence_owner='~:@(~A~)'" owner))))) (mapcar #'car (database-query query database nil nil)))) (defmethod database-execute-command (sql-expression (database oracle-database)) (database-query sql-expression database nil nil) (when (database-autocommit database) (oracle-commit database)) t) (defstruct (cd (:constructor make-cd) (:print-function print-cd)) "a column descriptor: metadata about the data in a table" ;; name of this column (name (error "missing NAME") :type simple-string :read-only t) ;; the size in bytes of a single element (sizeof (error "missing SIZE") :type fixnum :read-only t) ;; an array of +N-BUF-ROWS+ elements in C representation (buffer (error "Missing BUFFER") :type foreign-resource :read-only t) ;; an array of +N-BUF-ROWS+ OCI return codes in C representation. ;; (There must be one return code for every element of every ;; row in order to be able to represent nullness.) (retcodes (error "Missing RETCODES") :type foreign-resource :read-only t) (indicators (error "Missing INDICATORS") :type foreign-resource :read-only t) ;; the OCI code for the data type of a single element (oci-data-type (error "missing OCI-DATA-TYPE") :type fixnum :read-only t) (result-type (error "missing RESULT-TYPE") :read-only t)) (defun print-cd (cd stream depth) (declare (ignore depth)) (print-unreadable-object (cd stream :type t) (format stream ":NAME ~S :OCI-DATA-TYPE ~S :OCI-DATA-SIZE ~S" (cd-name cd) (cd-oci-data-type cd) (cd-sizeof cd)))) (defun print-query-cursor (qc stream depth) (declare (ignore depth)) (print-unreadable-object (qc stream :type t :identity t) (prin1 (qc-db qc) stream))) (defmethod database-query-result-set ((query-expression string) (database oracle-database) &key full-set result-types) (let ((cursor (sql-stmt-exec query-expression database result-types nil))) (if full-set (values cursor (length (qc-cds cursor)) nil) (values cursor (length (qc-cds cursor)))))) (defmethod database-dump-result-set (result-set (database oracle-database)) (close-query result-set)) (defmethod database-store-next-row (result-set (database oracle-database) list) (let* ((eof-value :eof) (row (fetch-row result-set nil eof-value (encoding database)))) (unless (eq eof-value row) (loop for i from 0 below (length row) do (setf (nth i list) (nth i row))) list))) (defmethod database-start-transaction ((database oracle-database)) (call-next-method) ;; Not needed with simple transaction #+ignore (with-slots (svchp errhp) database (oci-trans-start (deref-vp svchp) (deref-vp errhp) 60 +oci-trans-new+)) t) (defun oracle-commit (database) (with-slots (svchp errhp) database (osucc (oci-trans-commit (deref-vp svchp) (deref-vp errhp) 0)))) (defmethod database-commit-transaction ((database oracle-database)) (call-next-method) (oracle-commit database) t) (defmethod database-abort-transaction ((database oracle-database)) (call-next-method) (osucc (oci-trans-rollback (deref-vp (svchp database)) (deref-vp (errhp database)) 0)) t) ;; Specifications (defmethod db-type-has-bigint? ((type (eql :oracle))) nil) (defmethod db-type-has-fancy-math? ((db-type (eql :oracle))) t) (defmethod db-type-has-boolean-where? ((db-type (eql :oracle))) nil) (when (clsql-sys:database-type-library-loaded :oracle) (clsql-sys:initialize-database-type :database-type :oracle)) cl-sql-6.4.1/db-oracle/oracle-constants.lisp0000644000175000017500000006553611335067642017755 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; FILE IDENTIFICATION ;;;; ;;;; Name: oracle-constants.lisp ;;;; Purpose: Constants for CLSQL Oracle interface ;;;; ;;;; This file is part of CLSQL. ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* (in-package #:clsql-oracle) (defconstant +oci-default+ #x00) ; default value for parameters and attributes (defconstant +oci-threaded+ #x01) ; application is in threaded environment (defconstant +oci-object+ #x02) ; the application is in object environment (defconstant +oci-non-blocking+ #x04) ; non blocking mode of operation (defconstant +oci-env-no-mutex+ #x08) ; the environment handle will not be protected by a mutex internally ;; Handle types (defconstant +oci-htype-env+ 1) ; environment handle (defconstant +oci-htype-error+ 2) ; error handle (defconstant +oci-htype-svcctx+ 3) ; service handle (defconstant +oci-htype-stmt+ 4) ; statement handle (defconstant +oci-htype-bind+ 5) ; bind handle (defconstant +oci-htype-define+ 6) ; define handle (defconstant +oci-htype-describe+ 7) ; describe handle (defconstant +oci-htype-server+ 8) ; server handle (defconstant +oci-htype-session+ 9) ; authentication handle (defconstant +oci-htype-trans+ 10) ; transaction handle (defconstant +oci-htype-complexobject+ 11) ; complex object retrieval handle (defconstant +oci-htype-security+ 12) ; security handle ;; Descriptor types (defconstant +oci-dtype-lob+ 50) ; lob locator (defconstant +oci-dtype-snap+ 51) ; snapshot (defconstant +oci-dtype-rset+ 52) ; result set (defconstant +oci-dtype-param+ 53) ; parameter descriptor obtained from ocigparm (defconstant +oci-dtype-rowid+ 54) ; rowid (defconstant +oci-dtype-complexobjectcomp+ 55) ; complex object retrieval descriptor (defconstant +oci-dtype-file+ 56) ; File Lob locator (defconstant +oci-dtype-aqenq-options+ 57) ; enqueue options (defconstant +oci-dtype-aqdeq-options+ 58) ; dequeue options (defconstant +oci-dtype-aqmsg-properties+ 59) ; message properties (defconstant +oci-dtype-aqagent+ 60) ; aq agent ;; Objectr pointer types (defconstant +oci-otype-name+ 1) ; object name (defconstant +oci-otype-ref+ 2) ; REF to TDO (defconstant +oci-otype-ptr+ 3) ; PTR to TDO ;; Attribute types (defconstant +oci-attr-fncode+ 1) ; the OCI function code (defconstant +oci-attr-object+ 2) ; is the environment initialized in object mode (defconstant +oci-attr-nonblocking-mode+ 3) ; non blocking mode (defconstant +oci-attr-sqlcode+ 4) ; the SQL verb (defconstant +oci-attr-env+ 5) ; the environment handle (defconstant +oci-attr-server+ 6) ; the server handle (defconstant +oci-attr-session+ 7) ; the user session handle (defconstant +oci-attr-trans+ 8) ; the transaction handle (defconstant +oci-attr-row-count+ 9) ; the rows processed so far (defconstant +oci-attr-sqlfncode+ 10) ; the SQL verb of the statement (defconstant +oci-attr-prefetch-rows+ 11) ; sets the number of rows to prefetch (defconstant +oci-attr-nested-prefetch-rows+ 12) ; the prefetch rows of nested table (defconstant +oci-attr-prefetch-memory+ 13) ; memory limit for rows fetched (defconstant +oci-attr-nested-prefetch-memory+ 14) ; memory limit for nested rows (defconstant +oci-attr-char-count+ 15) ; this specifies the bind and define size in characters (defconstant +oci-attr-pdscl+ 16) ; packed decimal scale (defconstant +oci-attr-pdfmt+ 17) ; packed decimal format (defconstant +oci-attr-param-count+ 18) ; number of column in the select list (defconstant +oci-attr-rowid+ 19) ; the rowid (defconstant +oci-attr-charset+ 20) ; the character set value (defconstant +oci-attr-nchar+ 21) ; NCHAR type (defconstant +oci-attr-username+ 22) ; username attribute (defconstant +oci-attr-password+ 23) ; password attribute (defconstant +oci-attr-stmt-type+ 24) ; statement type (defconstant +oci-attr-internal-name+ 25) ; user friendly global name (defconstant +oci-attr-external-name+ 26) ; the internal name for global txn (defconstant +oci-attr-xid+ 27) ; XOPEN defined global transaction id (defconstant +oci-attr-trans-lock+ 28) ; (defconstant +oci-attr-trans-name+ 29) ; string to identify a global transaction (defconstant +oci-attr-heapalloc+ 30) ; memory allocated on the heap (defconstant +oci-attr-charset-id+ 31) ; Character Set ID (defconstant +oci-attr-charset-form+ 32) ; Character Set Form (defconstant +oci-attr-maxdata-size+ 33) ; Maximumsize of data on the server (defconstant +oci-attr-cache-opt-size+ 34) ; object cache optimal size (defconstant +oci-attr-cache-max-size+ 35) ; object cache maximum size percentage (defconstant +oci-attr-pinoption+ 36) ; object cache default pin option (defconstant +oci-attr-alloc-duration+ 37) ; object cache default allocation duration (defconstant +oci-attr-pin-duration+ 38) ; object cache default pin duration (defconstant +oci-attr-fdo+ 39) ; Format Descriptor object attribute (defconstant +oci-attr-postprocessing-callback+ 40) ; Callback to process outbind data (defconstant +oci-attr-postprocessing-context+ 41) ; Callback context to process outbind data (defconstant +oci-attr-rows-returned+ 42) ; Number of rows returned in current iter - for Bind handles (defconstant +oci-attr-focbk+ 43) ; Failover Callback attribute (defconstant +oci-attr-in-v8-mode+ 44) ; is the server/service context in V8 mode (defconstant +oci-attr-lobempty+ 45) ; empty lob ? (defconstant +oci-attr-sesslang+ 46) ; session language handle ;; AQ Attribute Types ;; Enqueue Options (defconstant +oci-attr-visibility+ 47) ; visibility (defconstant +oci-attr-relative-msgid+ 48) ; relative message id (defconstant +oci-attr-sequence-deviation+ 49) ; sequence deviation ; - Dequeue Options - ; consumer name ;#define OCI-ATTR-DEQ-MODE 50 ;(defconstant +OCI-ATTR-CONSUMER-NAME 50 + 51) ; dequeue mode ;#define OCI-ATTR-NAVIGATION 52 ; navigation ;#define OCI-ATTR-WAIT 53 ; wait ;#define OCI-ATTR-DEQ-MSGID 54 ; dequeue message id ; - Message Properties - (defconstant +OCI-ATTR-PRIORITY+ 55) ; priority (defconstant +OCI-ATTR-DELAY+ 56) ; delay (defconstant +OCI-ATTR-EXPIRATION+ 57) ; expiration (defconstant +OCI-ATTR-CORRELATION+ 58) ; correlation id (defconstant +OCI-ATTR-ATTEMPTS+ 59) ; # of attempts (defconstant +OCI-ATTR-RECIPIENT-LIST+ 60) ; recipient list (defconstant +OCI-ATTR-EXCEPTION-QUEUE+ 61) ; exception queue name (defconstant +OCI-ATTR-ENQ-TIME+ 62) ; enqueue time (only OCIAttrGet) (defconstant +OCI-ATTR-MSG-STATE+ 63) ; message state (only OCIAttrGet) ;; AQ Agent (defconstant +OCI-ATTR-AGENT-NAME+ 64) ; agent name (defconstant +OCI-ATTR-AGENT-ADDRESS+ 65) ; agent address (defconstant +OCI-ATTR-AGENT-PROTOCOL+ 66) ; agent protocol ;- Server handle - (defconstant +OCI-ATTR-NATIVE-FDES+ 67) ; native cncxn file desc ;-Parameter Attribute Types- (defconstant +OCI-ATTR-UNK+ 101) ; unknown attribute (defconstant +OCI-ATTR-NUM-COLS+ 102) ; number of columns (defconstant +OCI-ATTR-LIST-COLUMNS+ 103) ; parameter of the column list (defconstant +OCI-ATTR-RDBA+ 104) ; DBA of the segment header (defconstant +OCI-ATTR-CLUSTERED+ 105) ; whether the table is clustered (defconstant +OCI-ATTR-PARTITIONED+ 106) ; whether the table is partitioned (defconstant +OCI-ATTR-INDEX-ONLY+ 107) ; whether the table is index only (defconstant +OCI-ATTR-LIST-ARGUMENTS+ 108) ; parameter of the argument list (defconstant +OCI-ATTR-LIST-SUBPROGRAMS+ 109) ; parameter of the subprogram list (defconstant +OCI-ATTR-REF-TDO+ 110) ; REF to the type descriptor (defconstant +OCI-ATTR-LINK+ 111) ; the database link name (defconstant +OCI-ATTR-MIN+ 112) ; minimum value (defconstant +OCI-ATTR-MAX+ 113) ; maximum value (defconstant +OCI-ATTR-INCR+ 114) ; increment value (defconstant +OCI-ATTR-CACHE+ 115) ; number of sequence numbers cached (defconstant +OCI-ATTR-ORDER+ 116) ; whether the sequence is ordered (defconstant +OCI-ATTR-HW-MARK+ 117) ; high-water mark (defconstant +OCI-ATTR-TYPE-SCHEMA+ 118) ; type's schema name (defconstant +OCI-ATTR-TIMESTAMP+ 119) ; timestamp of the object (defconstant +OCI-ATTR-NUM-ATTRS+ 120) ; number of sttributes (defconstant +OCI-ATTR-NUM-PARAMS+ 121) ; number of parameters (defconstant +OCI-ATTR-OBJID+ 122) ; object id for a table or view (defconstant +OCI-ATTR-PTYPE+ 123) ; type of info described by (defconstant +OCI-ATTR-PARAM+ 124) ; parameter descriptor (defconstant +OCI-ATTR-OVERLOAD-ID+ 125) ; overload ID for funcs and procs (defconstant +OCI-ATTR-TABLESPACE+ 126) ; table name space (defconstant +OCI-ATTR-TDO+ 127) ; TDO of a type (defconstant +OCI-ATTR-PARSE-ERROR-OFFSET+ 128) ; Parse Error offset ;-Credential Types- (defconstant +OCI-CRED-RDBMS+ 1) ; database username/password (defconstant +OCI-CRED-EXT+ 2) ; externally provided credentials ;; Error Return Values- (defconstant +oci-continue+ -24200) ; Continue with the body of the OCI function (defconstant +oci-still-executing+ -3123) ; OCI would block error (defconstant +oci-invalid-handle+ -2) ; maps to SQL-INVALID-HANDLE (defconstant +oci-error+ -1) ; maps to SQL-ERROR (defconstant +oci-success+ 0) ; maps to SQL-SUCCESS of SAG CLI (defconstant +oci-success-with-info+ 1) ; maps to SQL-SUCCESS-WITH-INFO (defconstant +oci-need-data+ 99) ; maps to SQL-NEED-DATA (defconstant +oci-no-data+ 100) ; maps to SQL-NO-DATA ;; Parsing Syntax Types- (defconstant +oci-ntv-syntax+ 1) ; Use what so ever is the native lang of server (defconstant +oci-v7-syntax+ 2) ; V7 language (defconstant +oci-v8-syntax+ 3) ; V8 language ;-Scrollable Cursor Options- (defconstant +oci-fetch-next+ #x02) ; next row (defconstant +oci-fetch-first+ #x04) ; first row of the result set (defconstant +oci-fetch-last+ #x08) ; the last row of the result set (defconstant +oci-fetch-prior+ #x10) ; the previous row relative to current (defconstant +oci-fetch-absolute+ #x20) ; absolute offset from first (defconstant +oci-fetch-relative+ #x40) ; offset relative to current ;-Bind and Define Options- (defconstant +OCI-SB2-IND-PTR+ #x01) ; unused (defconstant +OCI-DATA-AT-EXEC+ #x02) ; data at execute time (defconstant +OCI-DYNAMIC-FETCH+ #x02) ; fetch dynamically (defconstant +OCI-PIECEWISE+ #x04) ; piecewise DMLs or fetch ;- ;-Execution Modes- (defconstant +OCI-BATCH-MODE+ #x01) ; batch the oci statement for execution (defconstant +OCI-EXACT-FETCH+ #x02) ; fetch the exact rows specified (defconstant +OCI-KEEP-FETCH-STATE+ #x04) ; unused (defconstant +OCI-SCROLLABLE-CURSOR+ #x08) ; cursor scrollable (defconstant +OCI-DESCRIBE-ONLY+ #x10) ; only describe the statement (defconstant +OCI-COMMIT-ON-SUCCESS+ #x20) ; commit, if successful execution ;- ;-Authentication Modes- (defconstant +OCI-MIGRATE+ #x0001) ; migratable auth context (defconstant +OCI-SYSDBA+ #x0002) ; for SYSDBA authorization (defconstant +OCI-SYSOPER+ #x0004) ; for SYSOPER authorization (defconstant +OCI-PRELIM-AUTH+ #x0008) ; for preliminary authorization ;- ;-Piece Information- (defconstant +OCI-PARAM-IN+ #x01) ; in parameter (defconstant +OCI-PARAM-OUT+ #x02) ; out parameter ;- ;- Transaction Start Flags - ; NOTE: OCI-TRANS-JOIN and OCI-TRANS-NOMIGRATE not supported in 8.0.X (defconstant +OCI-TRANS-NEW+ #x00000001) ; starts a new transaction branch (defconstant +OCI-TRANS-JOIN+ #x00000002) ; join an existing transaction (defconstant +OCI-TRANS-RESUME+ #x00000004) ; resume this transaction (defconstant +OCI-TRANS-STARTMASK+ #x000000ff) (defconstant +OCI-TRANS-READONLY+ #x00000100) ; starts a readonly transaction (defconstant +OCI-TRANS-READWRITE+ #x00000200) ; starts a read-write transaction (defconstant +OCI-TRANS-SERIALIZABLE+ #x00000400) ; starts a serializable transaction (defconstant +OCI-TRANS-ISOLMASK+ #x0000ff00) (defconstant +OCI-TRANS-LOOSE+ #x00010000) ; a loosely coupled branch (defconstant +OCI-TRANS-TIGHT+ #x00020000) ; a tightly coupled branch (defconstant +OCI-TRANS-TYPEMASK+ #x000f0000) ; (defconstant +OCI-TRANS-NOMIGRATE+ #x00100000) ; non migratable transaction ;- ;- Transaction End Flags - (defconstant +OCI-TRANS-TWOPHASE+ #x01000000) ; use two phase commit ;- ;; AQ Constants ;; NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE ;; The following constants must match the PL/SQL dbms-aq constants ;; NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE ; - Visibility flags - (defconstant +OCI-ENQ-IMMEDIATE+ 1) ; enqueue is an independent transaction (defconstant +OCI-ENQ-ON-COMMIT+ 2) ; enqueue is part of current transaction ; - Dequeue mode flags - (defconstant +OCI-DEQ-BROWSE+ 1) ; read message without acquiring a lock (defconstant +OCI-DEQ-LOCKED+ 2) ; read and obtain write lock on message (defconstant +OCI-DEQ-REMOVE+ 3) ; read the message and delete it ; - Dequeue navigation flags - (defconstant +OCI-DEQ-FIRST-MSG+ 1) ; get first message at head of queue (defconstant +OCI-DEQ-NEXT-MSG+ 3) ; next message that is available (defconstant +OCI-DEQ-NEXT-TRANSACTION+ 2) ; get first message of next txn group ; - Message states - (defconstant +OCI-MSG-WAITING+ 1) ; the message delay has not yet completed (defconstant +OCI-MSG-READY+ 0) ; the message is ready to be processed (defconstant +OCI-MSG-PROCESSED+ 2) ; the message has been processed (defconstant +OCI-MSG-EXPIRED+ 3) ; message has moved to exception queue ; - Sequence deviation - (defconstant +OCI-ENQ-BEFORE+ 2) ; enqueue message before another message (defconstant +OCI-ENQ-TOP+ 3) ; enqueue message before all messages ; - Visibility flags - (defconstant +OCI-DEQ-IMMEDIATE+ 1) ; dequeue is an independent transaction (defconstant +OCI-DEQ-ON-COMMIT+ 2) ; dequeue is part of current transaction ; - Wait - (defconstant +OCI-DEQ-WAIT-FOREVER+ -1) ; wait forever if no message available (defconstant +OCI-DEQ-NO-WAIT+ 0) ; do not wait if no message is available ; - Delay - (defconstant +OCI-MSG-NO-DELAY+ 0) ; message is available immediately ;; Expiration (defconstant +OCI-MSG-NO-EXPIRATION+ -1) ; message will never expire ;; Describe Handle Parameter Attributes ;; Attributes common to Columns and Stored Procs (defconstant +oci-attr-data-size+ 1) ; maximum size of the data (defconstant +oci-attr-data-type+ 2) ; the sql type of the column/argument (defconstant +oci-attr-disp-size+ 3) ; the display size (defconstant +oci-attr-name+ 4) ; the name of the column/argument (defconstant +oci-attr-precision+ 5) ; precision if number type (defconstant +oci-attr-scale+ 6) ; scale if number type (defconstant +oci-attr-is-null+ 7) ; is it null ? (defconstant +oci-attr-type-name+ 8) ;; name of the named data type or a package name for package private types (defconstant +OCI-ATTR-SCHEMA-NAME+ 9) ; the schema name (defconstant +OCI-ATTR-SUB-NAME+ 10) ; type name if package private type (defconstant +OCI-ATTR-POSITION+ 11) ; relative position of col/arg in the list of cols/args ; complex object retrieval parameter attributes (defconstant +OCI-ATTR-COMPLEXOBJECTCOMP-TYPE+ 50) ; (defconstant +OCI-ATTR-COMPLEXOBJECTCOMP-TYPE-LEVEL+ 51) ; (defconstant +OCI-ATTR-COMPLEXOBJECT-LEVEL+ 52) ; (defconstant +OCI-ATTR-COMPLEXOBJECT-COLL-OUTOFLINE+ 53) ; ; Only Columns (defconstant +OCI-ATTR-DISP-NAME+ 100) ; the display name ;; stored procs (defconstant +OCI-ATTR-OVERLOAD+ 210) ; is this position overloaded (defconstant +OCI-ATTR-LEVEL+ 211) ; level for structured types (defconstant +OCI-ATTR-HAS-DEFAULT+ 212) ; has a default value (defconstant +OCI-ATTR-IOMODE+ 213) ; in, out inout (defconstant +OCI-ATTR-RADIX+ 214) ; returns a radix (defconstant +OCI-ATTR-NUM-ARGS+ 215) ; total number of arguments ;; named type attributes (defconstant +oci-attr-typecode+ 216) ; lobject or collection (defconstant +oci-attr-collection-typecode+ 217) ; varray or nested table (defconstant +oci-attr-version+ 218) ; user assigned version (defconstant +oci-attr-is-incomplete-type+ 219) ; is this an incomplete type (defconstant +oci-attr-is-system-type+ 220) ; a system type (defconstant +oci-attr-is-predefined-type+ 221) ; a predefined type (defconstant +oci-attr-is-transient-type+ 222) ; a transient type (defconstant +oci-attr-is-system-generated-type+ 223) ; system generated type (defconstant +oci-attr-has-nested-table+ 224) ; contains nested table attr (defconstant +oci-attr-has-lob+ 225) ; has a lob attribute (defconstant +oci-attr-has-file+ 226) ; has a file attribute (defconstant +oci-attr-collection-element+ 227) ; has a collection attribute (defconstant +oci-attr-num-type-attrs+ 228) ; number of attribute types (defconstant +oci-attr-list-type-attrs+ 229) ; list of type attributes (defconstant +oci-attr-num-type-methods+ 230) ; number of type methods (defconstant +oci-attr-list-type-methods+ 231) ; list of type methods (defconstant +oci-attr-map-method+ 232) ; map method of type (defconstant +oci-attr-order-method+ 233) ; order method of type ; only collection element (defconstant +OCI-ATTR-NUM-ELEMS+ 234) ; number of elements ; only type methods (defconstant +OCI-ATTR-ENCAPSULATION+ 235) ; encapsulation level (defconstant +OCI-ATTR-IS-SELFISH+ 236) ; method selfish (defconstant +OCI-ATTR-IS-VIRTUAL+ 237) ; virtual (defconstant +OCI-ATTR-IS-INLINE+ 238) ; inline (defconstant +OCI-ATTR-IS-CONSTANT+ 239) ; constant (defconstant +OCI-ATTR-HAS-RESULT+ 240) ; has result (defconstant +OCI-ATTR-IS-CONSTRUCTOR+ 241) ; constructor (defconstant +OCI-ATTR-IS-DESTRUCTOR+ 242) ; destructor (defconstant +OCI-ATTR-IS-OPERATOR+ 243) ; operator (defconstant +OCI-ATTR-IS-MAP+ 244) ; a map method (defconstant +OCI-ATTR-IS-ORDER+ 245) ; order method (defconstant +OCI-ATTR-IS-RNDS+ 246) ; read no data state method (defconstant +OCI-ATTR-IS-RNPS+ 247) ; read no process state (defconstant +OCI-ATTR-IS-WNDS+ 248) ; write no data state method (defconstant +OCI-ATTR-IS-WNPS+ 249) ; write no process state ; describing public objects (defconstant +OCI-ATTR-DESC-PUBLIC+ 250) ; public object ;- ;-OCIPasswordChange- (defconstant +OCI-AUTH+ #x08) ; Change the password but do not login ;-Other Constants- (defconstant +OCI-MAX-FNS+ 100) ; max number of OCI Functions (defconstant +OCI-SQLSTATE-SIZE+ 5) ; (defconstant +OCI-ERROR-MAXMSG-SIZE+ 1024) ; max size of an error message ;; (defconstant +OCI-LOBMAXSIZE+ 4MAXVAL) ; maximum lob data size (defconstant +OCI-ROWID-LEN+ 23) ; ;- ;- Fail Over Events - (defconstant +OCI-FO-END+ #x00000001) ; (defconstant +OCI-FO-ABORT+ #x00000002) ; (defconstant +OCI-FO-REAUTH+ #x00000004) ; (defconstant +OCI-FO-BEGIN+ #x00000008) ; (defconstant +OCI-FO-ERROR+ #x00000010) ; ;- ;- Fail Over Types - (defconstant +OCI-FO-NONE+ #x00000001) ; (defconstant +OCI-FO-SESSION+ #x00000002) ; (defconstant +OCI-FO-SELECT+ #x00000004) ; (defconstant +OCI-FO-TXNAL+ #x00000008) ; ;- ;-Function Codes- (defconstant +OCI-FNCODE-INITIALIZE+ 1) ; OCIInitialize (defconstant +OCI-FNCODE-HANDLEALLOC+ 2) ; OCIHandleAlloc (defconstant +OCI-FNCODE-HANDLEFREE+ 3) ; OCIHandleFree (defconstant +OCI-FNCODE-DESCRIPTORALLOC+ 4) ; OCIDescriptorAlloc (defconstant +OCI-FNCODE-DESCRIPTORFREE+ 5) ; OCIDescriptorFree (defconstant +OCI-FNCODE-ENVINIT+ 6) ; OCIEnvInit (defconstant +OCI-FNCODE-SERVERATTACH+ 7) ; OCIServerAttach (defconstant +OCI-FNCODE-SERVERDETACH+ 8) ; OCIServerDetach ; unused 9 (defconstant +OCI-FNCODE-SESSIONBEGIN+ 10) ; OCISessionBegin (defconstant +OCI-FNCODE-SESSIONEND+ 11) ; OCISessionEnd (defconstant +OCI-FNCODE-PASSWORDCHANGE+ 12) ; OCIPasswordChange (defconstant +OCI-FNCODE-STMTPREPARE+ 13) ; OCIStmtPrepare ; unused 14- 16 (defconstant +OCI-FNCODE-BINDDYNAMIC+ 17) ; OCIBindDynamic (defconstant +OCI-FNCODE-BINDOBJECT+ 18) ; OCIBindObject ; 19 unused (defconstant +OCI-FNCODE-BINDARRAYOFSTRUCT+ 20) ; OCIBindArrayOfStruct (defconstant +OCI-FNCODE-STMTEXECUTE+ 21) ; OCIStmtExecute ; unused 22-24 (defconstant +OCI-FNCODE-DEFINEOBJECT+ 25) ; OCIDefineObject (defconstant +OCI-FNCODE-DEFINEDYNAMIC+ 26) ; OCIDefineDynamic (defconstant +OCI-FNCODE-DEFINEARRAYOFSTRUCT+ 27) ; OCIDefineArrayOfStruct (defconstant +OCI-FNCODE-STMTFETCH+ 28) ; OCIStmtFetch (defconstant +OCI-FNCODE-STMTGETBIND+ 29) ; OCIStmtGetBindInfo ; 30, 31 unused (defconstant +OCI-FNCODE-DESCRIBEANY+ 32) ; OCIDescribeAny (defconstant +OCI-FNCODE-TRANSSTART+ 33) ; OCITransStart (defconstant +OCI-FNCODE-TRANSDETACH+ 34) ; OCITransDetach (defconstant +OCI-FNCODE-TRANSCOMMIT+ 35) ; OCITransCommit ; 36 unused (defconstant +OCI-FNCODE-ERRORGET+ 37) ; OCIErrorGet (defconstant +OCI-FNCODE-LOBOPENFILE+ 38) ; OCILobFileOpen (defconstant +OCI-FNCODE-LOBCLOSEFILE+ 39) ; OCILobFileClose ; 40 was LOBCREATEFILE, unused ; 41 was OCILobFileDelete, unused (defconstant +OCI-FNCODE-LOBCOPY+ 42) ; OCILobCopy (defconstant +OCI-FNCODE-LOBAPPEND+ 43) ; OCILobAppend (defconstant +OCI-FNCODE-LOBERASE+ 44) ; OCILobErase (defconstant +OCI-FNCODE-LOBLENGTH+ 45) ; OCILobGetLength (defconstant +OCI-FNCODE-LOBTRIM+ 46) ; OCILobTrim (defconstant +OCI-FNCODE-LOBREAD+ 47) ; OCILobRead (defconstant +OCI-FNCODE-LOBWRITE+ 48) ; OCILobWrite ; 49 unused (defconstant +OCI-FNCODE-SVCCTXBREAK+ 50) ; OCIBreak (defconstant +OCI-FNCODE-SERVERVERSION+ 51) ; OCIServerVersion ; unused 52, 53 (defconstant +OCI-FNCODE-ATTRGET+ 54) ; OCIAttrGet (defconstant +OCI-FNCODE-ATTRSET+ 55) ; OCIAttrSet (defconstant +OCI-FNCODE-PARAMSET+ 56) ; OCIParamSet (defconstant +OCI-FNCODE-PARAMGET+ 57) ; OCIParamGet (defconstant +OCI-FNCODE-STMTGETPIECEINFO+ 58) ; OCIStmtGetPieceInfo (defconstant +OCI-FNCODE-LDATOSVCCTX+ 59) ; OCILdaToSvcCtx ; 60 unused (defconstant +OCI-FNCODE-STMTSETPIECEINFO+ 61) ; OCIStmtSetPieceInfo (defconstant +OCI-FNCODE-TRANSFORGET+ 62) ; OCITransForget (defconstant +OCI-FNCODE-TRANSPREPARE+ 63) ; OCITransPrepare (defconstant +OCI-FNCODE-TRANSROLLBACK+ 64) ; OCITransRollback (defconstant +OCI-FNCODE-DEFINEBYPOS+ 65) ; OCIDefineByPos (defconstant +OCI-FNCODE-BINDBYPOS+ 66) ; OCIBindByPos (defconstant +OCI-FNCODE-BINDBYNAME+ 67) ; OCIBindByName (defconstant +OCI-FNCODE-LOBASSIGN+ 68) ; OCILobAssign (defconstant +OCI-FNCODE-LOBISEQUAL+ 69) ; OCILobIsEqual (defconstant +OCI-FNCODE-LOBISINIT+ 70) ; OCILobLocatorIsInit ; 71 was lob locator size in beta2 (defconstant +OCI-FNCODE-LOBENABLEBUFFERING+ 71) ; OCILobEnableBuffering (defconstant +OCI-FNCODE-LOBCHARSETID+ 72) ; OCILobCharSetID (defconstant +OCI-FNCODE-LOBCHARSETFORM+ 73) ; OCILobCharSetForm (defconstant +OCI-FNCODE-LOBFILESETNAME+ 74) ; OCILobFileSetName (defconstant +OCI-FNCODE-LOBFILEGETNAME+ 75) ; OCILobFileGetName (defconstant +OCI-FNCODE-LOGON+ 76) ; OCILogon (defconstant +OCI-FNCODE-LOGOFF+ 77) ; OCILogoff (defconstant +OCI-FNCODE-LOBDISABLEBUFFERING+ 78) ; OCILobDisableBuffering (defconstant +OCI-FNCODE-LOBFLUSHBUFFER+ 79) ; OCILobFlushBuffer (defconstant +OCI-FNCODE-LOBLOADFROMFILE+ 80) ; OCILobLoadFromFile ;- ;- FILE open modes - (defconstant +OCI-FILE-READONLY+ 1) ; readonly mode open for FILE types ;- ;- LOB Buffering Flush Flags - (defconstant +OCI-LOB-BUFFER-FREE+ 1) ; (defconstant +OCI-LOB-BUFFER-NOFREE+ 2) ; ;- ;- OCI Statement Types - (defconstant +oci-stmt-select+ 1) ; select statement (defconstant +oci-stmt-update+ 2) ; update statement (defconstant +oci-stmt-delete+ 3) ; delete statement (defconstant +oci-stmt-insert+ 4) ; insert statement (defconstant +oci-stmt-create+ 5) ; create statement (defconstant +oci-stmt-drop+ 6) ; drop statement (defconstant +oci-stmt-alter+ 7) ; alter statement (defconstant +oci-stmt-begin+ 8) ; begin ... (pl/sql statement) (defconstant +oci-stmt-declare+ 9) ; declare .. (pl/sql statement ) ;- ;- OCI Parameter Types - (defconstant +OCI-PTYPE-UNK+ 0) ; unknown (defconstant +OCI-PTYPE-TABLE+ 1) ; table (defconstant +OCI-PTYPE-VIEW+ 2) ; view (defconstant +OCI-PTYPE-PROC+ 3) ; procedure (defconstant +OCI-PTYPE-FUNC+ 4) ; function (defconstant +OCI-PTYPE-PKG+ 5) ; package (defconstant +OCI-PTYPE-TYPE+ 6) ; user-defined type (defconstant +OCI-PTYPE-SYN+ 7) ; synonym (defconstant +OCI-PTYPE-SEQ+ 8) ; sequence (defconstant +OCI-PTYPE-COL+ 9) ; column (defconstant +OCI-PTYPE-ARG+ 10) ; argument (defconstant +OCI-PTYPE-LIST+ 11) ; list (defconstant +OCI-PTYPE-TYPE-ATTR+ 12) ; user-defined type's attribute (defconstant +OCI-PTYPE-TYPE-COLL+ 13) ; collection type's element (defconstant +OCI-PTYPE-TYPE-METHOD+ 14) ; user-defined type's method (defconstant +OCI-PTYPE-TYPE-ARG+ 15) ; user-defined type method's argument (defconstant +OCI-PTYPE-TYPE-RESULT+ 16) ; user-defined type method's result ;- ;- OCI List Types - (defconstant +OCI-LTYPE-UNK+ 0) ; unknown (defconstant +OCI-LTYPE-COLUMN+ 1) ; column list (defconstant +OCI-LTYPE-ARG-PROC+ 2) ; procedure argument list (defconstant +OCI-LTYPE-ARG-FUNC+ 3) ; function argument list (defconstant +OCI-LTYPE-SUBPRG+ 4) ; subprogram list (defconstant +OCI-LTYPE-TYPE-ATTR+ 5) ; type attribute (defconstant +OCI-LTYPE-TYPE-METHOD+ 6) ; type method (defconstant +OCI-LTYPE-TYPE-ARG-PROC+ 7) ; type method w/o result argument list (defconstant +OCI-LTYPE-TYPE-ARG-FUNC+ 8) ; type method w/result argument list ;; typecodes cl-sql-6.4.1/db-oracle/Makefile0000644000175000017500000000124011335067642015223 0ustar kevinkevin#!/usr/bin/make ########################################################################## # FILE IDENTIFICATION # # Name: Makefile # Purpose: Makefile for CLSQL Oracle interface # Author: Kevin M. Rosenberg # Created: May 2004 # # This file, part of CLSQL, is Copyright (c) 2004 by Kevin M. Rosenberg # # CLSQL users are granted the rights to distribute and use this software # as governed by the terms of the Lisp Lesser GNU Public License # (http://opensource.franz.com/preamble.html), also known as the LLGPL. ########################################################################## SUBDIRS= include ../Makefile.common .PHONY: distclean distclean: clean cl-sql-6.4.1/db-oracle/README0000644000175000017500000000225610667176647014470 0ustar kevinkevinThis is the header of the cadabra source file. ;;;; The original version of this code was copyright (c) 1999-2000 Cadabra Inc. ;;;; It was placed in the public domain by Cadabra in January 2000. ;;;; ;;;; The implementors of the original version were Winton Davies ;;;; and William Newman . ;;;; known issues: ;;;; * The code will leak C resources if errors occur in the the wrong ;;;; places, since it doesn't wrap its allocation/deallocation ;;;; logic in the necessary EVAL-WHENs to prevent this. (This could be ;;;; easily be an issue for long-running processes which recover from ;;;; database errors instead of simply terminating when they occur. It's ;;;; not an issue for programs which consider database errors so abnormal ;;;; that they die immediately when they encounter one.) ;;;; * Instead of reading Oracle header files automatically, this code ;;;; uses constants, types, and function signatures manually transcribed ;;;; from the Oracle header files. Thus, changes in the header files ;;;; may require manual maintenance of the code. (This version was written ;;;; for Oracle 8.1.5.) cl-sql-6.4.1/Makefile0000644000175000017500000000243312134026311013362 0ustar kevinkevin#!/usr/bin/make ########################################################################## # FILE IDENTIFICATION # # Name: Makefile # Purpose: Makefile for the CLSQL package # Programer: Kevin M. Rosenberg # Date Started: Mar 2002 # # This file, part of CLSQL, is Copyright (c) 2002-2010 by Kevin M. Rosenberg # # CLSQL users are granted the rights to distribute and use this software # as governed by the terms of the Lisp Lesser GNU Public License # (http://opensource.franz.com/preamble.html), also known as the LLGPL. ########################################################################## PKG := clsql DEBPKG := cl-sql SUBDIRS := sql tests uffi db-mysql db-aodbc db-odbc \ db-postgresql db-postgresql-socket db-sqlite \ db-oracle DOCSUBDIRS:=doc include Makefile.common LIBSUBDIRS=db-mysql uffi .PHONY: subdirs $(LIBSUBDIRS) .PHONY: all all: $(LIBSUBDIRS) $(LIBSUBDIRS): $(MAKE) -C $@ SOURCE_FILES=interfaces sql cmucl-compat doc test-suite Makefile VERSION \ COPYING.CLSQL COPYING.MaiSQL README INSTALL ChangeLog NEWS TODO \ set-logical.cl clsql-uffi.system \ clsql.system clsql-aodbc.system clsql-mysql.system \ clsql-postgresql.system clsql-postgresql-socket.system .PHONY: doc doc: $(MAKE) -C doc .PHONY:dist dist: clean @$(MAKE) -C doc $@ cl-sql-6.4.1/INSTALL0000644000175000017500000000024510667176647013005 0ustar kevinkevinRefer to the main documentation file for installation instructions. Documentation is availabe as a PDF file in doc/clsql.pdf and as HTML files in doc/html.tar.gz. cl-sql-6.4.1/clsql-postgresql.asd0000644000175000017500000000304011332141035015725 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; FILE IDENTIFICATION ;;;; ;;;; Name: clsql-postgresql.asd ;;;; Purpose: ASDF file for CLSQL PostgresSQL backend ;;;; Programmer: Kevin M. Rosenberg ;;;; Date Started: Aug 2002 ;;;; ;;;; This file, part of CLSQL, is Copyright (c) 2002 by Kevin M. Rosenberg ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* (defpackage #:clsql-postgresql-system (:use #:asdf #:cl)) (in-package #:clsql-postgresql-system) #+(and allegro macosx) (push "so" excl::*load-foreign-types*) (defsystem clsql-postgresql :name "cl-sql-postgresql" :author "Kevin M. Rosenberg " :maintainer "Kevin M. Rosenberg " :licence "Lessor Lisp General Public License" :description "Common Lisp PostgreSQL API Driver" :long-description "cl-sql-postgresql package provides a the database driver for the PostgreSQL API." :depends-on (clsql clsql-uffi) :components ((:module :db-postgresql :components ((:file "postgresql-package") (:file "postgresql-loader" :depends-on ("postgresql-package")) (:file "postgresql-api" :depends-on ("postgresql-loader")) (:file "postgresql-sql" :depends-on ("postgresql-api")))))) cl-sql-6.4.1/tests/0000755000175000017500000000000012134026703013067 5ustar kevinkevincl-sql-6.4.1/tests/test-pool.lisp0000644000175000017500000000664411616055736015734 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; FILE IDENTIFICATION ;;;; ;;;; Name: test-pool.lisp ;;;; Purpose: Tests for connection pools ;;;; Author: Ryan Davis ;;;; Created: June 27 2011 ;;;; ;;;; This file, part of CLSQL, is Copyright (c) 2004-2010 by Kevin M. Rosenberg ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* (in-package #:clsql-tests) ;; setup a dummy database for the pool to use (pushnew :dummy clsql-sys:*loaded-database-types*) (defclass dummy-database (clsql-sys:database) () (:default-initargs :database-type :dummy)) (defmethod clsql-sys:database-connect (connection-spec (database-type (eql :dummy))) (let ((db (make-instance 'dummy-database :connection-spec connection-spec))) (setf (slot-value db 'clsql-sys::state) :open) db)) (defmethod clsql-sys::database-name-from-spec (connection-spec (database-type (eql :dummy))) "dummy") (defmethod clsql-sys::database-acquire-from-conn-pool ((db dummy-database)) T) (setq *rt-pool* '( (deftest :pool/acquire (let ((pool (clsql-sys::find-or-create-connection-pool nil :dummy)) dbx res) (clsql-sys::clear-conn-pool pool) (flet ((test-result (x) (push x res))) (test-result (length (clsql-sys::all-connections pool))) (test-result (length (clsql-sys::free-connections pool))) (clsql-sys:with-database (db nil :database-type :dummy :pool T) (test-result (not (null db))) (test-result (length (clsql-sys::all-connections pool))) (test-result (length (clsql-sys::free-connections pool))) (setf dbx db)) (test-result (length (clsql-sys::all-connections pool))) (test-result (length (clsql-sys::free-connections pool))) (clsql-sys:with-database (db nil :database-type :dummy :pool T) (test-result (eq db dbx))) ) (nreverse res)) (0 0 T 1 0 1 1 T) ) (deftest :pool/max-free-connections (let ((pool (clsql-sys::find-or-create-connection-pool nil :dummy))) (flet ((run (max-free dbs-to-release) (let ((clsql-sys:*db-pool-max-free-connections* max-free) dbs) (clsql-sys::clear-conn-pool pool) (dotimes (i dbs-to-release dbs) (push (clsql-sys:connect nil :database-type :dummy :pool T :if-exists :new) dbs)) (list (length (clsql-sys::all-connections pool)) (progn (dolist (db dbs) (clsql-sys:disconnect :database db)) (length (clsql-sys::free-connections pool)) ))))) (append (run 5 10) (run nil 10)))) (10 5 10 10) ) (deftest :pool/find-or-create-connection-pool (let ((p (clsql-sys::find-or-create-connection-pool nil :dummy))) (values (null p) (eq p (clsql-sys::find-or-create-connection-pool nil :dummy)) (eq p (clsql-sys::find-or-create-connection-pool :spec :dummy)))) nil T nil) )) cl-sql-6.4.1/tests/benchmarks.lisp0000644000175000017500000000630311335067642016110 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; FILE IDENTIFICATION ;;;; ;;;; Name: benchmarks.lisp ;;;; Purpose: Time performance tests for CLSQL ;;;; Authors: Kevin M. Rosenberg ;;;; Created: March 5, 2004 ;;;; ;;;; This file is part of CLSQL. ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* (in-package #:clsql-tests) (defun run-benchmarks-append-report-file (report-file) (run-function-append-report-file 'run-benchmarks report-file)) (clsql:def-view-class bench () ((a :initarg :a :type integer) (b :initarg :b :type (string 100)) (c :initarg :c :type float))) (defun run-benchmarks (&key (report-stream *standard-output*) (sexp-report-stream nil) (count 10000)) (let ((specs (read-specs)) (*report-stream* report-stream) (*sexp-report-stream* sexp-report-stream)) (unless specs (warn "Not running benchmarks because test configuration file is missing") (return-from run-benchmarks :skipped)) (load-necessary-systems specs) (dolist (db-type +all-db-types+) (dolist (spec (db-type-spec db-type specs)) (do-benchmarks-for-backend db-type spec count)))) (values)) (defun do-benchmarks-for-backend (db-type spec count) (test-connect-to-database db-type spec) (write-report-banner "Benchmarks" db-type *report-stream* (database-name-from-spec spec db-type)) (create-view-from-class 'bench) (benchmark-init) (benchmark-selects count) (drop-view-from-class 'bench)) (defun benchmark-init () (dotimes (i 10) (execute-command "INSERT INTO BENCH (A,B,C) VALUES (123,'A Medium size string',3.14159)"))) (defun benchmark-selects (n) (let ((*trace-output* *report-stream*)) (format *report-stream* "~&~%*** QUERY ***~%") (time (dotimes (i n) (query "SELECT * FROM BENCH"))) (format *report-stream* "~&~%*** QUERY WITH RESULT-TYPES NIL ***~%") (time (dotimes (i n) (query "SELECT * FROM BENCH" :result-types nil))) (format *report-stream* "~&~%*** QUERY WITH FIELD-NAMES NIL ***~%") (time (dotimes (i n) (query "SELECT * FROM BENCH" :field-names nil))) (with-dataset *ds-employees* (format *report-stream* "~&~%*** JOINED OBJECT QUERY RETRIEVAL IMMEDIATE ***~%") (time (dotimes (i (truncate n 10)) (mapcar #'(lambda (ea) (slot-value ea 'address)) (select 'employee-address :flatp t)))) (format *report-stream* "~&~%*** JOINED OBJECT QUERY RETRIEVAL DEFERRED ***~%") (let* ((slotdef (find 'address (clsql-sys::class-slots (find-class 'employee-address)) :key #'clsql-sys::slot-definition-name)) (dbi (when slotdef (clsql-sys::view-class-slot-db-info slotdef)))) (setf (gethash :retrieval dbi) :deferred) (time (dotimes (i (truncate n 10)) (mapcar #'(lambda (ea) (slot-value ea 'address)) (select 'employee-address :flatp t)))) (setf (gethash :retrieval dbi) :immediate))))) cl-sql-6.4.1/tests/ds-artists.lisp0000644000175000017500000000221211616055736016066 0ustar kevinkevin(in-package #:clsql-tests) (clsql-sys:file-enable-sql-reader-syntax) (defparameter artist1 nil) (def-view-class artist () ((artist_id :accessor artist_id :initarg :id :type integer :db-kind :key :db-constraints (:not-null :auto-increment) :autoincrement-sequence 'artist_artist_id_seq) (name :accessor name :initarg :name :type (varchar 20)) (genre :accessor genre :initarg :genre :type (varchar 10) :db-constraints (:default "'Unknown'")))) (defun initialize-ds-artists () ; (start-sql-recording :type :both) ; (let ((*backend-warning-behavior* ; (if (member *test-database-type* '(:postgresql :postgresql-socket)) ; :ignore ; :warn))) (mapc #'clsql:create-view-from-class '(artist)) (setq *test-start-utime* (get-universal-time)) (let* ((*db-auto-sync* nil)) (setf artist1 (make-instance 'artist :name "Mogwai")))) (def-dataset *ds-artists* (:setup initialize-ds-artists) (:cleanup (lambda () (mapc #'clsql-sys:drop-view-from-class '(artist)) (ignore-errors (mapc #'clsql-sys:drop-sequence (list "artist_artist_id_seq")))))) cl-sql-6.4.1/tests/test-oodml.lisp0000644000175000017500000011606512064366222016065 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ====================================================================== ;;;; File: test-oodml.lisp ;;;; Created: 01/04/2004 ;;;; ;;;; Tests for the CLSQL Object Oriented Data Definition Language ;;;; (OODML). ;;;; ;;;; This file is part of CLSQL. ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ====================================================================== (in-package #:clsql-tests) (clsql-sys:file-enable-sql-reader-syntax) (setq *rt-oodml* '( (deftest :oodml/select/1 (with-dataset *ds-employees* (mapcar #'(lambda (e) (slot-value e 'last-name)) (clsql:select 'employee :order-by [last-name] :flatp t :caching nil))) ("Andropov" "Brezhnev" "Chernenko" "Gorbachev" "Kruschev" "Lenin" "Putin" "Stalin" "Trotsky" "Yeltsin")) (deftest :oodml/select/2 (with-dataset *ds-employees* (mapcar #'(lambda (e) (slot-value e 'name)) (clsql:select 'company :flatp t :caching nil))) ("Widgets Inc.")) (deftest :oodml/select/3 (with-dataset *ds-employees* (mapcar #'(lambda (e) (slot-value e 'ecompanyid)) (clsql:select 'employee :where [and [= [slot-value 'employee 'ecompanyid] [slot-value 'company 'companyid]] [= [slot-value 'company 'name] "Widgets Inc."]] :flatp t :caching nil))) (1 1 1 1 1 1 1 1 1 1)) (deftest :oodml/select/4 (with-dataset *ds-employees* (mapcar #'(lambda (e) (concatenate 'string (slot-value e 'first-name) " " (slot-value e 'last-name))) (clsql:select 'employee :where [= [slot-value 'employee 'first-name] "Vladimir"] :flatp t :order-by [last-name] :caching nil))) ("Vladimir Lenin" "Vladimir Putin")) (deftest :oodml/select/5 (with-dataset *ds-employees* (length (clsql:select 'employee :where [married] :flatp t :caching nil))) 3) (deftest :oodml/select/6 (with-dataset *ds-employees* (let ((a (caar (clsql:select 'address :where [= 1 [addressid]] :caching nil)))) (values (slot-value a 'street-number) (slot-value a 'street-name) (slot-value a 'city) (slot-value a 'postal-code)))) 10 "Park Place" "Leningrad" 123) (deftest :oodml/select/7 (with-dataset *ds-employees* (let ((a (caar (clsql:select 'address :where [= 2 [addressid]] :caching nil)))) (values (slot-value a 'street-number) (slot-value a 'street-name) (slot-value a 'city) (slot-value a 'postal-code)))) nil "" "no city" 0) (deftest :oodml/select/8 (with-dataset *ds-employees* (mapcar #'(lambda (e) (slot-value e 'married)) (clsql:select 'employee :flatp t :order-by [emplid] :caching nil))) (t t t nil nil nil nil nil nil nil)) (deftest :oodml/select/9 (with-dataset *ds-employees* (mapcar #'(lambda (pair) (list (typep (car pair) 'address) (typep (second pair) 'employee-address) (slot-value (car pair) 'addressid) (slot-value (second pair) 'aaddressid) (slot-value (second pair) 'aemplid))) (employee-addresses employee1))) ((t t 1 1 1) (t t 2 2 1))) (deftest :oodml/select/10 (with-dataset *ds-employees* (mapcar #'(lambda (pair) (list (typep (car pair) 'address) (typep (second pair) 'employee-address) (slot-value (car pair) 'addressid) (slot-value (second pair) 'aaddressid) (slot-value (second pair) 'aemplid))) (employee-addresses employee2))) ((t t 2 2 2))) (deftest :oodml/select/11 (with-dataset *ds-employees* (values (mapcar #'(lambda (x) (slot-value x 'emplid)) (clsql:select 'employee :order-by '(([emplid] :asc)) :flatp t)) (mapcar #'(lambda (x) (slot-value x 'emplid)) (clsql:select 'employee :order-by '(([emplid] :desc)) :flatp t)))) (1 2 3 4 5 6 7 8 9 10) (10 9 8 7 6 5 4 3 2 1)) ;; test retrieval of node, derived nodes etc (deftest :oodml/select/12 (with-dataset *ds-nodes* (length (clsql:select 'node :where [not [null [node-id]]] :flatp t :caching nil))) 11) (deftest :oodml/select/13 (with-dataset *ds-nodes* (let ((a (car (clsql:select 'node :where [= 1 [node-id]] :flatp t :caching nil)))) (values (slot-value a 'node-id) (slot-value a 'title)))) 1 "Bare node") (deftest :oodml/select/14 (with-dataset *ds-nodes* (length (clsql:select 'setting :where [not [null [setting-id]]] :flatp t :caching nil))) 4) (deftest :oodml/select/15 (with-dataset *ds-nodes* (let ((a (car (clsql:select 'setting :where [= 3 [setting-id]] :flatp t :caching nil)))) (values (slot-value a 'node-id) (slot-value a 'setting-id) (slot-value a 'title) (slot-value a 'vars)))) 3 3 "Setting2" "var 2") (deftest :oodml/select/16 (with-dataset *ds-nodes* (length (clsql:select 'user :where [not [null [user-id]]] :flatp t :caching nil))) 2) (deftest :oodml/select/17 (with-dataset *ds-nodes* (let ((a (car (clsql:select 'user :where [= 4 [user-id]] :flatp t :caching nil)))) (values (slot-value a 'node-id) (slot-value a 'user-id) (slot-value a 'title) (slot-value a 'nick)))) 4 4 "user-1" "first user") (deftest :oodml/select/18 (with-dataset *ds-nodes* (length (clsql:select 'theme :where [not [null [theme-id]]] :flatp t :caching nil))) 2) (deftest :oodml/select/19 (with-dataset *ds-nodes* (let ((a (car (clsql:select 'theme :where [= 6 [theme-id]] :flatp t :caching nil)))) (slot-value a 'theme-id))) 6) (deftest :oodml/select/20 (with-dataset *ds-nodes* (let ((a (car (clsql:select 'theme :where [= 7 [theme-id]] :flatp t :caching nil)))) (values (slot-value a 'node-id) (slot-value a 'theme-id) (slot-value a 'title) (slot-value a 'vars) (slot-value a 'doc) ))) 7 7 "theme-2" nil "second theme") ;; Some tests to check weird subclassed nodes (node without own table, or subclassed of same) (deftest :oodml/select/21 (with-dataset *ds-nodes* (let ((a (car (clsql:select 'location :where [= [title] "location-1"] :flatp t :caching nil)))) (values (slot-value a 'node-id) (slot-value a 'title)))) 8 "location-1") (deftest :oodml/select/22 (with-dataset *ds-nodes* (let ((a (car (clsql:select 'subloc :where [not [null [subloc-id]]] :flatp t :caching nil)))) (values (slot-value a 'node-id) (slot-value a 'subloc-id) (slot-value a 'title) (slot-value a 'loc)))) 10 10 "subloc-1" "a subloc") (deftest :oodml/select/23 (with-dataset *ds-artists* (length (clsql:select 'artist :flatp t :caching nil))) 0) ;; test retrieval is deferred (deftest :oodm/retrieval/1 (with-dataset *ds-employees* (every #'(lambda (e) (not (slot-boundp e 'company))) (select 'employee :flatp t :caching nil))) t) (deftest :oodm/retrieval/2 (with-dataset *ds-employees* (every #'(lambda (e) (not (slot-boundp e 'address))) (select 'deferred-employee-address :flatp t :caching nil))) t) ;; :retrieval :immediate should be boundp before accessed (deftest :oodm/retrieval/3 (with-dataset *ds-employees* (every #'(lambda (ea) (slot-boundp ea 'address)) (select 'employee-address :flatp t :caching nil))) t) (deftest :oodm/retrieval/4 (with-dataset *ds-employees* (every #'(lambda (ea) (typep (slot-value ea 'address) 'address)) (select 'employee-address :flatp t :caching nil))) t) (deftest :oodm/retrieval/5 (with-dataset *ds-employees* (every #'(lambda (ea) (typep (slot-value ea 'address) 'address)) (select 'deferred-employee-address :flatp t :caching nil))) t) (deftest :oodm/retrieval/6 (with-dataset *ds-employees* (every #'(lambda (ea) (slot-boundp (slot-value ea 'address) 'addressid)) (select 'employee-address :flatp t :caching nil))) t) (deftest :oodm/retrieval/7 (with-dataset *ds-employees* (every #'(lambda (ea) (slot-boundp (slot-value ea 'address) 'addressid)) (select 'deferred-employee-address :flatp t :caching nil))) t) (deftest :oodm/retrieval/8 (with-dataset *ds-employees* (mapcar #'(lambda (ea) (slot-value (slot-value ea 'address) 'street-number)) (select 'employee-address :flatp t :order-by [aaddressid] :caching nil))) (10 10 nil nil nil nil)) (deftest :oodm/retrieval/9 (with-dataset *ds-employees* (mapcar #'(lambda (ea) (slot-value (slot-value ea 'address) 'street-number)) (select 'deferred-employee-address :flatp t :order-by [aaddressid] :caching nil))) (10 10 nil nil nil nil)) ;; tests update-records-from-instance (deftest :oodml/update-records/1 (with-dataset *ds-employees* (values (progn (let ((lenin (car (clsql:select 'employee :where [= 1 [slot-value 'employee 'emplid]] :flatp t :caching nil)))) (format nil "~a ~a: ~a" (first-name lenin) (last-name lenin) (employee-email lenin)))) (progn (setf (slot-value employee1 'first-name) "Dimitriy" (slot-value employee1 'last-name) "Ivanovich" (slot-value employee1 'email) "ivanovich@soviet.org") (clsql:update-records-from-instance employee1) (let ((lenin (car (clsql:select 'employee :where [= 1 [slot-value 'employee 'emplid]] :flatp t :caching nil)))) (format nil "~a ~a: ~a" (first-name lenin) (last-name lenin) (employee-email lenin)))))) "Vladimir Lenin: lenin@soviet.org" "Dimitriy Ivanovich: ivanovich@soviet.org") ;; tests update-record-from-slot (deftest :oodml/update-records/2 (with-dataset *ds-employees* ;(start-sql-recording :type :both) (values (employee-email (car (clsql:select 'employee :where [= 1 [slot-value 'employee 'emplid]] :flatp t :caching nil))) (progn (setf (slot-value employee1 'email) "lenin-nospam@soviet.org") (clsql:update-record-from-slot employee1 'email) (employee-email (car (clsql:select 'employee :where [= 1 [slot-value 'employee 'emplid]] :flatp t :caching nil)))))) "lenin@soviet.org" "lenin-nospam@soviet.org") ;; tests update-record-from-slots (deftest :oodml/update-records/3 (with-dataset *ds-employees* (values (let ((lenin (car (clsql:select 'employee :where [= 1 [slot-value 'employee 'emplid]] :flatp t :caching nil)))) (format nil "~a ~a: ~a" (first-name lenin) (last-name lenin) (employee-email lenin))) (progn (setf (slot-value employee1 'first-name) "Dimitriy" (slot-value employee1 'last-name) "Ivanovich" (slot-value employee1 'email) "ivanovich@soviet.org") (clsql:update-record-from-slots employee1 '(first-name last-name email)) (let ((lenin (car (clsql:select 'employee :where [= 1 [slot-value 'employee 'emplid]] :flatp t :caching nil)))) (format nil "~a ~a: ~a" (first-name lenin) (last-name lenin) (employee-email lenin)))))) "Vladimir Lenin: lenin@soviet.org" "Dimitriy Ivanovich: ivanovich@soviet.org") (deftest :oodml/update-records/4 (with-dataset *ds-nodes* (flet ((print-fresh-node () (let ((base (car (clsql:select 'node :where [= 1 [slot-value 'node 'node-id]] :flatp t :caching nil)))) (format nil "~a ~a" (slot-value base 'node-id) (slot-value base 'title))))) (values (print-fresh-node) (let ((base (car (clsql:select 'node :where [= 1 [slot-value 'node 'node-id]] :flatp t :caching nil)))) (setf (slot-value base 'title) "Altered title") (clsql:update-records-from-instance base) (print-fresh-node))))) "1 Bare node" "1 Altered title") (deftest :oodml/update-records/4-slots ;just like 4, but use slots fns. (with-dataset *ds-nodes* (flet ((print-fresh-setting () (let ((node (car (clsql:select 'setting :where [= 3 [slot-value 'setting 'setting-id]] :flatp t :caching nil)))) (format nil "~a ~a ~a" (slot-value node 'setting-id) (slot-value node 'title) (slot-value node 'vars))))) (values (print-fresh-setting) (let ((node (car (clsql:select 'setting :where [= 3 [slot-value 'setting 'setting-id]] :flatp t :caching nil)))) (setf (slot-value node 'title) "Altered title") (setf (slot-value node 'vars) "Altered vars") (clsql-sys:update-record-from-slot node 'title) (clsql-sys:update-record-from-slot node 'vars) (print-fresh-setting)) (let ((node (car (clsql:select 'setting :where [= 3 [slot-value 'setting 'setting-id]] :flatp t :caching nil)))) (setf (slot-value node 'title) "Setting2") (setf (slot-value node 'vars) "var 2") (clsql:update-records-from-instance node) (clsql-sys:update-record-from-slots node '(vars title)) (print-fresh-setting))))) "3 Setting2 var 2" "3 Altered title Altered vars" "3 Setting2 var 2") (deftest :oodml/update-records/5 (with-dataset *ds-nodes* (flet ((print-fresh-setting () (let ((node (car (clsql:select 'setting :where [= 3 [slot-value 'setting 'setting-id]] :flatp t :caching nil)))) (format nil "~a ~a ~a" (slot-value node 'setting-id) (slot-value node 'title) (slot-value node 'vars))))) (values (print-fresh-setting) (let ((node (car (clsql:select 'setting :where [= 3 [slot-value 'setting 'setting-id]] :flatp t :caching nil)))) (setf (slot-value node 'title) "Altered title") (setf (slot-value node 'vars) "Altered vars") (clsql:update-records-from-instance node) (print-fresh-setting))))) "3 Setting2 var 2" "3 Altered title Altered vars") (deftest :oodml/update-records/5-slots (with-dataset *ds-nodes* (flet ((print-fresh-setting () (let ((node (car (clsql:select 'setting :where [= 3 [slot-value 'setting 'setting-id]] :flatp t :caching nil)))) (format nil "~a ~a ~a" (slot-value node 'setting-id) (slot-value node 'title) (slot-value node 'vars))))) (values (print-fresh-setting) (let ((node (car (clsql:select 'setting :where [= 3 [slot-value 'setting 'setting-id]] :flatp t :caching nil)))) (setf (slot-value node 'title) "Altered title") (setf (slot-value node 'vars) "Altered vars") (clsql-sys:update-record-from-slot node 'title) (clsql-sys:update-record-from-slot node 'vars) (print-fresh-setting)) (let ((node (car (clsql:select 'setting :where [= 3 [slot-value 'setting 'setting-id]] :flatp t :caching nil)))) (setf (slot-value node 'title) "Setting2") (setf (slot-value node 'vars) "var 2") (clsql-sys:update-record-from-slots node '(title vars)) (print-fresh-setting))))) "3 Setting2 var 2" "3 Altered title Altered vars" "3 Setting2 var 2") (deftest :oodml/update-records/6 (with-dataset *ds-nodes* (flet ((print-fresh-setting () (let ((node (car (clsql:select 'setting :where [= 7 [slot-value 'setting 'setting-id]] :flatp t :caching nil)))) (format nil "~a ~a ~a" (slot-value node 'setting-id) (slot-value node 'title) (or (slot-value node 'vars) "NIL"))))) (values (print-fresh-setting) (let ((node (car (clsql:select 'setting :where [= 7 [slot-value 'setting 'setting-id]] :flatp t :caching nil)))) (setf (slot-value node 'title) "Altered title") (setf (slot-value node 'vars) "Altered vars") (clsql:update-records-from-instance node) (print-fresh-setting)) (let ((node (car (clsql:select 'setting :where [= 7 [slot-value 'setting 'setting-id]] :flatp t :caching nil)))) (setf (slot-value node 'title) "theme-2") (setf (slot-value node 'vars) nil) (clsql:update-records-from-instance node) (print-fresh-setting))))) "7 theme-2 NIL" "7 Altered title Altered vars" "7 theme-2 NIL") (deftest :oodml/update-records/7 (with-dataset *ds-nodes* (flet ((print-fresh-user () "requery to get what the db has, and print out." (let ((node (car (clsql:select 'user :where [= 5 [slot-value 'user 'user-id]] :flatp t :caching nil)))) (format nil "~a ~a ~a" (slot-value node 'user-id) (slot-value node 'title) (slot-value node 'nick))))) (values (print-fresh-user) (let ((node (car (clsql:select 'user :where [= 5 [slot-value 'user 'user-id]] :flatp t :caching nil)))) (setf (slot-value node 'title) "Altered title") (setf (slot-value node 'nick) "Altered nick") (clsql:update-records-from-instance node) (print-fresh-user))))) "5 user-2 second user" "5 Altered title Altered nick") (deftest :oodml/update-records/8 (with-dataset *ds-nodes* (flet ((print-fresh-theme () (let ((node (car (clsql:select 'theme :where [= 6 [slot-value 'theme 'theme-id]] :flatp t :caching nil)))) (with-slots (node-id setting-id theme-id title vars doc) node (format nil "~a ~a ~a ~a ~a ~a" node-id setting-id theme-id title (or vars "NIL") doc))))) (values (print-fresh-theme) (let ((node (car (clsql:select 'setting :where [= 6 [slot-value 'setting 'setting-id]] :flatp t :caching nil)))) (setf (slot-value node 'title) "Altered title") (setf (slot-value node 'vars) nil) (clsql:update-records-from-instance node) (print-fresh-theme)) (let ((node (car (clsql:select 'theme :where [= 6 [slot-value 'theme 'theme-id]] :flatp t :caching nil)))) (setf (slot-value node 'title) "Altered title again") (setf (slot-value node 'doc) "altered doc") (clsql:update-records-from-instance node) (print-fresh-theme)) (let ((node (car (clsql:select 'theme :where [= 6 [slot-value 'theme 'theme-id]] :flatp t :caching nil)))) (setf (slot-value node 'title) "theme-1") (setf (slot-value node 'vars) "empty") (setf (slot-value node 'doc) "first theme") (clsql:update-records-from-instance node) (print-fresh-theme))))) "6 6 6 theme-1 empty first theme" "6 6 6 Altered title NIL first theme" "6 6 6 Altered title again NIL altered doc" "6 6 6 theme-1 empty first theme") (deftest :oodml/update-records/9 (with-dataset *ds-nodes* (flet ((print-fresh-subloc () (let ((sl (car (clsql:select 'subloc :where [= 10 [slot-value 'subloc 'subloc-id]] :flatp t :caching nil)))) (unless sl (error "Couldn't find expected sublocation")) (format nil "~a ~a ~a" (slot-value sl 'subloc-id) (slot-value sl 'title) (slot-value sl 'loc))))) (values (print-fresh-subloc) (let ((sl (car (clsql:select 'subloc :where [= 10 [slot-value 'subloc 'subloc-id]] :flatp t :caching nil)))) (setf (slot-value sl 'title) "Altered subloc title") (setf (slot-value sl 'loc) "Altered loc") (clsql:update-records-from-instance sl) (print-fresh-subloc))))) "10 subloc-1 a subloc" "10 Altered subloc title Altered loc") (deftest :oodml/update-records/9-slots ;like 9, but use slots fns. (with-dataset *ds-nodes* (flet ((print-fresh-subloc () (let ((sl (car (clsql:select 'subloc :where [= 10 [slot-value 'subloc 'subloc-id]] :flatp t :caching nil)))) (unless sl (error "In psfl: found no sublocation with id = 10")) (format nil "~a ~a ~a" (slot-value sl 'subloc-id) (slot-value sl 'title) (slot-value sl 'loc))))) (values (print-fresh-subloc) (let ((sl (car (clsql:select 'subloc :where [= 10 [slot-value 'subloc 'subloc-id]] :flatp t :caching nil)))) (unless sl (error "Select for modification: Found no sublocation with id = 10")) (setf (slot-value sl 'title) "Altered subloc title") (setf (slot-value sl 'loc) "Altered loc") (clsql:update-record-from-slot sl 'title) (clsql:update-record-from-slot sl 'loc) (print-fresh-subloc)) (let ((sl (car (clsql:select 'subloc :where [= 10 [slot-value 'subloc 'subloc-id]] :flatp t :caching nil)))) (unless sl (error "Select for next modification: Found no sublocation with id = 10")) (setf (slot-value sl 'title) "subloc-1") (setf (slot-value sl 'loc) "a subloc") (clsql:update-record-from-slots sl '(title loc)) (print-fresh-subloc))))) "10 subloc-1 a subloc" "10 Altered subloc title Altered loc" "10 subloc-1 a subloc") ;; Verify that we can set a float to nil and then read it back ;; (was failing in Postgresql at somepoint) (deftest :oodml/update-records/10 (with-dataset *ds-employees* (let ((emp (first (clsql:select 'employee :where [= [emplid] 1] :flatp t)))) (setf (height emp) nil) (clsql-sys:update-record-from-slot emp 'height) (values (clsql:select [height] :from [employee] :where [= [emplid] 1]) (progn (setf (height emp) 42.0) (clsql-sys:update-record-from-slot emp 'height) (clsql:select [height] :from [employee] :where [= [emplid] 1])) (progn (setf (height emp) 24.13d0) (clsql-sys:update-record-from-slot emp 'height) (clsql:select [height] :from [employee] :where [= [emplid] 1]))))) ((nil)) ((42.0d0)) ((24.13d0))) (deftest :oodml/update-records/11 (with-dataset *ds-artists* (clsql:update-records-from-instance artist1) (list (name artist1) (artist_id artist1))) ("Mogwai" 1)) (deftest :oodml/update-records/12 (with-dataset *ds-artists* (clsql:update-records-from-instance artist1) (list (name artist1) (genre artist1))) ("Mogwai" "Unknown")) ;; tests update-instance-from-records (deftest :oodml/update-instance/1 (with-dataset *ds-employees* (values (format nil "~a ~a: ~a" (slot-value employee1 'first-name) (slot-value employee1 'last-name) (slot-value employee1 'email)) (progn (clsql:update-records [employee] :av-pairs '(([first-name] "Ivan") ([last-name] "Petrov") ([email] "petrov@soviet.org")) :where [= [emplid] 1]) (clsql:update-instance-from-records employee1) (format nil "~a ~a: ~a" (slot-value employee1 'first-name) (slot-value employee1 'last-name) (slot-value employee1 'email))))) "Vladimir Lenin: lenin@soviet.org" "Ivan Petrov: petrov@soviet.org") ;; tests update-slot-from-record (deftest :oodml/update-instance/2 (with-dataset *ds-employees* (values (slot-value employee1 'email) (progn (clsql:update-records [employee] :av-pairs '(([email] "lenin-nospam@soviet.org")) :where [= [emplid] 1]) (clsql:update-slot-from-record employee1 'email) (slot-value employee1 'email)))) "lenin@soviet.org" "lenin-nospam@soviet.org") ;; tests normalizedp update-instance-from-records (deftest :oodml/update-instance/3 (with-dataset *ds-nodes* (values (with-output-to-string (out) (format out "~a ~a ~a ~a" (slot-value theme2 'theme-id) (slot-value theme2 'title) (or (slot-value theme2 'vars) "NIL") (slot-value theme2 'doc))) (progn (clsql:update-records [node] :av-pairs '(([title] "Altered title")) :where [= [node-id] 7]) (clsql:update-records [setting] :av-pairs '(([vars] "Altered vars")) :where [= [setting-id] 7]) (clsql:update-records [theme] :av-pairs '(([doc] "Altered doc")) :where [= [theme-id] 7]) (clsql:update-instance-from-records theme2) (with-output-to-string (out) (format out "~a ~a ~a ~a" (slot-value theme2 'theme-id) (slot-value theme2 'title) (slot-value theme2 'vars) (slot-value theme2 'doc)))))) "7 theme-2 NIL second theme" "7 Altered title Altered vars Altered doc") (deftest :oodml/update-instance/4 (with-dataset *ds-nodes* (values (progn (setf loc2 (car (clsql:select 'location :where [= [node-id] 9] :flatp t :caching nil))) (format nil "~a ~a" (slot-value loc2 'node-id) (slot-value loc2 'title))) (progn (clsql:update-records [node] :av-pairs '(([title] "Altered title")) :where [= [node-id] 9]) (clsql:update-instance-from-records loc2) (format nil "~a ~a" (slot-value loc2 'node-id) (slot-value loc2 'title))))) "9 location-2" "9 Altered title") (deftest :oodml/update-instance/5 (with-dataset *ds-nodes* (values (format nil "~a ~a ~a" (slot-value subloc2 'subloc-id) (slot-value subloc2 'title) (slot-value subloc2 'loc)) (progn (clsql:update-records [node] :av-pairs '(([title] "Altered title")) :where [= [node-id] 11]) (clsql:update-records [subloc] :av-pairs '(([loc] "Altered loc")) :where [= [subloc-id] 11]) (clsql:update-instance-from-records subloc2) (format nil "~a ~a ~a" (slot-value subloc2 'subloc-id) (slot-value subloc2 'title) (slot-value subloc2 'loc))))) "11 subloc-2 second subloc" "11 Altered title Altered loc") ;; tests update-slot-from-record with normalizedp stuff (deftest :oodml/update-instance/6 (with-dataset *ds-nodes* (values (slot-value theme1 'doc) (slot-value theme1 'vars) (progn (clsql:update-records [theme] :av-pairs '(([doc] "altered doc")) :where [= [theme-id] 6]) (clsql:update-slot-from-record theme1 'doc) (slot-value theme1 'doc)) (progn (clsql:update-records [setting] :av-pairs '(([vars] "altered vars")) :where [= [setting-id] 6]) (clsql:update-slot-from-record theme1 'vars) (slot-value theme1 'vars)))) "first theme" "empty" "altered doc" "altered vars") (deftest :oodml/update-instance/7 (flet ((print-loc (l) (format nil "~a: ~a" (slot-value l 'node-id) (slot-value l 'title))) (print-subloc (sl) (format nil "~a: ~a" (slot-value sl 'node-id) (slot-value sl 'loc)))) (with-dataset *ds-nodes* (values (print-loc loc2) (print-subloc subloc2) (progn (clsql:update-records [node] :av-pairs '(([title] "altered title")) :where [= [node-id] 9]) (clsql:update-slot-from-record loc2 'title) (print-loc loc2)) (progn (clsql:update-records [subloc] :av-pairs '(([loc] "altered loc")) :where [= [subloc-id] 11]) (clsql:update-slot-from-record subloc2 'loc) (print-subloc subloc2))))) "9: location-2" "11: second subloc" "9: altered title" "11: altered loc") (deftest :oodml/do-query/1 (with-dataset *ds-employees* (let ((result '())) (clsql:do-query ((e) [select 'employee :order-by [emplid]]) (push (slot-value e 'last-name) result)) result)) ("Putin" "Yeltsin" "Gorbachev" "Chernenko" "Andropov" "Brezhnev" "Kruschev" "Trotsky" "Stalin" "Lenin")) (deftest :oodml/do-query/2 (with-dataset *ds-employees* (let ((result '())) (clsql:do-query ((e c) [select 'employee 'company :where [= [slot-value 'employee 'last-name] "Lenin"]]) (push (list (slot-value e 'last-name) (slot-value c 'name)) result)) result)) (("Lenin" "Widgets Inc."))) (deftest :oodml/map-query/1 (with-dataset *ds-employees* (clsql:map-query 'list #'last-name [select 'employee :order-by [emplid]])) ("Lenin" "Stalin" "Trotsky" "Kruschev" "Brezhnev" "Andropov" "Chernenko" "Gorbachev" "Yeltsin" "Putin")) (deftest :oodml/map-query/2 (with-dataset *ds-employees* (clsql:map-query 'list #'(lambda (e c) (list (slot-value e 'last-name) (slot-value c 'name))) [select 'employee 'company :where [= [slot-value 'employee 'last-name] "Lenin"]])) (("Lenin" "Widgets Inc."))) (deftest :oodml/iteration/3 (with-dataset *ds-employees* (loop for (e) being the records in [select 'employee :where [< [emplid] 4] :order-by [emplid]] collect (slot-value e 'last-name))) ("Lenin" "Stalin" "Trotsky")) (deftest :oodml/cache/1 (with-dataset *ds-employees* (let ((*default-caching* t)) (setf (clsql-sys:record-caches *default-database*) nil) (let ((employees (select 'employee))) (every #'(lambda (a b) (eq a b)) employees (select 'employee))))) t) (deftest :oodml/cache/2 (with-dataset *ds-employees* (let* ((*default-caching* t) (employees (select 'employee))) (equal employees (select 'employee :flatp t)))) nil) (deftest :oodml/refresh/1 (with-dataset *ds-employees* (let* ((clsql-sys:*default-caching* t) (addresses (select 'address))) (equal addresses (select 'address :refresh t)))) t) (deftest :oodml/refresh/2 (with-dataset *ds-employees* (let* ((clsql-sys:*default-caching* t) (addresses (select 'address :order-by [addressid] :flatp t :refresh t)) (city (slot-value (car addresses) 'city))) (clsql:update-records [addr] :av-pairs '((city_field "A new city")) :where [= [addressid] (slot-value (car addresses) 'addressid)]) (let* ((new-addresses (select 'address :order-by [addressid] :refresh t :flatp t)) (new-city (slot-value (car addresses) 'city)) ) (clsql:update-records [addr] :av-pairs `((city_field ,city)) :where [= [addressid] (slot-value (car addresses) 'addressid)]) (values (equal addresses new-addresses) city new-city)))) t "Leningrad" "A new city") (deftest :oodml/refresh/3 (with-dataset *ds-employees* (let* ((clsql-sys:*default-caching* t) (addresses (select 'address :order-by [addressid] :flatp t))) (values (equal addresses (select 'address :refresh t :flatp t)) (equal addresses (select 'address :flatp t))))) nil nil) (deftest :oodml/refresh/4 (with-dataset *ds-employees* (let* ((clsql-sys:*default-caching* t) (addresses (select 'address :order-by [addressid] :flatp t :refresh t)) (*db-auto-sync* t)) (make-instance 'address :addressid 1000 :city "A new address city") (let ((new-addresses (select 'address :order-by [addressid] :flatp t :refresh t))) (values (length addresses) (length new-addresses) (eq (first addresses) (first new-addresses)) (eq (second addresses) (second new-addresses)))))) 3 4 t t) (deftest :oodml/uoj/full-set (with-dataset *ds-employees* (progn (let* ((dea-list (select 'deferred-employee-address :caching nil :order-by ["ea_join" aaddressid] :flatp t)) (dea-list-copy (copy-seq dea-list)) (initially-unbound (every #'(lambda (dea) (not (slot-boundp dea 'address))) dea-list))) (update-objects-joins dea-list :slots 'address :max-len nil) (values initially-unbound (equal dea-list dea-list-copy) (every #'(lambda (dea) (slot-boundp dea 'address)) dea-list) (every #'(lambda (dea) (typep (slot-value dea 'address) 'address)) dea-list) (mapcar #'(lambda (dea) (slot-value (slot-value dea 'address) 'addressid)) dea-list))))) t t t t (1 1 2 2 2 3)) (deftest :oodml/uoj/batched (with-dataset *ds-employees* (progn (let* ((dea-list (select 'deferred-employee-address :caching nil :order-by ["ea_join" aaddressid] :flatp t)) (dea-list-copy (copy-seq dea-list)) (initially-unbound (every #'(lambda (dea) (not (slot-boundp dea 'address))) dea-list))) (update-objects-joins dea-list :slots 'address :max-len 2) (values initially-unbound (equal dea-list dea-list-copy) (every #'(lambda (dea) (slot-boundp dea 'address)) dea-list) (every #'(lambda (dea) (typep (slot-value dea 'address) 'address)) dea-list) (mapcar #'(lambda (dea) (slot-value (slot-value dea 'address) 'addressid)) dea-list))))) t t t t (1 1 2 2 2 3)) ;; update-object-joins needs to be fixed for multiple keys #+ignore (deftest :oodml/uoj/multi-key (progn (clsql:update-objects-joins (list company1)) (mapcar #'(lambda (e) (slot-value e 'ecompanyid)) (company-employees company1))) (1 1 1 1 1 1 1 1 1 1)) (deftest :oodml/big/1 (with-dataset *ds-big* (let ((objs (clsql:select 'big :order-by [i] :flatp t))) (values (length objs) (do ((i 0 (1+ i)) (max (expt 2 60)) (rest objs (cdr rest))) ((= i (length objs)) t) (let ((obj (car rest)) (index (1+ i))) (unless (and (eql (slot-value obj 'i) index) (eql (slot-value obj 'bi) (truncate max index))) (print index) (describe obj) (return nil))))))) 555 t) (deftest :oodml/db-auto-sync/1 (with-dataset *ds-employees* (values (progn (make-instance 'employee :emplid 20 :groupid 1 :last-name "Ivanovich") (select [last-name] :from [employee] :where [= [emplid] 20] :flatp t :field-names nil)) (let ((*db-auto-sync* t)) (make-instance 'employee :emplid 20 :groupid 1 :last-name "Ivanovich") (prog1 (select [last-name] :from [employee] :flatp t :field-names nil :where [= [emplid] 20]) (delete-records :from [employee] :where [= [emplid] 20]))))) nil ("Ivanovich")) (deftest :oodml/db-auto-sync/2 (with-dataset *ds-employees* (values (let ((instance (make-instance 'employee :emplid 20 :groupid 1 :last-name "Ivanovich"))) (setf (slot-value instance 'last-name) "Bulgakov") (select [last-name] :from [employee] :where [= [emplid] 20] :flatp t :field-names nil)) (let* ((*db-auto-sync* t) (instance (make-instance 'employee :emplid 20 :groupid 1 :last-name "Ivanovich"))) (setf (slot-value instance 'last-name) "Bulgakov") (prog1 (select [last-name] :from [employee] :flatp t :field-names nil :where [= [emplid] 20]) (delete-records :from [employee] :where [= [emplid] 20]))))) nil ("Bulgakov")) (deftest :oodml/db-auto-sync/3 (with-dataset *ds-nodes* (values (progn (make-instance 'theme :title "test-theme" :vars "test-vars" :doc "test-doc") (select [node-id] :from [node] :where [= [title] "test-theme"] :flatp t :field-names nil)) (let ((*db-auto-sync* t)) (make-instance 'theme :title "test-theme" :vars "test-vars" :doc "test-doc") (prog1 (select [title] :from [node] :where [= [title] "test-theme"] :flatp t :field-names nil) (delete-records :from [node] :where [= [title] "test-theme"]) (delete-records :from [setting] :where [= [vars] "test-vars"]) (delete-records :from [theme] :where [= [doc] "test-doc"]))))) nil ("test-theme")) (deftest :oodml/db-auto-sync/4 (with-dataset *ds-nodes* (values (let ((inst (make-instance 'theme :title "test-theme" :vars "test-vars" :doc "test-doc")) (*print-circle* nil)) (setf (slot-value inst 'title) "alternate-test-theme") (format nil "~a ~a ~a ~a" (or (select [title] :from [node] :where [= [title] "test-theme"] :flatp t :field-names nil) "NIL") (or (select [vars] :from [setting] :where [= [vars] "test-vars"] :flatp t :field-names nil) "NIL") (or (select [doc] :from [theme] :where [= [doc] "test-doc"] :flatp t :field-names nil) "NIL") (or (select [title] :from [node] :where [= [title] "alternate-test-theme"] :flatp t :field-names nil) "NIL"))) (let* ((*db-auto-sync* t) (inst (make-instance 'theme :title "test-theme" :vars "test-vars" :doc "test-doc"))) (setf (slot-value inst 'title) "alternate-test-theme") (prog1 (format nil "~a ~a ~a ~a" (or (select [title] :from [node] :where [= [title] "test-theme"] :flatp t :field-names nil) "NIL") (or (select [vars] :from [setting] :where [= [vars] "test-vars"] :flatp t :field-names nil) "NIL") (or (select [doc] :from [theme] :where [= [doc] "test-doc"] :flatp t :field-names nil) "NIL") (or (select [title] :from [node] :where [= [title] "alternate-test-theme"] :flatp t :field-names nil) "NIL")) (delete-records :from [node] :where [= [title] "alternate-test-theme"]) (delete-records :from [setting] :where [= [vars] "test-vars"]) (delete-records :from [theme] :where [= [doc] "test-doc"]))))) "NIL NIL NIL NIL" "NIL (test-vars) (test-doc) (alternate-test-theme)") (deftest :oodml/setf-slot-value/1 (with-dataset *ds-employees* (let* ((*db-auto-sync* t) (instance (make-instance 'employee :emplid 20 :groupid 1))) (prog1 (setf (slot-value instance 'first-name) "Mikhail" (slot-value instance 'last-name) "Bulgakov") (delete-records :from [employee] :where [= [emplid] 20])))) "Bulgakov") (deftest :oodml/float/1 (with-dataset *ds-employees* (let* ((emp1 (car (select 'employee :where [= [slot-value 'employee 'emplid] 1] :flatp t :caching nil))) (height (slot-value emp1 'height))) (prog1 (progn (setf (slot-value emp1 'height) 1.0E0) (clsql:update-record-from-slot emp1 'height) (= (car (clsql:select [height] :from [employee] :where [= [emplid] 1] :flatp t :field-names nil)) 1)) (setf (slot-value emp1 'height) height) (clsql:update-record-from-slot emp1 'height)))) t) (deftest :oodml/float/2 (with-dataset *ds-employees* (let* ((emp1 (car (select 'employee :where [= [slot-value 'employee 'emplid] 1] :flatp t :caching nil))) (height (slot-value emp1 'height))) (prog1 (progn (setf (slot-value emp1 'height) 1.0S0) (clsql:update-record-from-slot emp1 'height) (= (car (clsql:select [height] :from [employee] :where [= [emplid] 1] :flatp t :field-names nil)) 1)) (setf (slot-value emp1 'height) height) (clsql:update-record-from-slot emp1 'height)))) t) (deftest :oodml/float/3 (with-dataset *ds-employees* (let* ((emp1 (car (select 'employee :where [= [slot-value 'employee 'emplid] 1] :flatp t :caching nil))) (height (slot-value emp1 'height))) (prog1 (progn (setf (slot-value emp1 'height) 1.0F0) (clsql:update-record-from-slot emp1 'height) (= (car (clsql:select [height] :from [employee] :where [= [emplid] 1] :flatp t :field-names nil)) 1)) (setf (slot-value emp1 'height) height) (clsql:update-record-from-slot emp1 'height)))) t) (deftest :oodml/float/4 (with-dataset *ds-employees* (let* ((emp1 (car (select 'employee :where [= [slot-value 'employee 'emplid] 1] :flatp t :caching nil))) (height (slot-value emp1 'height))) (prog1 (progn (setf (slot-value emp1 'height) 1.0D0) (clsql:update-record-from-slot emp1 'height) (= (car (clsql:select [height] :from [employee] :where [= [emplid] 1] :flatp t :field-names nil)) 1)) (setf (slot-value emp1 'height) height) (clsql:update-record-from-slot emp1 'height)))) t) (deftest :oodml/float/5 (with-dataset *ds-employees* (let* ((emp1 (car (select 'employee :where [= [slot-value 'employee 'emplid] 1] :flatp t :caching nil))) (height (slot-value emp1 'height))) (prog1 (progn (setf (slot-value emp1 'height) 1.0L0) (clsql:update-record-from-slot emp1 'height) (= (car (clsql:select [height] :from [employee] :where [= [emplid] 1] :flatp t :field-names nil)) 1)) (setf (slot-value emp1 'height) height) (clsql:update-record-from-slot emp1 'height)))) t) )) cl-sql-6.4.1/tests/test-init.lisp0000644000175000017500000004202611616055736015720 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ====================================================================== ;;;; File: test-init.lisp ;;;; Authors: Marcus Pearce , Kevin Rosenberg ;;;; Created: 30/03/2004 ;;;; ;;;; Initialisation utilities for running regression tests on CLSQL. ;;;; ;;;; This file is part of CLSQL. ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ====================================================================== (in-package #:clsql-tests) (defvar *report-stream* *standard-output* "Stream to send text report.") (defvar *sexp-report-stream* nil "Stream to send sexp report.") (defvar *rt-internal*) (defvar *rt-basic*) (defvar *rt-connection*) (defvar *rt-fddl*) (defvar *rt-fdml*) (defvar *rt-ooddl*) (defvar *rt-oodml*) (defvar *rt-syntax*) (defvar *rt-time*) (defvar *rt-pool*) ;; Below must be set as nil since test-i18n.lisp is not loaded on all platforms. (defvar *rt-i18n* nil) (defvar *test-database-type* nil) (defvar *test-database-underlying-type* nil) (defvar *test-database-user* nil) (defvar *test-false-database-user* "adsfjalsdkfjlakjsdfl" "For testing ownership, a user that isn't the owner.") (defvar *test-start-utime* nil) (defvar *test-connection-spec* nil) (defvar *test-connection-db-type* nil) (defvar *test-report-width* 80 "Width of test report in ems.") (defun test-connect-to-database (db-type spec) (when (clsql-sys:db-backend-has-create/destroy-db? db-type) (ignore-errors (destroy-database spec :database-type db-type)) (ignore-errors (create-database spec :database-type db-type))) (setf *test-database-type* db-type) (setf *test-database-user* (cond ((member db-type '(:oracle :odbc :aodbc)) (second spec)) ((>= (length spec) 3) (third spec)))) ;; Connect to the database (clsql:connect spec :database-type db-type :make-default t :if-exists :old) ;; Ensure database is empty (truncate-database :database *default-database*) (setf *test-database-underlying-type* (clsql-sys:database-underlying-type *default-database*)) ;; If Postgres, turn off notices to console (when (eql db-type :postgresql) (clsql:execute-command "SET client_min_messages = WARNING")) *default-database*) (defun default-suites () "The default list of tests to run." (append *rt-connection* *rt-basic* *rt-fddl* *rt-fdml* *rt-ooddl* *rt-oodml* *rt-syntax* *rt-time* *rt-i18n*)) (defun internal-suites () "The default internal suites that should run without any specific backend" (append *rt-internal* *rt-pool*)) (defvar *error-count* 0) (defvar *error-list* nil) (defun run-function-append-report-file (function report-file) (let* ((report-path (etypecase report-file (pathname report-file) (string (parse-namestring report-file)))) (sexp-report-path (make-pathname :defaults report-path :type "sexp"))) (with-open-file (rs report-path :direction :output :if-exists :append :if-does-not-exist :create) (with-open-file (srs sexp-report-path :direction :output :if-exists :append :if-does-not-exist :create) (funcall function :report-stream rs :sexp-report-stream srs))))) (defun run-tests-append-report-file (report-file) (run-function-append-report-file 'run-tests report-file)) (defun run-tests (&key (report-stream *standard-output*) (sexp-report-stream nil) (suites (append (internal-suites) (default-suites)))) ;; clear SQL-OUTPUT cache (setq clsql-sys::*output-hash* (make-hash-table :test #'equal)) (setf *test-database-underlying-type* nil) (let ((specs (read-specs)) (*report-stream* report-stream) (*sexp-report-stream* sexp-report-stream) (*error-count* 0) (*error-list* nil)) (unless specs (warn "Not running tests because test configuration file is missing") (return-from run-tests :skipped)) (load-necessary-systems specs) ;;run the internal suites (do-tests-for-internals :suites (intersection suites (internal-suites))) ;; run backend-specific tests (let ((suites (intersection suites (default-suites)))) (when suites (dolist (db-type +all-db-types+) (dolist (spec (db-type-spec db-type specs)) (let ((*test-connection-spec* spec) (*test-connection-db-type* db-type)) (do-tests-for-backend db-type spec :suites suites))))))) (zerop *error-count*)) (defun load-necessary-systems (specs) (dolist (db-type +all-db-types+) (when (db-type-spec db-type specs) (clsql-sys:initialize-database-type :database-type db-type)))) (defun write-report-banner (report-type db-type stream db-name) (format stream "~& ****************************************************************************** *** CLSQL ~A begun at ~A *** ~A *** ~A on ~A *** Database ~:@(~A~) *** Type: ~:@(~A~) backend~A. ****************************************************************************** " report-type (clsql:format-time nil (clsql:utime->time (get-universal-time))) (lisp-implementation-type) (lisp-implementation-version) (machine-type) db-name db-type (if (not (eq db-type *test-database-underlying-type*)) (format nil " with underlying type ~:@(~A~)" *test-database-underlying-type*) "") )) (defun do-tests-for-internals (&key (suites (internal-suites))) (write-report-banner "Test Suite" "CLSQL Internals" *report-stream* "N/A") (%do-tests suites nil)) (defun %do-tests (test-forms db-type) (regression-test:rem-all-tests) (dolist (test-form test-forms) (eval test-form)) (let* ((cl:*print-right-margin* *test-report-width*) (remaining (regression-test:do-tests *report-stream*))) (when (regression-test:pending-tests) (incf *error-count* (length remaining)))) (let ((sexp-error (list db-type *test-database-underlying-type* (get-universal-time) (length test-forms) (regression-test:pending-tests) (lisp-implementation-type) (lisp-implementation-version) (machine-type)))) (when *sexp-report-stream* (write sexp-error :stream *sexp-report-stream* :readably t)) (push sexp-error *error-list*)) ) (defun do-tests-for-backend (db-type spec &key (suites (default-suites)) ) (test-connect-to-database db-type spec) (unwind-protect (multiple-value-bind (test-forms skip-tests) (compute-tests-for-backend db-type *test-database-underlying-type* :suites suites) (write-report-banner "Test Suite" db-type *report-stream* (database-name-from-spec spec db-type)) (%do-tests test-forms db-type) (format *report-stream* "~&Tests skipped:") (if skip-tests (let ((max-test-name (length (symbol-name (caar skip-tests))))) (dolist (skipped (cdr skip-tests)) (let ((len (length (symbol-name (car skipped))))) (when (> len max-test-name) (setq max-test-name len)))) (let ((fmt (format nil "~~& ~~~DA ~~A~~%" max-test-name))) (dolist (skipped skip-tests) ;; word-wrap the reason string field (let* ((test (car skipped)) (reason (cdr skipped)) (rlen (length reason)) (rwidth (max 20 (- (or *test-report-width* 80) max-test-name 3))) (rwords (clsql-sys::delimited-string-to-list reason #\space t)) (rformat (format nil "~~{~~<~%~~1,~D:;~~A~~> ~~}" rwidth)) (rwrapped (format nil rformat rwords)) (rlines (clsql-sys::delimited-string-to-list rwrapped #\Newline t))) (dolist (rline rlines) (format *report-stream* fmt (if test (prog1 test (setq test nil)) "") rline)))))) (format *report-stream* " None~%"))) (disconnect))) (defun compute-tests-for-backend (db-type db-underlying-type &key (suites (default-suites))) (let ((test-forms '()) (skip-tests '())) (dolist (test-form (if (listp suites) suites (list suites))) (let ((test (second test-form))) (cond ((and (not (eql db-underlying-type :mysql)) (clsql-sys:in test :connection/query-command)) (push (cons test "known to work only in MySQL as yet.") skip-tests)) ((and (null (clsql-sys:db-type-has-views? db-underlying-type)) (clsql-sys:in test :fddl/view/1 :fddl/view/2 :fddl/view/3 :fddl/view/4)) (push (cons test "views not supported.") skip-tests)) ((and (null (clsql-sys:db-type-has-boolean-where? db-underlying-type)) (clsql-sys:in test :fdml/select/11 :oodml/select/5)) (push (cons test "boolean where not supported.") skip-tests)) ((and (null (clsql-sys:db-type-has-subqueries? db-underlying-type)) (clsql-sys:in test :fdml/select/5 :fdml/select/10 :fdml/select/32 :fdml/select/33)) (push (cons test "subqueries not supported.") skip-tests)) ((and (null (clsql-sys:db-type-transaction-capable? db-underlying-type *default-database*)) (clsql-sys:in test :fdml/transaction/1 :fdml/transaction/2 :fdml/transaction/3 :fdml/transaction/4)) (push (cons test "transactions not supported.") skip-tests)) ((and (null (clsql-sys:db-type-has-fancy-math? db-underlying-type)) (clsql-sys:in test :fdml/select/1)) (push (cons test "fancy math not supported.") skip-tests)) ((and (eql *test-database-type* :sqlite) (clsql-sys:in test :fddl/view/4 :fdml/select/10 :fdml/select/21 :fdml/select/32 :fdml/select/33)) (push (cons test "not supported by sqlite.") skip-tests)) ((and (eql *test-database-type* :sqlite3) (clsql-sys:in test :fddl/view/4 :fdml/select/10 :fdml/select/21 :fdml/select/32 :fdml/select/33)) (push (cons test "not supported by sqlite3.") skip-tests)) ((and (not (clsql-sys:db-type-has-bigint? db-type)) (clsql-sys:in test :basic/bigint/1)) (push (cons test "bigint not supported.") skip-tests)) ((and (eql *test-database-underlying-type* :mysql) (clsql-sys:in test :fdml/select/26)) (push (cons test "string table aliases not supported on all MySQL versions.") skip-tests)) ((and (eql *test-database-underlying-type* :mysql) (clsql-sys:in test :fdml/select/22 :fdml/query/5 :fdml/query/7 :fdml/query/8)) (push (cons test "not supported by mysql.") skip-tests)) ((and (null (clsql-sys:db-type-has-union? db-underlying-type)) (clsql-sys:in test :fdml/query/6 :fdml/select/31)) (push (cons test "union not supported") skip-tests)) ((and (eq *test-database-type* :oracle) (clsql-sys:in test :fdml/query/8 :fdml/select/21 :fddl/table/6)) (push (cons test "syntax not supported.") skip-tests)) ((and (eq *test-database-type* :odbc) (eq *test-database-underlying-type* :postgresql) (clsql-sys:in test :fddl/owner/1 :fddl/owner/table :fddl/owner/attributes :fddl/owner/attribute-types :fddl/owner/index :fddl/owner/sequence)) (push (cons test "table ownership not supported by postgresql odbc driver.") skip-tests)) ((and (not (member *test-database-underlying-type* '(:postgresql :oracle))) (clsql-sys:in test :fddl/owner/1 :fddl/owner/table :fddl/owner/attributes :fddl/owner/attribute-types :fddl/owner/index :fddl/owner/sequence)) (push (cons test "table ownership not supported.") skip-tests)) ((and (null (clsql-sys:db-type-has-intersect? db-underlying-type)) (clsql-sys:in test :fdml/query/7)) (push (cons test "intersect not supported.") skip-tests)) ((and (null (clsql-sys:db-type-has-except? db-underlying-type)) (clsql-sys:in test :fdml/query/8)) (push (cons test "except not supported.") skip-tests)) ((and (eq *test-database-underlying-type* :mssql) (clsql-sys:in test :fdml/select/9)) (push (cons test "mssql uses integer math for AVG.") skip-tests)) ((and (not (member *test-database-underlying-type* '(:postgresql :mysql :sqlite3 ))) (clsql-sys:in test :fdml/select/37 :fdml/select/38)) (push (cons test "LIMIT keyword not supported in SELECT.") skip-tests)) ((and (not (clsql-sys:db-type-has-auto-increment? db-underlying-type)) (clsql-sys:in test :oodml/select/12 :oodml/select/13 :oodml/select/14 :oodml/select/15 :oodml/select/16 :oodml/select/17 :oodml/select/18 :oodml/select/19 :oodml/select/20 :oodml/select/21 :oodml/select/22 :oodml/select/23 :oodml/update-records/4 :oodml/update-records/4-slots :oodml/update-records/5 :oodml/update-records/5-slots :oodml/update-records/6 :oodml/update-records/7 :oodml/update-records/8 :oodml/update-records/9 :oodml/update-records/9-slots :oodml/update-records/10 :oodml/update-records/11 :OODML/UPDATE-RECORDS/12 :oodml/update-instance/3 :oodml/update-instance/4 :oodml/update-instance/5 :oodml/update-instance/6 :oodml/update-instance/7 :oodml/db-auto-sync/3 :oodml/db-auto-sync/4)) (push (cons test ":auto-increment not supported.") skip-tests)) ((and (not (member *test-database-underlying-type* '(:postgresql :postgresql-socket))) (clsql-sys:in test :time/pg/fdml/usec :time/pg/oodml/no-usec :time/pg/oodml/usec)) (push (cons test "Postgres specific test.") skip-tests)) ((and (eql *test-database-type* :postgresql-socket3) (clsql-sys:in test :BASIC/SELECT/2 :basic/select/3)) (push (cons test "Postgres-socket3 always auto types") skip-tests)) ((and (eql *test-database-type* :postgresql-socket3) (clsql-sys:in test :fdml/select/18)) (push (cons test "Postgres-socket3 doesnt support attribute based type coersion") skip-tests)) ((and (eql *test-database-type* :postgresql-socket3) (clsql-sys:in test :basic/map/1 :basic/map/2 :basic/map/3 :basic/map/4 :basic/do/1 :basic/do/2 :fdml/do-query/1 :fdml/map-query/1 :fdml/map-query/2 :fdml/map-query/3 :fdml/map-query/4 :fdml/loop/1 :fdml/loop/2 :fdml/loop/3 )) (push (cons test "postgresql-socket3 doesnt support cursoring interface") skip-tests)) ((and (member *test-database-underlying-type* '(:mysql)) (clsql-sys:in test :time/cross-platform/msec :time/cross-platform/usec/no-tz :time/cross-platform/usec/tz)) (push (cons test "MySQL doesn't support fractional seconds on timestamp columns (http://forge.mysql.com/worklog/task.php?id=946).") skip-tests)) ((and (member *test-database-underlying-type* '(:mssql)) (clsql-sys:in test :time/cross-platform/usec/no-tz :time/cross-platform/usec/tz)) (push (cons test "MSSQL doesn't support micro-seconds on datetime columns.") skip-tests)) (t (push test-form test-forms))))) (values (nreverse test-forms) (nreverse skip-tests)))) (defun rapid-load (type &optional (position 0)) "Rapid load for interactive testing." (when *default-database* (disconnect :database *default-database*)) (test-connect-to-database type (nth position (db-type-spec type (read-specs)))) ;(test-initialise-database) *default-database*) (defun rl () (rapid-load :postgresql)) (defun rlm () (rapid-load :mysql)) (defun rlo () (rapid-load :oracle)) cl-sql-6.4.1/tests/test-i18n.lisp0000644000175000017500000000401511725170505015521 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; FILE IDENTIFICATION ;;;; ;;;; Name: test-i18n.lisp ;;;; Purpose: Tests for passing non-ascii encoded strings to db and back ;;;; Author: Nathan Bird & Kevin M. Rosenberg ;;;; Created: Feb 2010 ;;;; ;;;; This file is part of CLSQL. ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* (in-package #:clsql-tests) (setq *rt-i18n* '( ;;; The point of these two is to require proper encoding support ;;; UTF-8 for example can handle these easily. ;; I show this as a 20char string and 27 bytes in utf-8 (deftest :basic/i18n/1 (let ((uffi:*default-foreign-encoding* :utf-8)) (first (query "SELECT 'Iñtërnâtiônàlizætiøn'" :flatp t :field-names nil))) "Iñtërnâtiônàlizætiøn") ;; the z in this one is even stronger ;; I show this as a 20char string and 28 bytes in utf-8 (deftest :basic/i18n/2 (let ((uffi:*default-foreign-encoding* :utf-8)) (first (query "SELECT 'Iñtërnâtiônàližætiøn'" :flatp t :field-names nil))) "Iñtërnâtiônàližætiøn") (deftest :basic/i18n/big/1 (let ((test-string (with-output-to-string (str) (dotimes (n 250) (write-sequence "Iñtërnâtiônàližætiøn" str))))) (with-dataset *ds-bigtext* (clsql-sys:execute-command (format nil "INSERT INTO testbigtext (a) VALUES ('~a')" test-string)) (let ((res (first (clsql:query "SELECT a from testbigtext" :flatp t :field-names nil)))) (assert (equal test-string res) (test-string res) "Returned internationalization string was incorrect. Test :basic/i18n/big/1"))))) )) cl-sql-6.4.1/tests/test-time.lisp0000644000175000017500000004474012064366222015711 0ustar kevinkevin;;; -*- Mode: Lisp -*- ;;; ;;; Copyright (c) 2000, 2001 onShore Development, Inc. ;;; ;;; Test time functions (time.lisp) (in-package #:clsql-tests) (clsql-sys:file-enable-sql-reader-syntax) (def-view-class datetest () ((id :column "id" :type integer :db-kind :key :db-constraints (:not-null :unique) :accessor id :initarg :id :initform nil :db-type "int4") (testtimetz :column "testtimetz" :type clsql-sys:wall-time :db-kind :base :db-constraints nil :accessor testtimetz :initarg :testtimetz :initform nil :db-type "timestamp with time zone") (testtime :column "testtime" :type clsql-sys:wall-time :db-kind :base :db-constraints nil :accessor testtime :initarg :testtime :initform nil :db-type "timestamp without time zone"))) (def-dataset *ds-datetest* (:setup (lambda () (clsql-sys:create-view-from-class 'datetest))) (:cleanup "DROP TABLE datetest")) (def-dataset *cross-platform-datetest* (:setup (lambda () (create-table [datetest] '(([testtime] wall-time))))) (:cleanup (lambda () (drop-table [datetest])))) (setq *rt-time* '( ;; we use parse timestring a lot through here verifying other things ;; start off just checking that. (deftest :time/iso-parse/0 (let* ((time1 (parse-timestring "2010-01-23"))) (decode-time time1)) 0 0 0 0 23 1 2010 6) (deftest :time/iso-parse/1 (let* ((time1 (parse-timestring "2010-01-23T14:56:32Z"))) (decode-time time1)) 0 32 56 14 23 1 2010 6) (deftest :time/iso-parse/2 (let* ((time1 (parse-timestring "2008-02-29 12:46:32"))) (decode-time time1)) 0 32 46 12 29 2 2008 5) (deftest :time/iso-parse/3 (let* ((time1 (parse-timestring "2010-01-23 14:56:32.44"))) (decode-time time1)) 440000 32 56 14 23 1 2010 6) (deftest :time/iso-parse/4 (let* ((time1 (parse-timestring "2010-01-23 14:56:32.0044"))) (decode-time time1)) 4400 32 56 14 23 1 2010 6) (deftest :time/iso-parse/5 (let* ((time1 (parse-timestring "2010-01-23 14:56:32.000003"))) (decode-time time1)) 3 32 56 14 23 1 2010 6) (deftest :time/print-parse/1 ;;make sure when we print and parse we get the same time. (let* ((time (clsql-sys:make-time :year 2010 :month 1 :day 4 :hour 14 :minute 15 :second 44)) (string-time (iso-timestring time)) (time2 (parse-timestring string-time))) (decode-time time2)) 0 44 15 14 4 1 2010 1) (deftest :time/print-parse/2 ;;make sure when we print and parse we get the same time. (let* ((time (clsql-sys:make-time :year 2010 :month 1 :day 4 :hour 14 :minute 15 :second 44 :usec 3)) (string-time (iso-timestring time)) (time2 (parse-timestring string-time))) (decode-time time2)) 3 44 15 14 4 1 2010 1) ;; relations of intervals (deftest :time/1 (let* ((time-1 (clsql:parse-timestring "2002-01-01 10:00:00")) (time-2 (clsql:parse-timestring "2002-01-01 11:00:00")) (time-3 (clsql:parse-timestring "2002-01-01 12:00:00")) (time-4 (clsql:parse-timestring "2002-01-01 13:00:00")) (interval-1 (clsql:make-interval :start time-1 :end time-2)) (interval-2 (clsql:make-interval :start time-2 :end time-3)) (interval-3 (clsql:make-interval :start time-3 :end time-4)) (interval-4 (clsql:make-interval :start time-1 :end time-3)) (interval-5 (clsql:make-interval :start time-2 :end time-4)) (interval-6 (clsql:make-interval :start time-1 :end time-4))) (flet ((my-assert (number relation i1 i2) (declare (ignore number)) (let ((found-relation (clsql:interval-relation i1 i2))) (equal relation found-relation)))) (and (my-assert 1 :contains interval-1 interval-1) (my-assert 2 :precedes interval-1 interval-2) (my-assert 3 :precedes interval-1 interval-3) (my-assert 4 :contained interval-1 interval-4) (my-assert 5 :precedes interval-1 interval-5) (my-assert 6 :contained interval-1 interval-6) (my-assert 7 :follows interval-2 interval-1) (my-assert 8 :contains interval-2 interval-2) (my-assert 9 :precedes interval-2 interval-3) (my-assert 10 :contained interval-2 interval-4) (my-assert 11 :contained interval-2 interval-5) (my-assert 12 :contained interval-2 interval-6) (my-assert 13 :follows interval-3 interval-1) (my-assert 14 :follows interval-3 interval-2) (my-assert 15 :contains interval-3 interval-3) (my-assert 16 :follows interval-3 interval-4) (my-assert 17 :contained interval-3 interval-5) (my-assert 18 :contained interval-3 interval-6) (my-assert 19 :contains interval-4 interval-1) (my-assert 20 :contains interval-4 interval-2) (my-assert 21 :precedes interval-4 interval-3) (my-assert 22 :contains interval-4 interval-4) (my-assert 23 :overlaps interval-4 interval-5) (my-assert 24 :contained interval-4 interval-6) (my-assert 25 :follows interval-5 interval-1) (my-assert 26 :contains interval-5 interval-2) (my-assert 27 :contains interval-5 interval-3) (my-assert 28 :overlaps interval-5 interval-4) (my-assert 29 :contains interval-5 interval-5) (my-assert 30 :contained interval-5 interval-6) (my-assert 31 :contains interval-6 interval-1) (my-assert 32 :contains interval-6 interval-2) (my-assert 33 :contains interval-6 interval-3) (my-assert 34 :contains interval-6 interval-4) (my-assert 35 :contains interval-6 interval-5) (my-assert 36 :contains interval-6 interval-6)))) t) ;; adjacent intervals in list (deftest :time/2 (let* ((interval-list nil) (time-1 (clsql:parse-timestring "2002-01-01 10:00:00")) (time-3 (clsql:parse-timestring "2002-01-01 12:00:00")) (time-4 (clsql:parse-timestring "2002-01-01 13:00:00"))) (setf interval-list (clsql:interval-push interval-list (clsql:make-interval :start time-1 :end time-3 :type :open))) (setf interval-list (clsql:interval-push interval-list (clsql:make-interval :start time-3 :end time-4 :type :open))) (clsql:interval-relation (car interval-list) (cadr interval-list))) :precedes) ;; nested intervals in list (deftest :time/3 (let* ((interval-list nil) (time-1 (clsql:parse-timestring "2002-01-01 10:00:00")) (time-2 (clsql:parse-timestring "2002-01-01 11:00:00")) (time-3 (clsql:parse-timestring "2002-01-01 12:00:00")) (time-4 (clsql:parse-timestring "2002-01-01 13:00:00"))) (setf interval-list (clsql:interval-push interval-list (clsql:make-interval :start time-1 :end time-4 :type :open))) (setf interval-list (clsql:interval-push interval-list (clsql:make-interval :start time-2 :end time-3 :type :closed))) (let* ((interval (car interval-list)) (interval-contained (when interval (car (clsql:interval-contained interval))))) (when (and interval interval-contained) (and (clsql:time= (clsql:interval-start interval) time-1) (clsql:time= (clsql:interval-end interval) time-4) (eq (clsql:interval-type interval) :open) (clsql:time= (clsql:interval-start interval-contained) time-2) (clsql:time= (clsql:interval-end interval-contained) time-3) (eq (clsql:interval-type interval-contained) :closed))))) t) ;; interval-edit - nonoverlapping (deftest :time/4 (let* ((interval-list nil) (time-1 (clsql:parse-timestring "2002-01-01 10:00:00")) (time-2 (clsql:parse-timestring "2002-01-01 11:00:00")) (time-3 (clsql:parse-timestring "2002-01-01 12:00:00")) (time-4 (clsql:parse-timestring "2002-01-01 13:00:00"))) (setf interval-list (clsql:interval-push interval-list (clsql:make-interval :start time-1 :end time-2 :type :open))) (setf interval-list (clsql:interval-push interval-list (clsql:make-interval :start time-3 :end time-4 :type :closed))) (setf interval-list (clsql:interval-edit interval-list time-1 time-1 time-3)) ;; should be time-3 not time-2 (clsql:time= (clsql:interval-end (car interval-list)) time-3)) t) ;; interval-edit - overlapping (deftest :time/5 (let* ((interval-list nil) (time-1 (clsql:parse-timestring "2002-01-01 10:00:00")) (time-2 (clsql:parse-timestring "2002-01-01 11:00:00")) (time-3 (clsql:parse-timestring "2002-01-01 12:00:00")) (time-4 (clsql:parse-timestring "2002-01-01 13:00:00"))) (setf interval-list (clsql:interval-push interval-list (clsql:make-interval :start time-1 :end time-2 :type :open))) (setf interval-list (clsql:interval-push interval-list (clsql:make-interval :start time-2 :end time-4 :type :closed))) (let ((pass t)) (handler-case (progn (setf interval-list (clsql:interval-edit interval-list time-1 time-1 time-3)) (setf pass nil)) (error nil)) pass)) t) ;; interval-edit - nested intervals in list (deftest :time/6 (let* ((interval-list nil) (time-1 (clsql:parse-timestring "2002-01-01 10:00:00")) (time-2 (clsql:parse-timestring "2002-01-01 11:00:00")) (time-3 (clsql:parse-timestring "2002-01-01 12:00:00")) (time-4 (clsql:parse-timestring "2002-01-01 13:00:00")) (time-5 (clsql:parse-timestring "2002-01-01 14:00:00")) (time-6 (clsql:parse-timestring "2002-01-01 15:00:00"))) (setf interval-list (clsql:interval-push interval-list (clsql:make-interval :start time-1 :end time-6 :type :open))) (setf interval-list (clsql:interval-push interval-list (clsql:make-interval :start time-2 :end time-3 :type :closed))) (setf interval-list (clsql:interval-push interval-list (clsql:make-interval :start time-4 :end time-5 :type :closed))) (setf interval-list (clsql:interval-edit interval-list time-1 time-1 time-4)) ;; should be time-4 not time-6 (clsql:time= (clsql:interval-end (car interval-list)) time-4)) t) ;; Test the boundaries of Local Time with granularity of 1 year (deftest :time/7 (let ((sec-in-year (* 60 60 24 365)) (year (clsql:time-element (clsql:make-time) :year))) (dotimes (n 50 n) (let ((date (clsql:make-time :second (* n sec-in-year)))) (unless (= (+ year n) (clsql:time-element date :year)) (return n))))) 50) ;; Test db-timestring (deftest :time/9 (flet ((grab-year (dbstring) (parse-integer (subseq dbstring 1 5)))) (let ((second-in-year (* 60 60 24 365))) (dotimes (n 2000 n) (let* ((second (* -1 n second-in-year)) (date (clsql:make-time :year 2525 :second second))) (unless (= (grab-year (clsql:db-timestring date)) (clsql:time-element date :year)) (return n)))))) 2000) ;; Conversion between MJD and Gregorian (deftest :time/10 (dotimes (base 10000 base) (unless (= (apply #'clsql:gregorian-to-mjd (clsql:mjd-to-gregorian base)) base) (return base))) 10000) ;; Clsql:Roll by minutes: +90 (deftest :time/11 (let ((now (clsql:get-time))) (clsql:time= (clsql:time+ now (clsql:make-duration :minute 90)) (clsql:roll now :minute 90))) t) ;;Clsql:Roll by minutes: +900 (deftest :time/12 (let ((now (clsql:get-time))) (clsql:time= (clsql:time+ now (clsql:make-duration :minute 900)) (clsql:roll now :minute 900))) t) ;; Clsql:Roll by minutes: +900 (deftest :time/13 (let* ((now (clsql:get-time)) (add-time (clsql:time+ now (clsql:make-duration :minute 9000))) (roll-time (clsql:roll now :minute 9000))) (clsql:time= add-time roll-time)) t) ;;; The cross platform dataset uses the 'timestamp' column type which is ;;; in sql-92, for all that means. (deftest :time/cross-platform/no-usec/no-tz (with-dataset *cross-platform-datetest* (let ((time (parse-timestring "2008-09-09T14:37:29"))) (clsql-sys:insert-records :into [datetest] :attributes '([testtime]) :values (list time)) (let ((testtime (first (clsql:select [testtime] :from [datetest] :flatp t :where [= [testtime] time] )))) (format-time nil (parse-timestring testtime) :format :iso) ))) #.(format-time nil (parse-timestring "2008-09-09T14:37:29") :format :iso)) (deftest :time/cross-platform/no-usec/tz (with-dataset *cross-platform-datetest* (let ((time (parse-timestring "2008-09-09T14:37:29-04:00"))) (clsql-sys:insert-records :into [datetest] :attributes '([testtime]) :values (list time)) (let ((testtime (first (clsql:select [testtime] :from [datetest] :flatp t :where [= [testtime] time] )))) (format-time nil (parse-timestring testtime) :format :iso) ))) #.(format-time nil (parse-timestring "2008-09-09T14:37:29-04:00") :format :iso)) ;;;This test gets at the databases that only support miliseconds, ;;; not microseconds. (deftest :time/cross-platform/msec (with-dataset *cross-platform-datetest* (let ((time (parse-timestring "2008-09-09T14:37:29.423"))) (clsql-sys:insert-records :into [datetest] :attributes '([testtime]) :values (list time)) (let ((testtime (first (clsql:select [testtime] :from [datetest] :flatp t :where [= [testtime] time] )))) (format-time nil (parse-timestring testtime) :format :iso) ))) #.(format-time nil (parse-timestring "2008-09-09T14:37:29.423") :format :iso)) (deftest :time/cross-platform/usec/no-tz (with-dataset *cross-platform-datetest* (let ((time (parse-timestring "2008-09-09T14:37:29.000213"))) (clsql-sys:insert-records :into [datetest] :attributes '([testtime]) :values (list time)) (let ((testtime (first (clsql:select [testtime] :from [datetest] :flatp t :where [= [testtime] time] )))) (format-time nil (parse-timestring testtime) :format :iso) ))) #.(format-time nil (parse-timestring "2008-09-09T14:37:29.000213") :format :iso)) (deftest :time/cross-platform/usec/tz (with-dataset *cross-platform-datetest* (let ((time (parse-timestring "2008-09-09T14:37:29.000213-04:00"))) (clsql-sys:insert-records :into [datetest] :attributes '([testtime]) :values (list time)) (let ((testtime (first (clsql:select [testtime] :from [datetest] :limit 1 :flatp t :where [= [testtime] time] )))) (format-time nil (parse-timestring testtime) :format :iso) ))) #.(format-time nil (parse-timestring "2008-09-09T14:37:29.000213-04:00") :format :iso)) ;;; All odbc databases use local times exclusively (they do not send timezone info) ;;; Postgresql can use timezones, except when being used over odbc. This test when ;;; run through both postgres socket and postgres odbc should test a fairly ;;; broad swath of available problem space ;;; ;;; Things the following tests try to prove correct ;;; * Reading and writing usec and usec-less times ;;; * reading and writing timezones (Z=utc) when appropriate (eg: postgresql-socket) ;;; * reading and writing localtimes when appropriate (eg: ODBC) ;;; * reading and writing through both the oodml and fdml layers (deftest :time/pg/fdml/usec (with-dataset *ds-datetest* (let ((time (parse-timestring "2008-09-09T14:37:29.000213-04:00"))) (clsql-sys:insert-records :into [datetest] :attributes '([testtimetz] [testtime] [id]) :values (list time time 1)) (destructuring-bind (testtimetz testtime) (first (clsql:select [testtimetz] [testtime] :from [datetest] :limit 1 :flatp t :where [= [testtime] time] )) (values (iso-timestring (parse-timestring testtime)) (iso-timestring (parse-timestring testtimetz)))))) #.(iso-timestring (parse-timestring "2008-09-09T14:37:29.000213-04:00")) #.(iso-timestring (parse-timestring "2008-09-09T14:37:29.000213-04:00"))) (deftest :time/pg/oodml/no-usec (with-dataset *ds-datetest* (let ((time (parse-timestring "2008-09-09T14:37:29-04:00"))) (clsql-sys:update-records-from-instance (make-instance 'datetest :testtimetz time :testtime time :id 1)) (let ((o (first (clsql:select 'datetest :limit 1 :flatp t :where [= [testtime] time] )))) (assert o (o) "o shouldnt be null here (we should have just inserted)") (update-records-from-instance o) (update-instance-from-records o) (values (iso-timestring (testtime o)) (iso-timestring (testtimetz o)))))) #.(iso-timestring (parse-timestring "2008-09-09T14:37:29-04:00")) #.(iso-timestring (parse-timestring "2008-09-09T14:37:29-04:00"))) (deftest :time/pg/oodml/usec (with-dataset *ds-datetest* (let ((time (parse-timestring "2008-09-09T14:37:29.000278-04:00"))) (clsql-sys:update-records-from-instance (make-instance 'datetest :testtimetz time :testtime time :id 1)) (let ((o (first (clsql:select 'datetest :limit 1 :flatp t :where [= [testtime] time] )))) (assert o (o) "o shouldnt be null here (we should have just inserted)") (update-records-from-instance o) (update-instance-from-records o) (values (iso-timestring (testtime o)) (iso-timestring (testtimetz o))) ))) #.(iso-timestring (parse-timestring "2008-09-09T14:37:29.000278-04:00")) #.(iso-timestring (parse-timestring "2008-09-09T14:37:29.000278-04:00"))) (deftest :time/historic-datetimes (with-dataset *cross-platform-datetest* (let ((time (parse-timestring "1800-09-09T14:37:29"))) (clsql-sys:insert-records :into [datetest] :attributes '([testtime]) :values (list time)) (let ((testtime (first (clsql:select [testtime] :from [datetest] :flatp t :where [= [testtime] time] )))) (format-time nil (parse-timestring testtime) :format :iso) ))) #.(format-time nil (parse-timestring "1800-09-09T14:37:29") :format :iso)) )) cl-sql-6.4.1/tests/datasets.lisp0000644000175000017500000001111111616055736015577 0ustar kevinkevin;;;; Proposed new file in clsql-tests to enable abstracting datasets for reuse. ;;;; ;;;; The core is def-datset and with-dataset that respectively define a set, ;;;; and enable one for a dynamic scope. Datasets will normally be setup and ;;;; torn down in the scope of one test, which may impose a computation ;;;; overhead, but enables simpler tests by not worrying about side-effects ;;;; between tests. ;;;; ;;;; In general datasets should be database agnostic, but because the code ;;;; is only run in the scope of a test, if a test is excluded for a backend ;;;; or some other reason then it is never run hence doesn't cause problems. (in-package #:clsql-tests) (defparameter *dataset-debug-on-error* nil "If we get an error while loading or cleaning up the dataset, should we debug (T) or just print and quit.") (defun generic-error (e) (when (and *dataset-debug-on-error* *debugger-hook*) (invoke-debugger e)) (fresh-line *error-output*) (princ e *error-output*) (throw 'quit-dataset e)) (defmacro def-dataset (name &body body) "Define a dataset" ;;probably just shove this into a param, perhaps a marginal ;; bit of processing first. `(defparameter ,name ',body)) (defmacro with-dataset (name &body body) "Use a dataset in a dynamic scope, e.g. a single test. 1. Before the body: * :setup is run * :data is loaded 2. Body 3. :cleanup always happens" `(catch 'quit-dataset (unwind-protect (progn (restart-case (%dataset-init ,name) (retry-dataset-init () :report ,(format nil "Retry dataset('~a) init: (with any dataset changes)" (symbol-name name)) (%dataset-init ,name)) (skip-this-test () :report "FAIL and run the next test" (throw 'quit-dataset :data-set-failure))) ,@body) (%dataset-cleanup ,name)))) (defun %dataset-dispatch (arg) "For use with def-dataset and with-dataset, tries to DWIM." (etypecase arg (string (clsql-sys:execute-command arg)) ;treat it as a sql command. ((or function symbol) (funcall arg)) ;run functions (list (case (first arg) ((function lambda) (%dataset-dispatch (eval arg))) ;#' forms, lambdas (progn (mapc #'%dataset-dispatch (rest arg))) ; (progn "asdf" "ff") (ignore-errors (ignore-errors (mapc #'%dataset-dispatch (rest arg)))) (t (mapc #'%dataset-dispatch arg))) ;otherwise implicit progn ))) (defun %dataset-init (name) "Run initialization code and fill database for given dataset." ;;find items that looks like '(:setup ...), ;; dispatch the rest. (let ((setup (rest (find :setup name :key #'first))) (sqldata (rest (find :sqldata name :key #'first))) (objdata (rest (find :objdata name :key #'first)))) (when setup (%dataset-dispatch setup)) (when sqldata ;;run raw sql insert statements (destructuring-bind (table-name columns &rest values-list) sqldata (dolist (v values-list) (clsql-sys:execute-command (format nil "INSERT INTO ~a (~a) VALUES (~a)" table-name columns v))))) (when objdata ;;presumed to be view-class objects, force them to insert. (dolist (o objdata) (setf (slot-value o 'clsql-sys::view-database) nil) (clsql-sys:update-records-from-instance o))))) (defun %dataset-cleanup (name) "Run cleanup code associated with the given dataset." (restart-case (handler-bind ((error #'generic-error)) (let ((cleanup (rest (find :cleanup name :key #'first)))) (when cleanup (%dataset-dispatch cleanup)))) (retry-dataset-cleanup () :report "Retry dataset cleanup (with any dataset changes)" (%dataset-cleanup name)) (skip-cleanup () nil))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Example Test Code ;;incomplete example taken from test-init ;; (def-dataset *employees* ;; (:setup "CREATE TABLE employee ;; ( ;; emplid integer NOT NULL, ;; groupid integer NOT NULL, ;; first_name character varying(30), ;; last_name character varying(30), ;; email character varying(100), ;; ecompanyid integer, ;; managerid integer, ;; height double, ;; married boolean, ;; birthday timestamp without time zone, ;; bd_utime bigint, ;; CONSTRAINT employeepk PRIMARY KEY (emplid, groupid), ;; CONSTRAINT employee_emplid_key UNIQUE (emplid) ;; ) ;; ") ;; ;;alternatively setup can still be done as ;; ;;(:setup #'(lambda () (create-view-from-class ...))) ;; (:sqldata "employees" "emplid,groupid,married,height,first_name,last_name" ;; "1,1,false,1.5,'Napolean', 'Bonaparte'" ;; (format nil "1,1,true,~a,'Vladimir','Lenin'" (1+ (random 1.00)))) ;; (:cleanup "DROP TABLE EMPLOYEES")) cl-sql-6.4.1/tests/ds-nodes.lisp0000644000175000017500000001027412064366222015505 0ustar kevinkevin(in-package #:clsql-tests) (clsql-sys:file-enable-sql-reader-syntax) (defparameter basenode nil) (defparameter derivednode1 nil) (defparameter derivednode2 nil) (defparameter node nil) (defparameter setting1 nil) (defparameter setting2 nil) (defparameter user1 nil) (defparameter user2 nil) (defparameter theme1 nil) (defparameter theme2 nil) (defparameter loc1 nil) (defparameter loc2 nil) (defparameter subloc1 nil) (defparameter subloc2 nil) ;; classes for testing the normalizedp stuff (def-view-class node () ((node-id :accessor node-id :initarg :node-id :type integer :db-kind :key :db-constraints (:not-null :auto-increment)) (title :accessor title :initarg :title :type (varchar 240)) (createtime :accessor createtime :initarg :createtime :type wall-time :db-constraints (:not-null) :initform (get-time)) (modifiedtime :accessor modifiedtime :initarg :modifiedtime :type wall-time :initform (make-time :year 1900 :month 1 :day 1)))) (def-view-class setting (node) ((setting-id :accessor setting-id :initarg :setting-id :type integer :db-kind :key :db-constraints (:not-null :auto-increment)) (vars :accessor vars :initarg :vars :type (varchar 240))) (:normalizedp t)) (def-view-class user (node) ((user-id :accessor user-id :initarg :user-id :type integer :db-kind :key :db-constraints (:not-null :auto-increment)) (nick :accessor nick :initarg :nick :type (varchar 64))) (:base-table "nodeuser") (:normalizedp t)) (def-view-class theme (setting) ((theme-id :accessor theme-id :initarg :theme-id :type integer :db-kind :key :db-constraints (:not-null :auto-increment)) (doc :accessor doc :initarg :doc :type (varchar 240))) (:normalizedp t)) ;; A class that uses only a superclass db table (def-view-class location (node) () (:base-table node) (:normalizedp t)) (def-view-class subloc (location) ((subloc-id :accessor subloc-id :initarg :subloc-id :type integer :db-kind :key :db-constraints (:not-null :auto-increment)) (loc :accessor loc :initarg :loc :type (varchar 64))) (:normalizedp t)) (defun initialize-ds-nodes () ;; (start-sql-recording :type :both) (let ((*backend-warning-behavior* (if (member *test-database-type* '(:postgresql :postgresql-socket)) :ignore :warn))) (mapc #'clsql:create-view-from-class '(node setting user theme location subloc))) (setq *test-start-utime* (get-universal-time)) (let* ((*db-auto-sync* t)) (setf node (make-instance 'node :title "Bare node") setting1 (make-instance 'setting :title "Setting1" :vars "var 1") setting2 (make-instance 'setting :title "Setting2" :vars "var 2") user1 (make-instance 'user :title "user-1" :nick "first user") user2 (make-instance 'user :title "user-2" :nick "second user") theme1 (make-instance 'theme :title "theme-1" :vars "empty" :doc "first theme") theme2 (make-instance 'theme :title "theme-2" :doc "second theme") loc1 (make-instance 'location :title "location-1") loc2 (make-instance 'location :title "location-2") subloc1 (make-instance 'subloc :title "subloc-1" :loc "a subloc") subloc2 (make-instance 'subloc :title "subloc-2" :loc "second subloc")))) (def-dataset *ds-nodes* (:setup initialize-ds-nodes) (:cleanup (lambda () (mapc #'clsql-sys:drop-view-from-class '(node setting user theme location subloc)) (ignore-errors (clsql-sys:execute-command "DROP TABLE nodeuser") (mapc #'clsql-sys:drop-sequence '(node_node_id_seq setting_setting_id_seq subloc_subloc_id_seq theme_theme_id_seq nodeuser_user_id_seq) ))))) cl-sql-6.4.1/tests/Makefile0000644000175000017500000000117711335067642014546 0ustar kevinkevin#!/usr/bin/make ########################################################################## # FILE IDENTIFICATION # # Name: Makefile # Purpose: Makefile for CLSQL tests # Programer: Kevin M. Rosenberg # Date Started: Mar 2002 # # This file is part of CLSQL # # CLSQL users are granted the rights to distribute and use this software # as governed by the terms of the Lisp Lesser GNU Public License # (http://opensource.franz.com/preamble.html), also known as the LLGPL. ########################################################################## SUBDIRS= include ../Makefile.common .PHONY: distclean distclean: clean cl-sql-6.4.1/tests/test-connection.lisp0000644000175000017500000000357311335067642017115 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; FILE IDENTIFICATION ;;;; ;;;; Name: test-connection.lisp ;;;; Purpose: Tests for CLSQL database connections ;;;; Authors: Marcus Pearce and Kevin M. Rosenberg ;;;; Created: March 2004 ;;;; ;;;; This file is part of CLSQL. ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* (in-package #:clsql-tests) (setq *rt-connection* '( (deftest :connection/1 (let ((database (clsql:find-database (clsql:database-name clsql:*default-database*) :db-type (clsql-sys:database-type clsql:*default-database*)))) (eql (clsql-sys:database-type database) *test-database-type*)) t) (deftest :connection/2 (clsql-sys::string-to-list-connection-spec "localhost/dbname/user/passwd") ("localhost" "dbname" "user" "passwd")) (deftest :connection/3 (clsql-sys::string-to-list-connection-spec "dbname/user@hostname") ("hostname" "dbname" "user")) (deftest :connection/execute-command ;;check that we can issue basic commands. (values (clsql-sys:execute-command "CREATE TABLE DUMMY (foo integer)") (clsql-sys:execute-command "DROP TABLE DUMMY")) nil nil) (deftest :connection/query ;;check that we can do a basic query (first (clsql:query "SELECT 1" :flatp t :field-names nil)) 1) (deftest :connection/query-command ;;queries that are commands (no result set) shouldn't cause breakage (values (clsql-sys:query "CREATE TABLE DUMMY (foo integer)") (clsql-sys:query "DROP TABLE DUMMY")) nil nil) )) cl-sql-6.4.1/tests/test-internal.lisp0000644000175000017500000000540411616055736016570 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; FILE IDENTIFICATION ;;;; ;;;; Name: test-internal.lisp ;;;; Purpose: Tests for internal clsql functions ;;;; Author: Kevin M. Rosenberg ;;;; Created: May 2004 ;;;; ;;;; This file, part of CLSQL, is Copyright (c) 2004-2010 by Kevin M. Rosenberg ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* (in-package #:clsql-tests) (clsql-sys:file-enable-sql-reader-syntax) (setq *rt-internal* '( (deftest :int/convert/1 (clsql-sys::prepared-sql-to-postgresql-sql "SELECT FOO FROM BAR") "SELECT FOO FROM BAR") (deftest :int/convert/2 (clsql-sys::prepared-sql-to-postgresql-sql "SELECT FOO FROM BAR WHERE ID=?") "SELECT FOO FROM BAR WHERE ID=$1") (deftest :int/convert/3 (clsql-sys::prepared-sql-to-postgresql-sql "SELECT FOO FROM \"BAR\" WHERE ID=? AND CODE=?") "SELECT FOO FROM \"BAR\" WHERE ID=$1 AND CODE=$2") (deftest :int/convert/4 (clsql-sys::prepared-sql-to-postgresql-sql "SELECT FOO FROM BAR WHERE ID=\"Match?\" AND CODE=?") "SELECT FOO FROM BAR WHERE ID=\"Match?\" AND CODE=$1") (deftest :int/convert/5 (clsql-sys::prepared-sql-to-postgresql-sql "SELECT 'FOO' FROM BAR WHERE ID='Match?''?' AND CODE=?") "SELECT 'FOO' FROM BAR WHERE ID='Match?''?' AND CODE=$1") (deftest :int/output-caching/1 ;; ensure that key generation and matching is working ;; so that this table doesnt balloon (more than designed) (list (progn (clsql:sql [foo]) (clsql:sql [foo]) (hash-table-count clsql-sys::*output-hash*)) (progn (clsql:sql [foo.bar]) (clsql:sql [foo bar]) (hash-table-count clsql-sys::*output-hash*)) (progn (clsql:sql (clsql-sys:sql-expression :table (clsql-sys::database-identifier 'foo) :attribute (clsql-sys::database-identifier 'bar))) (clsql:sql (clsql-sys:sql-expression :table (clsql-sys::database-identifier 'foo) :attribute (clsql-sys::database-identifier 'bar))) (hash-table-count clsql-sys::*output-hash*))) (1 2 2)) (deftest :int/output-caching/2 ;; ensure that we can disable the output cache and ;; still have everything work (let ((clsql-sys::*output-hash*)) (list (clsql:sql [foo]) (clsql:sql [foo]) (clsql:sql [foo.bar]))) ("FOO" "FOO" "FOO.BAR")) )) cl-sql-6.4.1/tests/test-ooddl.lisp0000644000175000017500000001537512064366222016056 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; FILE IDENTIFICATION ;;;; ;;;; Name: test-ooddl.lisp ;;;; Purpose: Tests for the CLSQL Object Oriented Data Definition Language ;;;; Authors: Marcus Pearce and Kevin M. Rosenberg ;;;; Created: March 2004 ;;;; ;;;; This file is part of CLSQL. ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* (in-package #:clsql-tests) (clsql-sys:file-enable-sql-reader-syntax) (def-view-class big () ((i :type integer :initarg :i) (bi :type bigint :initarg :bi))) (def-dataset *ds-big* (:setup (lambda () (clsql-sys:create-view-from-class 'big) (let ((max (expt 2 60))) (dotimes (i 555) (update-records-from-instance (make-instance 'big :i (1+ i) :bi (truncate max (1+ i)))))))) (:cleanup (lambda () (clsql-sys:drop-view-from-class 'big)))) (setq *rt-ooddl* '( ;; Ensure slots inherited from standard-classes are :virtual (deftest :ooddl/metaclass/1 (values (clsql-sys::view-class-slot-db-kind (clsql-sys::slotdef-for-slot-with-class 'extraterrestrial (find-class 'person))) (clsql-sys::view-class-slot-db-kind (clsql-sys::slotdef-for-slot-with-class 'hobby (find-class 'person)))) :virtual :virtual) ;; Ensure all slots in view-class are view-class-effective-slot-definition (deftest :ooddl/metaclass/2 (values (every #'(lambda (slotd) (typep slotd 'clsql-sys::view-class-effective-slot-definition)) (clsql-sys::class-slots (find-class 'person))) (every #'(lambda (slotd) (typep slotd 'clsql-sys::view-class-effective-slot-definition)) (clsql-sys::class-slots (find-class 'employee))) (every #'(lambda (slotd) (typep slotd 'clsql-sys::view-class-effective-slot-definition)) (clsql-sys::class-slots (find-class 'setting))) (every #'(lambda (slotd) (typep slotd 'clsql-sys::view-class-effective-slot-definition)) (clsql-sys::class-slots (find-class 'theme))) (every #'(lambda (slotd) (typep slotd 'clsql-sys::view-class-effective-slot-definition)) (clsql-sys::class-slots (find-class 'node))) (every #'(lambda (slotd) (typep slotd 'clsql-sys::view-class-effective-slot-definition)) (clsql-sys::class-slots (find-class 'company)))) t t t t t t) ;; Ensure classes are correctly marked normalized or not, default not ;(deftest :ooddl/metaclass/3 ; (values ; (clsql-sys::normalizedp derivednode1) ; (clsql-sys::normalizedp basenode) ; (clsql-sys::normalizedp company1) ; (clsql-sys::normalizedp employee3) ; (clsql-sys::normalizedp derivednode-sc-2)) ; t nil nil nil t) ;(deftest :ooddl/metaclass/3 ; (values ; (normalizedp (find-class 'baseclass)) ; (normalizedp (find-class 'normderivedclass))) ; nil t) (deftest :ooddl/join/1 (with-dataset *ds-employees* (mapcar #'(lambda (e) (slot-value e 'ecompanyid)) (company-employees company1))) (1 1 1 1 1 1 1 1 1 1)) (deftest :ooddl/join/2 (with-dataset *ds-employees* (slot-value (president company1) 'last-name)) "Lenin") (deftest :ooddl/join/3 (with-dataset *ds-employees* (slot-value (employee-manager employee2) 'last-name)) "Lenin") (deftest :ooddl/join/4 (with-dataset *ds-employees* (values (length (employee-addresses employee10)) ;; add an address (let ((*db-auto-sync* T)) (make-instance 'address :addressid 50) (make-instance 'employee-address :emplid 10 :addressid 50) ;; again (length (employee-addresses employee10))) (progn (update-objects-joins (list employee10) :slots '(addresses)) (length (employee-addresses employee10))))) 0 0 1) (deftest :ooddl/big/1 ;;tests that we can create-view-from-class with a bigint slot, ;; and stick a value in there. (progn (clsql-sys:create-view-from-class 'big) (values (clsql:table-exists-p [big] ) (progn (clsql:drop-table [big] :if-does-not-exist :ignore) (clsql:table-exists-p [big] ))) ) t nil) (deftest :ooddl/big/2 (with-dataset *ds-big* (let ((rows (clsql:select [*] :from [big] :order-by [i] :field-names nil))) (values (length rows) (do ((i 0 (1+ i)) (max (expt 2 60)) (rest rows (cdr rest))) ((= i (length rows)) t) (let ((index (1+ i)) (int (first (car rest))) (bigint (second (car rest)))) (when (and (or (eq *test-database-type* :oracle) (and (eq *test-database-type* :odbc) (eq *test-database-underlying-type* :postgresql))) (stringp bigint)) (setf bigint (parse-integer bigint))) (unless (and (eql int index) (eql bigint (truncate max index))) (return nil))))))) 555 t) (deftest :ooddl/time/1 (with-dataset *ds-employees* (sleep 1) ;force birthdays into the past (let* ((now (clsql:get-time))) (when (member *test-database-underlying-type* '(:postgresql :postgresql-socket)) (clsql:execute-command "set datestyle to 'iso'")) (clsql:update-records [employee] :av-pairs `((birthday ,now)) :where [= [emplid] 1]) (let ((dbobj (car (clsql:select 'employee :where [= [birthday] now] :flatp t)))) (values (slot-value dbobj 'last-name) (clsql:time= (slot-value dbobj 'birthday) now))))) "Lenin" t) (deftest :ooddl/time/2 (with-dataset *ds-employees* (sleep 1) ;force birthdays into the past (let* ((now (clsql:get-time)) (fail-index -1)) (when (member *test-database-underlying-type* '(:postgresql :postgresql-socket)) (clsql:execute-command "set datestyle to 'iso'")) (dotimes (x 40) (clsql:update-records [employee] :av-pairs `((birthday ,now)) :where [= [emplid] 1]) (let ((dbobj (car (clsql:select 'employee :where [= [birthday] now] :flatp t)))) (unless (clsql:time= (slot-value dbobj 'birthday) now) (setf fail-index x)) (setf now (clsql:roll now :day (* 10 x))))) fail-index)) -1) (deftest :ooddl/time/3 (with-dataset *ds-employees* (progn (when (member *test-database-underlying-type* '(:postgresql :postgresql-socket)) (clsql:execute-command "set datestyle to 'iso'")) (let ((dbobj (car (clsql:select 'employee :where [= [emplid] 10] :flatp t)))) (list (eql *test-start-utime* (slot-value dbobj 'bd-utime)) (clsql:time= (slot-value dbobj 'birthday) (clsql:utime->time (slot-value dbobj 'bd-utime))))))) (t t)) )) cl-sql-6.4.1/tests/ds-employees.lisp0000644000175000017500000003747212064366222016410 0ustar kevinkevin(in-package #:clsql-tests) (clsql-sys:file-enable-sql-reader-syntax) (defparameter company1 nil) (defparameter employee1 nil) (defparameter employee2 nil) (defparameter employee3 nil) (defparameter employee4 nil) (defparameter employee5 nil) (defparameter employee6 nil) (defparameter employee7 nil) (defparameter employee8 nil) (defparameter employee9 nil) (defparameter employee10 nil) (defparameter address1 nil) (defparameter address2 nil) (defparameter address3 nil) (defparameter employee-address1 nil) (defparameter employee-address2 nil) (defparameter employee-address3 nil) (defparameter employee-address4 nil) (defparameter employee-address5 nil) (defparameter employee-address6 nil) (defclass thing () ((extraterrestrial :initform nil :initarg :extraterrestrial))) (def-view-class person (thing) ((height :db-kind :base :accessor height :type float :initarg :height) (married :db-kind :base :accessor married :type boolean :initarg :married) (birthday :type clsql:wall-time :initarg :birthday) (bd-utime :type clsql:universal-time :initarg :bd-utime) (hobby :db-kind :virtual :initarg :hobby :initform nil))) (def-view-class employee (person) ((emplid :db-kind :key :db-constraints (:not-null :unique) :type integer :initarg :emplid) (groupid :db-kind :key :db-constraints :not-null :type integer :initarg :groupid) (first-name :accessor first-name :type (varchar 30) :initarg :first-name) (last-name :accessor last-name :type (varchar 30) :initarg :last-name) (email :accessor employee-email :type (varchar 100) :initarg :email) (ecompanyid :type integer :initarg :companyid) (company :accessor employee-company :db-kind :join :db-info (:join-class company :home-key ecompanyid :foreign-key companyid :set nil)) (managerid :type integer :initarg :managerid) (manager :accessor employee-manager :db-kind :join :db-info (:join-class employee :home-key managerid :foreign-key emplid :set nil)) (addresses :accessor employee-addresses :db-kind :join :db-info (:join-class employee-address :home-key emplid :foreign-key aemplid :target-slot address :set t))) (:base-table employee)) (def-view-class company () ((companyid :db-kind :key :db-constraints :not-null :type integer :initarg :companyid) (groupid :db-kind :key :db-constraints :not-null :type integer :initarg :groupid) (name :type (varchar 100) :initarg :name) (presidentid :type integer :initarg :presidentid) (president :reader president :db-kind :join :db-info (:join-class employee :home-key presidentid :foreign-key emplid :set nil)) (employees :reader company-employees :db-kind :join :db-info (:join-class employee :home-key (companyid groupid) :foreign-key (ecompanyid groupid) :set t)))) (def-view-class address () ((addressid :db-kind :key :db-constraints :not-null :type integer :initarg :addressid) (street-number :type integer :initarg :street-number) (street-name :type (varchar 30) :void-value "" :initarg :street-name) (city :column "city_field" :void-value "no city" :type (varchar 30) :initarg :city) (postal-code :column zip :type integer :void-value 0 :initarg :postal-code)) (:base-table addr)) ;; many employees can reside at many addressess (def-view-class employee-address () ((aemplid :type integer :initarg :emplid) (aaddressid :type integer :initarg :addressid) (verified :type boolean :initarg :verified) (address :db-kind :join :db-info (:join-class address :home-key aaddressid :foreign-key addressid :retrieval :immediate)) (employee :db-kind :join :db-info (:join-class employee :home-key aemplid :foreign-key emplid :retrieval :immediate))) (:base-table "ea_join")) (def-view-class deferred-employee-address () ((aemplid :type integer :initarg :emplid) (aaddressid :type integer :initarg :addressid) (verified :type boolean :initarg :verified) (address :db-kind :join :db-info (:join-class address :home-key aaddressid :foreign-key addressid :retrieval :deferred :set nil))) (:base-table "ea_join")) (defun initialize-ds-employees () ;; (start-sql-recording :type :both) (let ((*backend-warning-behavior* (if (member *test-database-type* '(:postgresql :postgresql-socket)) :ignore :warn))) (mapc #'clsql:create-view-from-class '(employee company address employee-address))) (setq *test-start-utime* (get-universal-time)) (let* ((*db-auto-sync* t) (now-time (clsql:utime->time *test-start-utime*))) (setf company1 (make-instance 'company :presidentid 1 :companyid 1 :groupid 1 :name "Widgets Inc.") employee1 (make-instance 'employee :emplid 1 :groupid 1 :married t :height (1+ (random 1.00)) :bd-utime *test-start-utime* :birthday now-time :first-name "Vladimir" :last-name "Lenin" :email "lenin@soviet.org" :companyid 1) employee2 (make-instance 'employee :emplid 2 :groupid 1 :height (1+ (random 1.00)) :married t :bd-utime *test-start-utime* :birthday now-time :first-name "Josef" :last-name "Stalin" :email "stalin@soviet.org" :managerid 1 :companyid 1) employee3 (make-instance 'employee :emplid 3 :groupid 1 :height (1+ (random 1.00)) :married t :bd-utime *test-start-utime* :birthday now-time :first-name "Leon" :last-name "Trotsky" :email "trotsky@soviet.org" :managerid 1 :companyid 1) employee4 (make-instance 'employee :emplid 4 :groupid 1 :height (1+ (random 1.00)) :married nil :bd-utime *test-start-utime* :birthday now-time :first-name "Nikita" :last-name "Kruschev" :email "kruschev@soviet.org" :managerid 1 :companyid 1) employee5 (make-instance 'employee :emplid 5 :groupid 1 :married nil :height (1+ (random 1.00)) :bd-utime *test-start-utime* :birthday now-time :first-name "Leonid" :last-name "Brezhnev" :email "brezhnev@soviet.org" :managerid 1 :companyid 1) employee6 (make-instance 'employee :emplid 6 :groupid 1 :married nil :height (1+ (random 1.00)) :bd-utime *test-start-utime* :birthday now-time :first-name "Yuri" :last-name "Andropov" :email "andropov@soviet.org" :managerid 1 :companyid 1) employee7 (make-instance 'employee :emplid 7 :groupid 1 :height (1+ (random 1.00)) :married nil :bd-utime *test-start-utime* :birthday now-time :first-name "Konstantin" :last-name "Chernenko" :email "chernenko@soviet.org" :managerid 1 :companyid 1) employee8 (make-instance 'employee :emplid 8 :groupid 1 :height (1+ (random 1.00)) :married nil :bd-utime *test-start-utime* :birthday now-time :first-name "Mikhail" :last-name "Gorbachev" :email "gorbachev@soviet.org" :managerid 1 :companyid 1) employee9 (make-instance 'employee :emplid 9 :groupid 1 :married nil :height (1+ (random 1.00)) :bd-utime *test-start-utime* :birthday now-time :first-name "Boris" :last-name "Yeltsin" :email "yeltsin@soviet.org" :managerid 1 :companyid 1) employee10 (make-instance 'employee :emplid 10 :groupid 1 :married nil :height (1+ (random 1.00)) :bd-utime *test-start-utime* :birthday now-time :first-name "Vladimir" :last-name "Putin" :email "putin@soviet.org" :managerid 1 :companyid 1) address1 (make-instance 'address :addressid 1 :street-number 10 :street-name "Park Place" :city "Leningrad" :postal-code 123) address2 (make-instance 'address :addressid 2) address3 (make-instance 'address :addressid 3) employee-address1 (make-instance 'employee-address :emplid 1 :addressid 1 :verified t) employee-address2 (make-instance 'employee-address :emplid 2 :addressid 2 :verified t) employee-address3 (make-instance 'employee-address :emplid 3 :addressid 1 :verified nil) employee-address4 (make-instance 'employee-address :emplid 1 :addressid 2 :verified nil) employee-address5 (make-instance 'employee-address :emplid 3 :addressid 2) employee-address6 (make-instance 'employee-address :emplid 4 :addressid 3))) ;; sleep to ensure birthdays are no longer at current time ;(sleep 1) ;want to find the test that depends on it, put the sleep there. #|| ;; Lenin manages everyone ; (clsql:add-to-relation employee2 'manager employee1) (clsql:add-to-relation employee3 'manager employee1) (clsql:add-to-relation employee4 'manager employee1) (clsql:add-to-relation employee5 'manager employee1) (clsql:add-to-relation employee6 'manager employee1) (clsql:add-to-relation employee7 'manager employee1) (clsql:add-to-relation employee8 'manager employee1) (clsql:add-to-relation employee9 'manager employee1) (clsql:add-to-relation employee10 'manager employee1) ;; Everyone works for Widgets Inc. ; (clsql:add-to-relation company1 'employees employee1) (clsql:add-to-relation company1 'employees employee2) (clsql:add-to-relation company1 'employees employee3) (clsql:add-to-relation company1 'employees employee4) (clsql:add-to-relation company1 'employees employee5) (clsql:add-to-relation company1 'employees employee6) (clsql:add-to-relation company1 'employees employee7) (clsql:add-to-relation company1 'employees employee8) (clsql:add-to-relation company1 'employees employee9) (clsql:add-to-relation company1 'employees employee10) ;; Lenin is president of Widgets Inc. ; (clsql:add-to-relation company1 'president employee1) ||# ;; store these instances #|| (clsql:update-records-from-instance employee1) (clsql:update-records-from-instance employee2) (clsql:update-records-from-instance employee3) (clsql:update-records-from-instance employee4) (clsql:update-records-from-instance employee5) (clsql:update-records-from-instance employee6) (clsql:update-records-from-instance employee7) (clsql:update-records-from-instance employee8) (clsql:update-records-from-instance employee9) (clsql:update-records-from-instance employee10) (clsql:update-records-from-instance company1) (clsql:update-records-from-instance address1) (clsql:update-records-from-instance address2) ||# ) (def-dataset *ds-employees* (:setup initialize-ds-employees) (:cleanup (lambda () (mapc #'clsql-sys:drop-view-from-class '(employee company address employee-address)) (ignore-errors (clsql-sys:execute-command "DROP TABLE ea_join"))))) cl-sql-6.4.1/tests/README0000644000175000017500000001044210667176647013776 0ustar kevinkevin* RUNNING THE REGRESSION SUITE This test suite looks for a configuration file named ".clsql-test.config" located in the users home directory. This file contains a single assoc-list that specifies the connection specs for each database type to be tested. There is an example file in contained in CLSQL's examples directory. These tests require the downloading of the rt package from http://files.b9.com/. Load clsql.asd or put it somewhere where ASDF can find it and call: (asdf:oos 'asdf:test-op 'clsql) The test suite will then automatically run on all of the backends that you have defined in .clsql-test.config * REGRESSION TEST SUITE GOALS The intent of this test suite is to provide sufficient coverage for the system to support the following: ** Refactoring and Redesign of particular subsystems Refactoring and redesign efforts are normally restricted to a single subsystem, or perhaps to interdependent subsystems. In such cases, a set of regression tests which excercise the existing interface of the rest of CLSQL to the changing subsystems should be in place and passing before the coding starts. ** Ensuring portability and Supporting new ports. The more coverage the test suite provides the easier portability is to maintain, particularly if we have instances of the test suite running against the head on the supporting lisp environment/OS/hardware/DBMS combinations. Since no individual within the project has the ability to run all of those combinations themselves, we are dependent upon some informal coordination between the mintainers of the various ports. ** Adding new RDBMS backends The entire CLSQL DBMS interface needs to be excercised by the test suite, such that a new RDBMS backend that passes all the tests can be reasonably assured of working with the CLSQL layers above that. These tests should also serve as impromptu documentation for the details of that interface and what it expects frothe RDBMS driver layers. ** Bug identification and QA As new bugs are identified, they should have a regression test written which excercises them. This is to ensue that we donot start backtracking. These tests by theselves are also very valuable for developers, so even if you cannot fix a bug yourself, providing a testto excercise it greatly reduces the amount of timea developer must spend finding the bug prior to fixing it. * TEST DESIGN ISSUES ** Multiple RDBMS Issues CLSQL supports several RDBMS backends, and it should be possible to run every test against all of them. However, there are some features which we want tests for but which are not implemented on several of the backends. ** Test Hygiene Tests should be able to be run multiple times against the same database. It is also important that they clean up after themselves when they create tables, sequences or other pesistent entities in the RDBMS backends, because often there are limits to the number of those thatcan exist at one time, and it also makes debuging thru the SQL monitors difficult when there aretons of unused tables lying around. If test need to load large datasets, they should have a mechanism to ensure the dataset is loaded just once, and not with every test run. Lastly, because there are various idiosyncracies with RDBMSs, please ensure that you run the entire test suite once when you write your tests, to ensure that your test does not leave some state behind which causes other tests to fail. ** Test Run Configuration The file test-init.lisp defines several variables which can be used to control the connection dictionary of the database against which tests will be run. * DATABASE CONNECTIONS/LIFECYCLE ** CreateDB *** Without existing DB *** With existing DB and use old *** With existing DB and use new *** Error if existing DB ** Data Definition *** Create Tables/Views/Sequences/Indexes -- Should cover creation of tables with all supported types of fields. *** Delete Tables/Views/Sequences/Indexes *** Inspection of Tables and attributes, including types ** Data Manipulation *** Update *** Insert *** Delete *** Query ** Functional Interface *** Creation/Modification of SQL expressions *** Querying ** Embedded SQL syntax *** Excercise all sql operators ** Object Interface *** View class definition *** Object creation/manipulation/deletion *** Inter-object Relations cl-sql-6.4.1/tests/test-basic.lisp0000644000175000017500000002227111616055736016036 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; FILE IDENTIFICATION ;;;; ;;;; Name: test-basic.lisp ;;;; Purpose: Tests for clsql string-based queries and result types ;;;; Author: Kevin M. Rosenberg ;;;; Created: Mar 2002 ;;;; ;;;; This file, part of CLSQL, is Copyright (c) 2002-2010 by Kevin M. Rosenberg ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* (in-package #:clsql-tests) (setq *rt-basic* '( (deftest :basic/type/1 (with-dataset *ds-basic* (let ((results '())) (dolist (row (query "select * from TYPE_TABLE" :result-types :auto) results) (destructuring-bind (int float str) row (push (list (integerp int) (typep float 'double-float) (stringp str)) results))))) ((t t t) (t t t) (t t t) (t t t) (t t t) (t t t) (t t t) (t t t) (t t t) (t t t) (t t t))) (deftest :basic/type/2 (with-dataset *ds-basic* (let ((results '())) (dolist (row (query "select * from TYPE_TABLE" :result-types :auto) results) (destructuring-bind (int float str) row (setq results (cons (list (double-float-equal (transform-float-1 int) float) (double-float-equal (parse-double str) float)) results)))) results)) ((t t) (t t) (t t) (t t) (t t) (t t) (t t) (t t) (t t) (t t) (t t))) (deftest :basic/select/1 (with-dataset *ds-basic* (let ((rows (query "select * from TYPE_TABLE" :result-types :auto))) (values (length rows) (length (car rows))))) 11 3) (deftest :BASIC/SELECT/2 (with-dataset *ds-basic* (let ((results '())) (dolist (row (query "select * from TYPE_TABLE" :result-types nil) results) (destructuring-bind (int float str) row (push (list (stringp int) (stringp float) (stringp str)) results))))) ((t t t) (t t t) (t t t) (t t t) (t t t) (t t t) (t t t) (t t t) (t t t) (t t t) (t t t))) (deftest :basic/select/3 (with-dataset *ds-basic* (let ((results '())) (dolist (row (query "select * from TYPE_TABLE" :result-types nil) results) (destructuring-bind (int float str) row (push (list (double-float-equal (transform-float-1 (parse-integer int)) (parse-double float)) (double-float-equal (parse-double str) (parse-double float))) results))))) ((t t) (t t) (t t) (t t) (t t) (t t) (t t) (t t) (t t) (t t) (t t))) (deftest :basic/map/1 (with-dataset *ds-basic* (let ((results '()) (rows (map-query 'vector #'identity "select * from TYPE_TABLE" :result-types nil))) (declare (type (simple-array list (*)) rows)) (dotimes (i (length rows) results) (push (list (listp (aref rows i)) (length (aref rows i)) (eql (- i 5) (parse-integer (first (aref rows i)) :junk-allowed nil)) (double-float-equal (transform-float-1 (parse-integer (first (aref rows i)))) (parse-double (second (aref rows i))))) results)))) ((t 3 t t) (t 3 t t) (t 3 t t) (t 3 t t) (t 3 t t) (t 3 t t) (t 3 t t) (t 3 t t) (t 3 t t) (t 3 t t) (t 3 t t))) (deftest :basic/map/2 (with-dataset *ds-basic* (let ((results '()) (rows (map-query 'list #'identity "select * from TYPE_TABLE" :result-types nil))) (dotimes (i (length rows) results) (push (list (listp (nth i rows)) (length (nth i rows)) (eql (- i 5) (parse-integer (first (nth i rows)) :junk-allowed nil)) (double-float-equal (transform-float-1 (parse-integer (first (nth i rows)))) (parse-double (second (nth i rows))))) results)))) ((t 3 t t) (t 3 t t) (t 3 t t) (t 3 t t) (t 3 t t) (t 3 t t) (t 3 t t) (t 3 t t) (t 3 t t) (t 3 t t) (t 3 t t))) (deftest :basic/map/3 (with-dataset *ds-basic* (let ((results '()) (rows (map-query 'list #'identity "select * from TYPE_TABLE" :result-types :auto))) (dotimes (i (length rows) results) (push (list (listp (nth i rows)) (length (nth i rows)) (eql (- i 5) (first (nth i rows))) (double-float-equal (transform-float-1 (first (nth i rows))) (second (nth i rows)))) results)))) ((t 3 t t) (t 3 t t) (t 3 t t) (t 3 t t) (t 3 t t) (t 3 t t) (t 3 t t) (t 3 t t) (t 3 t t) (t 3 t t) (t 3 t t))) ;; confirm that a query on a single element returns a list of one element (deftest :basic/map/4 (with-dataset *ds-basic* (let ((rows (map-query 'list #'identity "select t_int from TYPE_TABLE" :result-types nil))) (values (consp (first rows)) (length (first rows))))) t 1) (deftest :basic/do/1 (with-dataset *ds-basic* (let ((results '())) (do-query ((int float str) "select * from TYPE_TABLE" :result-types nil) (let ((int-number (parse-integer int))) (setq results (cons (list (double-float-equal (transform-float-1 int-number) (parse-double float)) (double-float-equal (parse-double str) (parse-double float))) results)))) results)) ((t t) (t t) (t t) (t t) (t t) (t t) (t t) (t t) (t t) (t t) (t t))) (deftest :basic/do/2 (with-dataset *ds-basic* (let ((results '())) (do-query ((int float str) "select * from TYPE_TABLE" :result-types :auto) (setq results (cons (list (double-float-equal (transform-float-1 int) float) (double-float-equal (parse-double str) float)) results))) results)) ((t t) (t t) (t t) (t t) (t t) (t t) (t t) (t t) (t t) (t t) (t t))) (deftest :basic/bigint/1 (with-dataset *ds-bigint* (let ((results '())) (dolist (row (query "select * from TYPE_BIGINT" :result-types :auto) results) (destructuring-bind (int bigint) row (push (list (integerp int) (integerp bigint)) results))))) ((t t) (t t) (t t) (t t) (t t) (t t) (t t) (t t) (t t) (t t) (t t))) (deftest :basic/bigtext/1 (with-dataset *ds-bigtext* (let* ((len 7499) (str (make-string len :initial-element #\a)) (cmd (format nil "INSERT INTO testbigtext (a) VALUES ('~a')" str))) (execute-command cmd) (let ((a (first (query "SELECT a from testbigtext" :flatp t :field-names nil)))) (assert (string= str a) (str a) "mismatch on a. inserted: ~a returned: ~a" len (length a))) )) nil) (deftest :basic/bigtext/2 (flet ((random-char () (let ((alphabet "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") (idx (random 52))) (elt alphabet idx)))) (dotimes (n 10) (with-dataset *ds-bigtext* (let* ((len (random 7500)) (str (coerce (make-array len :initial-contents (loop repeat len collect (random-char))) 'string)) (cmd (format nil "INSERT INTO testbigtext (a) VALUES ('~a')" str))) (execute-command cmd) (let ((a (first (query "SELECT a from testbigtext" :flatp t :field-names nil)))) (assert (string= str a) (str a) "mismatch on randomized bigtext(~a) inserted: ~s returned: ~s" len str a)) )))) nil) )) (def-dataset *ds-basic* (:setup (lambda () (ignore-errors (clsql:execute-command "DROP TABLE TYPE_TABLE") (clsql:execute-command "DROP TABLE TYPE_BIGINT")) (clsql:execute-command "CREATE TABLE TYPE_TABLE (t_int integer, t_float double precision, t_str VARCHAR(30))") (dotimes (i 11) (let* ((test-int (- i 5)) (test-flt (transform-float-1 test-int))) (clsql:execute-command (format nil "INSERT INTO TYPE_TABLE VALUES (~a,~a,'~a')" test-int (clsql-sys:number-to-sql-string test-flt) (clsql-sys:number-to-sql-string test-flt) )))))) (:cleanup "DROP TABLE TYPE_TABLE")) (def-dataset *ds-bigint* (:setup (lambda () (ignore-errors (clsql:execute-command "DROP TABLE TYPE_BIGINT")) (clsql:execute-command "CREATE TABLE TYPE_BIGINT (T_INT integer, T_BIGINT BIGINT)") (dotimes (i 11) (clsql:execute-command (format nil "INSERT INTO TYPE_BIGINT VALUES (~a,~a)" (- i 5) (transform-bigint-1 (- i 5))))))) (:cleanup "DROP TABLE TYPE_BIGINT")) ;;;; Testing functions (defun transform-float-1 (i) (coerce (* i (abs (/ i 2)) (expt 10 (* 2 i))) 'double-float)) (defun transform-bigint-1 (i) (* i (expt 10 (* 3 (abs i))))) (defun parse-double (num-str) (let ((*read-default-float-format* 'double-float)) (coerce (read-from-string num-str) 'double-float))) (defun double-float-equal (a b) (if (zerop a) (if (zerop b) t nil) (let ((diff (abs (/ (- a b) a)))) (if (> diff (* 10 double-float-epsilon)) nil t)))) (def-dataset *ds-bigtext* (:setup "CREATE TABLE testbigtext(a varchar(7500))") (:cleanup "DROP TABLE testbigtext")) cl-sql-6.4.1/tests/test-fdml.lisp0000644000175000017500000006472211616055736015706 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ====================================================================== ;;;; File: test-fdml.lisp ;;;; Author: Marcus Pearce , Kevin Rosenberg ;;;; Created: 30/03/2004 ;;;; ;;;; Tests for the CLSQL Functional Data Manipulation Language ;;;; (FDML). ;;;; ;;;; This file is part of CLSQL. ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ====================================================================== (in-package #:clsql-tests) (clsql-sys:file-enable-sql-reader-syntax) ;;started defining an independent dataset that doesn't depend on the view-classes ;; but there is a *lot* of stuff in the file assuming that dataset. ;; (def-dataset *ds-fdml* ;; (:setup (lambda () ;; (let ((*backend-warning-behavior* ;; (if (member *test-database-type* '(:postgresql :postgresql-socket)) ;; :ignore ;; :warn))) ;; (clsql-sys:execute-command "CREATE TABLE EMPLOYEE ( ;; emplid integer NOT NULL, ;; groupid integer NOT NULL, ;; first_name character varying(30), ;; last_name character varying(30), ;; email character varying(100), ;; ecompanyid integer, ;; managerid integer, ;; height double precision, ;; married boolean, ;; birthday timestamp, ;; bd_utime bigint, ;; CONSTRAINT employeepk PRIMARY KEY (emplid, groupid), ;; CONSTRAINT employee_emplid_key UNIQUE (emplid) ;; )")))) ;; (:sqldata "EMPLOYEE" ;; "emplid,groupid,first_name,last_name,email,height,birthday" ;; "10,1,'a','b','a@b.org',1.9,current_timestamp" ;; "11,1,'x','y','x@y.org',null,current_timestamp" ;; ) ;; (:cleanup "DROP TABLE EMPLOYEE") ;; ) (setq *rt-fdml* '( ;; Computed values are not always classified as numeric by psqlodbc (deftest :fdml/query/1 (with-dataset *ds-employees* (let ((count (caar (clsql:query "SELECT COUNT(*) FROM EMPLOYEE WHERE (EMAIL LIKE '%org')" :field-names nil)))) (%get-int count))) 10) (deftest :fdml/query/2 (with-dataset *ds-employees* (multiple-value-bind (rows field-names) (clsql:query "SELECT FIRST_NAME,LAST_NAME FROM EMPLOYEE WHERE (EMPLID <= 5) ORDER BY LAST_NAME") (values rows (mapcar 'string-upcase field-names)))) (("Leonid" "Brezhnev") ("Nikita" "Kruschev") ("Vladimir" "Lenin") ("Josef" "Stalin") ("Leon" "Trotsky")) ("FIRST_NAME" "LAST_NAME")) (deftest :fdml/query/3 (with-dataset *ds-employees* (caar (clsql:query "SELECT EMPLID FROM EMPLOYEE WHERE LAST_NAME = 'Andropov'" :field-names nil))) 6) (deftest :fdml/query/4 (with-dataset *ds-employees* (typep (caar (clsql:query "SELECT HEIGHT FROM EMPLOYEE WHERE LAST_NAME = 'Andropov'" :field-names nil)) 'float)) t) (deftest :fdml/query/5 (with-dataset *ds-employees* (let ((res (clsql:query (clsql:sql [select [first-name] [sum [emplid]] :from [employee]] [group-by [first-name]] [order-by [sum [emplid]]]) :field-names nil :result-types nil))) (mapcar (lambda (p) (list (car p) (%get-int (second p)))) res))) (("Josef" 2) ("Leon" 3) ("Nikita" 4) ("Leonid" 5) ("Yuri" 6) ("Konstantin" 7) ("Mikhail" 8) ("Boris" 9) ("Vladimir" 11))) (deftest :fdml/query/6 (with-dataset *ds-employees* (let ((res (clsql:query (clsql:sql [union [select [emplid] :from [employee]] [select [groupid] :from [company]]]) :field-names nil :result-types nil :flatp t ))) (values (or (eql *test-database-type* :postgresql-socket3) (every #'stringp res)) (sort (mapcar #'%get-int res) #'<=)))) t (1 2 3 4 5 6 7 8 9 10)) (deftest :fdml/query/7 (with-dataset *ds-employees* (let ((res (car (clsql:query (clsql:sql [intersect [select [emplid] :from [employee]] [select [groupid] :from [company]]]) :field-names nil :result-types nil :flatp t)))) (values (or (stringp res) (eql *test-database-type* :postgresql-socket3)) (nth-value 0 (%get-int res))))) t 1) (deftest :fdml/query/8 (with-dataset *ds-employees* (let ((res (clsql:query (clsql:sql [except [select [emplid] :from [employee]] [select [groupid] :from [company]]]) :field-names nil :result-types nil :flatp t))) (values (or (every #'stringp res) (eql *test-database-type* :postgresql-socket3)) (sort (mapcar #'%get-int res) #'<=)))) t (2 3 4 5 6 7 8 9 10)) ;; compare min, max and average hieghts in inches (they're quite short ;; these guys!) (deftest :fdml/select/1 (with-dataset *ds-employees* (let ((max (clsql:select [function "floor" [/ [* [max [height]] 100] 2.54]] :from [employee] :result-types nil :flatp t)) (min (clsql:select [function "floor" [/ [* [min [height]] 100] 2.54]] :from [employee] :result-types nil :flatp t)) (avg (clsql:select [function "floor" [avg [/ [* [height] 100] 2.54]]] :from [employee] :result-types nil :flatp t))) (apply #'< (mapcar #'%get-int (append min avg max))))) t) (deftest :fdml/select/2 (with-dataset *ds-employees* (clsql:select [first-name] :from [employee] :flatp t :distinct t :field-names nil :result-types nil :order-by [first-name])) ("Boris" "Josef" "Konstantin" "Leon" "Leonid" "Mikhail" "Nikita" "Vladimir" "Yuri")) (deftest :fdml/select/3 (with-dataset *ds-employees* (let ((res (clsql:select [first-name] [count [*]] :from [employee] :result-types nil :group-by [first-name] :order-by [first-name] :field-names nil))) (mapcar (lambda (p) (list (car p) (%get-int (second p)))) res))) (("Boris" 1) ("Josef" 1) ("Konstantin" 1) ("Leon" 1) ("Leonid" 1) ("Mikhail" 1) ("Nikita" 1) ("Vladimir" 2) ("Yuri" 1))) (deftest :fdml/select/4 (with-dataset *ds-employees* (clsql:select [last-name] :from [employee] :where [like [email] "%org"] :order-by [last-name] :field-names nil :result-types nil :flatp t)) ("Andropov" "Brezhnev" "Chernenko" "Gorbachev" "Kruschev" "Lenin" "Putin" "Stalin" "Trotsky" "Yeltsin")) (deftest :fdml/select/5 (with-dataset *ds-employees* (clsql:select [email] :from [employee] :flatp t :result-types nil :where [in [employee emplid] [select [managerid] :from [employee]]] :field-names nil)) ("lenin@soviet.org")) (deftest :fdml/select/6 (with-dataset *ds-employees* (if (clsql-sys:db-type-has-fancy-math? *test-database-underlying-type*) (mapcar #'%get-int (clsql:select [function "trunc" [height]] :from [employee] :result-types nil :field-names nil :flatp t)) (mapcar #'%get-int (clsql:select [height] :from [employee] :flatp t :field-names nil :result-types nil)))) (1 1 1 1 1 1 1 1 1 1)) (deftest :fdml/select/7 (with-dataset *ds-employees* (let ((result (car (clsql:select [max [emplid]] :from [employee] :flatp t :field-names nil :result-types nil)))) (values (nth-value 0 (%get-int result))))) 10) (deftest :fdml/select/8 (with-dataset *ds-employees* (let ((result (car (clsql:select [min [emplid]] :from [employee] :flatp t :field-names nil :result-types nil)))) (values (nth-value 0 (%get-int result))))) 1) (deftest :fdml/select/9 (with-dataset *ds-employees* (let ((val (car (clsql:select [avg [emplid]] :from [employee] :flatp t :field-names nil :result-types nil)))) (typecase val (string (subseq val 0 3)) (number (format nil "~,1F" val))))) "5.5") (deftest :fdml/select/10 (with-dataset *ds-employees* (clsql:select [last-name] :from [employee] :where [not [in [emplid] [select [managerid] :from [company]]]] :result-types nil :field-names nil :flatp t :order-by [last-name])) ("Andropov" "Brezhnev" "Chernenko" "Gorbachev" "Kruschev" "Putin" "Stalin" "Trotsky" "Yeltsin")) (deftest :fdml/select/11 (with-dataset *ds-employees* (clsql:select [last-name] :from [employee] :where [married] :flatp t :field-names nil :order-by [emplid] :result-types nil)) ("Lenin" "Stalin" "Trotsky")) (deftest :fdml/select/12 (with-dataset *ds-employees* (let ((v 1)) (clsql:select [last-name] :from [employee] :where [= [emplid] v] :field-names nil :result-types nil))) (("Lenin"))) (deftest :fdml/select/13 (with-dataset *ds-employees* (multiple-value-bind (results field-names) (clsql:select [emplid] [last-name] :from [employee] :where [= [emplid] 1]) (values results (mapcar #'string-downcase field-names)))) ((1 "Lenin")) ("emplid" "last_name")) (deftest :fdml/select/14 (with-dataset *ds-employees* (floatp (car (clsql:select [height] :from [employee] :where [= [emplid] 1] :flatp t)))) t) (deftest :fdml/select/15 (with-dataset *ds-employees* (multiple-value-bind (rows field-names) (clsql:select [addressid] [street-number] [street-name] [city_field] [zip] :from [addr] :where [= 1 [addressid]]) (values rows (mapcar #'string-downcase field-names)))) ((1 10 "Park Place" "Leningrad" 123)) ("addressid" "street_number" "street_name" "city_field" "zip")) (deftest :fdml/select/16 (with-dataset *ds-employees* (clsql:select [emplid] :from [employee] :where [= 1 [emplid]] :field-names nil)) ((1))) (deftest :fdml/select/17 (with-dataset *ds-employees* (clsql:select [emplid] [last-name] :from [employee] :where [= 1 [emplid]] :field-names nil)) ((1 "Lenin"))) (deftest :fdml/select/18 (with-dataset *ds-employees* (clsql:select [emplid :string] [last-name] :from [employee] :where [= 1 [emplid]] :field-names nil)) (("1" "Lenin"))) (deftest :fdml/select/19 (with-dataset *ds-employees* (mapcar #'%get-int (clsql:select [emplid] :from [employee] :order-by [emplid] :where [between [* [emplid] 10] [* 5 10] [* 10 10]] :field-names nil :result-types nil :flatp t))) (5 6 7 8 9 10)) (deftest :fdml/select/20 (with-dataset *ds-employees* (mapcar #'%get-int (clsql:select [emplid] :from [employee] :order-by [emplid] :where [not [between [* [emplid] 10] [* 5 10] [* 10 10]]] :field-names nil :result-types nil :flatp t))) (1 2 3 4)) (deftest :fdml/select/21 (with-dataset *ds-employees* (clsql:select [substring [first-name] 1 4] :from [employee] :flatp t :order-by [emplid] :field-names nil)) ("Vlad" "Jose" "Leon" "Niki" "Leon" "Yuri" "Kons" "Mikh" "Bori" "Vlad")) (deftest :fdml/select/22 (with-dataset *ds-employees* (case *test-database-underlying-type* (:mssql (clsql:select [+ [first-name] " " [last-name]] :from [employee] :flatp t :order-by [emplid] :field-names nil)) (t (clsql:select [|| [first-name] " " [last-name]] :from [employee] :flatp t :order-by [emplid] :field-names nil)))) ("Vladimir Lenin" "Josef Stalin" "Leon Trotsky" "Nikita Kruschev" "Leonid Brezhnev" "Yuri Andropov" "Konstantin Chernenko" "Mikhail Gorbachev" "Boris Yeltsin" "Vladimir Putin")) (deftest :fdml/select/23 (with-dataset *ds-employees* (mapcar #'%get-int (clsql:select [emplid] :from [employee] :where [in [emplid] '(1 2 3 4)] :flatp t :order-by [emplid] :field-names nil :result-types nil))) (1 2 3 4)) (deftest :fdml/select/24 (with-dataset *ds-employees* (clsql:select [distinct [first-name]] :from [employee] :flatp t :order-by [first-name] :field-names nil :result-types nil)) ("Boris" "Josef" "Konstantin" "Leon" "Leonid" "Mikhail" "Nikita" "Vladimir" "Yuri")) (deftest :fdml/select/25 (with-dataset *ds-employees* (clsql:select [first-name] :from (clsql-sys:convert-to-db-default-case "employee" *default-database*) :flatp t :distinct t :field-names nil :result-types nil :order-by [first-name])) ("Boris" "Josef" "Konstantin" "Leon" "Leonid" "Mikhail" "Nikita" "Vladimir" "Yuri")) (deftest :fdml/select/26 (with-dataset *ds-employees* (clsql:select ["table" first-name] ["table" last-name] :from '([employee "table"] [employee "join"]) :where [and [= ["table" first-name] ["join" first-name]] [not [= ["table" emplid] ["join" emplid]]]] :order-by '(["table" last-name]) :result-types nil :field-names nil)) (("Vladimir" "Lenin") ("Vladimir" "Putin"))) (deftest :fdml/select/27 (with-dataset *ds-employees* (mapcar #'%get-int (clsql:select [coalesce [managerid] 10] :from [employee] :order-by [emplid] :field-names nil :result-types nil :flatp t))) (10 1 1 1 1 1 1 1 1 1)) (deftest :fdml/select/28 (with-dataset *ds-employees* (loop for column in `([*] [emplid]) collect (%get-int (car (clsql:select [count column] :from [employee] :flatp t :result-types nil :field-names nil))))) (10 10)) (deftest :fdml/select/29 (with-dataset *ds-employees* (clsql:select [first-name] [last-name] :from [employee] :result-types nil :field-names nil :order-by '(([first-name] :asc) ([last-name] :desc)))) (("Boris" "Yeltsin") ("Josef" "Stalin") ("Konstantin" "Chernenko") ("Leon" "Trotsky") ("Leonid" "Brezhnev") ("Mikhail" "Gorbachev") ("Nikita" "Kruschev") ("Vladimir" "Putin") ("Vladimir" "Lenin") ("Yuri" "Andropov"))) (deftest :fdml/select/30 (with-dataset *ds-employees* (clsql:select [first-name] [last-name] :from [employee] :result-types nil :field-names nil :order-by '(([first-name] :asc) ([last-name] :asc)))) (("Boris" "Yeltsin") ("Josef" "Stalin") ("Konstantin" "Chernenko") ("Leon" "Trotsky") ("Leonid" "Brezhnev") ("Mikhail" "Gorbachev") ("Nikita" "Kruschev") ("Vladimir" "Lenin") ("Vladimir" "Putin") ("Yuri" "Andropov"))) (deftest :fdml/select/31 (with-dataset *ds-employees* (clsql:select [last-name] :from [employee] :set-operation [union [select [first-name] :from [employee] :order-by [last-name]]] :flatp t :result-types nil :field-names nil)) ("Andropov" "Boris" "Brezhnev" "Chernenko" "Gorbachev" "Josef" "Konstantin" "Kruschev" "Lenin" "Leon" "Leonid" "Mikhail" "Nikita" "Putin" "Stalin" "Trotsky" "Vladimir" "Yeltsin" "Yuri")) (deftest :fdml/select/32 (with-dataset *ds-employees* (mapcar #'%get-int (clsql:select [emplid] :from [employee] :where [= [emplid] [any [select [companyid] :from [company]]]] :flatp t :result-types nil :field-names nil))) (1)) (deftest :fdml/select/33 (with-dataset *ds-employees* (clsql:select [last-name] :from [employee] :where [> [emplid] [all [select [groupid] :from [employee]]]] :order-by [last-name] :flatp t :result-types nil :field-names nil)) ("Andropov" "Brezhnev" "Chernenko" "Gorbachev" "Kruschev" "Putin" "Stalin" "Trotsky" "Yeltsin")) (deftest :fdml/select/34 (with-dataset *ds-employees* (loop for x from 1 below 5 collect (car (clsql:select [last-name] :from [employee] :where [= [emplid] x] :flatp t :result-types nil :field-names nil)))) ("Lenin" "Stalin" "Trotsky" "Kruschev")) ;; test escaping of single quotes (deftest :fdml/select/35 (with-dataset *ds-fddl* (first (clsql:select "What's up doc?" :from [alpha] :flatp t :field-names nil))) "What's up doc?") ;; test proper treatment of backslash (depending on backend) (deftest :fdml/select/36 (with-dataset *ds-fddl* (first (clsql:select "foo\\bar\\baz" :from [alpha] :flatp t :field-names nil))) "foo\\bar\\baz") (deftest :fdml/select/37 (with-dataset *ds-employees* (clsql:select [emplid] :from [employee] :order-by [emplid] :limit 5 :field-names nil :flatp t)) (1 2 3 4 5)) (deftest :fdml/select/38 (with-dataset *ds-employees* (clsql:select [emplid] :from [employee] :order-by [emplid] :limit 5 :offset 3 :field-names nil :flatp t)) (4 5 6 7 8)) (deftest :fdml/do-query/1 (with-dataset *ds-employees* (let ((result '())) (clsql:do-query ((name) [select [last-name] :from [employee] :order-by [last-name]]) (push name result)) result)) ("Yeltsin" "Trotsky" "Stalin" "Putin" "Lenin" "Kruschev" "Gorbachev" "Chernenko" "Brezhnev" "Andropov")) (deftest :fdml/map-query/1 (with-dataset *ds-employees* (clsql:map-query 'list #'identity [select [last-name] :from [employee] :flatp t :order-by [last-name]])) ("Andropov" "Brezhnev" "Chernenko" "Gorbachev" "Kruschev" "Lenin" "Putin" "Stalin" "Trotsky" "Yeltsin")) (deftest :fdml/map-query/2 (with-dataset *ds-employees* (clsql:map-query 'vector #'identity [select [last-name] :from [employee] :flatp t :order-by [last-name]])) #("Andropov" "Brezhnev" "Chernenko" "Gorbachev" "Kruschev" "Lenin" "Putin" "Stalin" "Trotsky" "Yeltsin")) (deftest :fdml/map-query/3 (with-dataset *ds-employees* (clsql:map-query 'list #'identity [select [last-name] :from [employee] :order-by [last-name]])) (("Andropov") ("Brezhnev") ("Chernenko") ("Gorbachev") ("Kruschev") ("Lenin") ("Putin") ("Stalin") ("Trotsky") ("Yeltsin"))) (deftest :fdml/map-query/4 (with-dataset *ds-employees* (clsql:map-query 'list #'identity [select [first-name] [last-name] :from [employee] :order-by [last-name]])) (("Yuri" "Andropov") ("Leonid" "Brezhnev") ("Konstantin" "Chernenko") ("Mikhail" "Gorbachev") ("Nikita" "Kruschev") ("Vladimir" "Lenin") ("Vladimir" "Putin") ("Josef" "Stalin") ("Leon" "Trotsky") ("Boris" "Yeltsin"))) (deftest :fdml/loop/1 (with-dataset *ds-employees* (loop for (forename surname) being each tuple in [select [first-name] [last-name] :from [employee] :order-by [last-name]] collect (concatenate 'string forename " " surname))) ("Yuri Andropov" "Leonid Brezhnev" "Konstantin Chernenko" "Mikhail Gorbachev" "Nikita Kruschev" "Vladimir Lenin" "Vladimir Putin" "Josef Stalin" "Leon Trotsky" "Boris Yeltsin")) (deftest :fdml/loop/2 (with-dataset *ds-employees* (loop for (addressid) being each tuple in [select [addressid] :from [addr] :order-by [addressid]] collect addressid)) (1 2)) (deftest :fdml/loop/3 (with-dataset *ds-employees* (loop for addressid being each tuple in [select [addressid] :from [addr] :order-by [addressid]] collect addressid)) (1 2)) ;; inserts a record using all values only and then deletes it (deftest :fdml/insert/1 (with-dataset *ds-employees* (let ((now (get-universal-time))) (clsql:insert-records :into [employee] :values `(11 1 "Yuri" "Gagarin" "gagarin@soviet.org" 1 1 1.85 t ,(clsql:utime->time now) ,now)) (values (clsql:select [first-name] [last-name] [email] :from [employee] :where [= [emplid] 11]) (progn (clsql:delete-records :from [employee] :where [= [emplid] 11]) (clsql:select [*] :from [employee] :where [= [emplid] 11]))))) (("Yuri" "Gagarin" "gagarin@soviet.org")) nil) ;; inserts a record using attributes and values and then deletes it (deftest :fdml/insert/2 (with-dataset *ds-employees* (progn (clsql:insert-records :into [employee] :attributes '(emplid groupid first_name last_name email ecompanyid managerid) :values '(11 1 "Yuri" "Gagarin" "gagarin@soviet.org" 1 1)) (values (clsql:select [first-name] [last-name] [email] :from [employee] :where [= [emplid] 11]) (progn (clsql:delete-records :from [employee] :where [= [emplid] 11]) (clsql:select [*] :from [employee] :where [= [emplid] 11]))))) (("Yuri" "Gagarin" "gagarin@soviet.org")) nil) ;; inserts a record using av-pairs and then deletes it (deftest :fdml/insert/3 (with-dataset *ds-employees* (progn (clsql:insert-records :into [employee] :av-pairs'((emplid 11) (groupid 1) (first_name "Yuri") (last_name "Gagarin") (email "gagarin@soviet.org") (ecompanyid 1) (managerid 1))) (values (clsql:select [first-name] [last-name] [email] :from [employee] :where [= [emplid] 11]) (progn (clsql:delete-records :from [employee] :where [= [emplid] 11]) (clsql:select [first-name] [last-name] [email] :from [employee] :where [= [emplid] 11]))))) (("Yuri" "Gagarin" "gagarin@soviet.org")) nil) ;; inserts a records using a query from another table (deftest :fdml/insert/4 (with-dataset *ds-employees* (progn (clsql:create-table [employee2] '(([forename] string) ([surname] string) ([email] string))) (clsql:insert-records :into [employee2] :query [select [first-name] [last-name] [email] :from [employee]] :attributes '(forename surname email)) (prog1 (equal (clsql:select [*] :from [employee2]) (clsql:select [first-name] [last-name] [email] :from [employee])) (clsql:drop-table [employee2] :if-does-not-exist :ignore)))) t) ;; updates a record using attributes and values and then deletes it (deftest :fdml/update/1 (with-dataset *ds-employees* (progn (clsql:update-records [employee] :attributes '(first_name last_name email) :values '("Yuri" "Gagarin" "gagarin@soviet.org") :where [= [emplid] 1]) (values (clsql:select [first-name] [last-name] [email] :from [employee] :where [= [emplid] 1]) (progn (clsql:update-records [employee] :av-pairs'((first_name "Vladimir") (last_name "Lenin") (email "lenin@soviet.org")) :where [= [emplid] 1]) (clsql:select [first-name] [last-name] [email] :from [employee] :where [= [emplid] 1]))))) (("Yuri" "Gagarin" "gagarin@soviet.org")) (("Vladimir" "Lenin" "lenin@soviet.org"))) ;; updates a record using av-pairs and then deletes it (deftest :fdml/update/2 (with-dataset *ds-employees* (progn (clsql:update-records [employee] :av-pairs'((first_name "Yuri") (last_name "Gagarin") (email "gagarin@soviet.org")) :where [= [emplid] 1]) (values (clsql:select [first-name] [last-name] [email] :from [employee] :where [= [emplid] 1]) (progn (clsql:update-records [employee] :av-pairs'((first_name "Vladimir") (last_name "Lenin") (email "lenin@soviet.org")) :where [= [emplid] 1]) (clsql:select [first-name] [last-name] [email] :from [employee] :where [= [emplid] 1]))))) (("Yuri" "Gagarin" "gagarin@soviet.org")) (("Vladimir" "Lenin" "lenin@soviet.org"))) ;; starts a transaction deletes a record and then rolls back the deletion (deftest :fdml/transaction/1 (with-dataset *ds-employees* (let ((results '())) ;; test if we are in a transaction (push (clsql:in-transaction-p) results) ;;start a transaction (clsql:start-transaction) ;; test if we are in a transaction (push (clsql:in-transaction-p) results) ;;Putin has got to go (clsql:delete-records :from [employee] :where [= [last-name] "Putin"]) ;;Should be nil (push (clsql:select [*] :from [employee] :where [= [last-name] "Putin"]) results) ;;Oh no, he's still there (clsql:rollback) ;; test that we are out of the transaction (push (clsql:in-transaction-p) results) ;; Check that we got him back alright (push (clsql:select [email] :from [employee] :where [= [last-name] "Putin"] :flatp t) results) (apply #'values (nreverse results)))) nil t nil nil ("putin@soviet.org")) ;; starts a transaction, updates a record and then rolls back the update (deftest :fdml/transaction/2 (with-dataset *ds-employees* (let ((results '())) ;; test if we are in a transaction (push (clsql:in-transaction-p) results) ;;start a transaction (clsql:start-transaction) ;; test if we are in a transaction (push (clsql:in-transaction-p) results) ;;Putin has got to go (clsql:update-records [employee] :av-pairs '((email "putin-nospam@soviet.org")) :where [= [last-name] "Putin"]) ;;Should be new value (push (clsql:select [email] :from [employee] :where [= [last-name] "Putin"] :flatp t) results) ;;Oh no, he's still there (clsql:rollback) ;; test that we are out of the transaction (push (clsql:in-transaction-p) results) ;; Check that we got him back alright (push (clsql:select [email] :from [employee] :where [= [last-name] "Putin"] :flatp t) results) (apply #'values (nreverse results)))) nil t ("putin-nospam@soviet.org") nil ("putin@soviet.org")) ;; runs an update within a transaction and checks it is committed (deftest :fdml/transaction/3 (with-dataset *ds-employees* (let ((results '())) ;; check status (push (clsql:in-transaction-p) results) ;; update records (push (clsql:with-transaction () (clsql:update-records [employee] :av-pairs '((email "lenin-nospam@soviet.org")) :where [= [emplid] 1])) results) ;; check status (push (clsql:in-transaction-p) results) ;; check that was committed (push (clsql:select [email] :from [employee] :where [= [emplid] 1] :flatp t) results) ;; undo the changes (push (clsql:with-transaction () (clsql:update-records [employee] :av-pairs '((email "lenin@soviet.org")) :where [= [emplid] 1])) results) ;; and check status (push (clsql:in-transaction-p) results) ;; check that was committed (push (clsql:select [email] :from [employee] :where [= [emplid] 1] :flatp t) results) (apply #'values (nreverse results)))) nil nil nil ("lenin-nospam@soviet.org") nil nil ("lenin@soviet.org")) ;; runs a valid update and an invalid one within a transaction and checks ;; that the valid update is rolled back when the invalid one fails. (deftest :fdml/transaction/4 (with-dataset *ds-employees* (let ((results '())) ;; check status (push (clsql:in-transaction-p) results) (handler-case (clsql:with-transaction () ;; valid update (clsql:update-records [employee] :av-pairs '((email "lenin-nospam@soviet.org")) :where [= [emplid] 1]) ;; invalid update which generates an error (clsql:update-records [employee] :av-pairs '((emale "lenin-nospam@soviet.org")) :where [= [emplid] 1])) (clsql:sql-database-error () (progn ;; check status (push (clsql:in-transaction-p) results) ;; and check nothing done (push (clsql:select [email] :from [employee] :where [= [emplid] 1] :flatp t) results) (apply #'values (nreverse results))))))) nil nil ("lenin@soviet.org")) )) cl-sql-6.4.1/tests/test-syntax.lisp0000644000175000017500000002761211746263021016277 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; FILE IDENTIFICATION ;;;; ;;;; Name: clsql.asd ;;;; Purpose: Tests for the CLSQL Symbolic SQL syntax. ;;;; Authors: Marcus Pearce and Kevin M. Rosenberg ;;;; Created: March 2004 ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* (in-package #:clsql-tests) (clsql-sys:file-enable-sql-reader-syntax) (setq *rt-syntax* '( (deftest :syntax/generic/1 (clsql:sql "foo") "'foo'") (deftest :syntax/generic/2 (clsql:sql 23) "23") (deftest :syntax/generic/3 (clsql:sql 'bar) "BAR") (deftest :syntax/generic/4 (clsql:sql '("ten" 10 ten)) "('ten',10,TEN)") (deftest :syntax/generic/5 (clsql:sql ["SELECT FOO,BAR FROM BAZ"]) "SELECT FOO,BAR FROM BAZ") (deftest :syntax/generic/6 (clsql:sql "What's up Doc?") "'What''s up Doc?'") (deftest :syntax/ident/1 (clsql:sql [foo]) "FOO") (deftest :syntax/ident/2 (clsql:sql [foo bar]) "FOO.BAR") (deftest :syntax/ident/3 (clsql:sql [foo :integer]) "FOO") (deftest :syntax/ident/4 (clsql:sql [foo bar :integer]) "FOO.BAR") (deftest :syntax/ident/5 (clsql:sql [foo "bar"]) "FOO \"bar\"") (deftest :syntax/ident/6 (clsql:sql ["foo" bar]) "\"foo\".BAR") (deftest :syntax/ident/7 (clsql:sql ["foo" bar :integer]) "\"foo\".BAR") (deftest :syntax/attribute/1 (clsql:sql (clsql:sql-expression :table 'foo :attribute 'bar)) "FOO.BAR") (deftest :syntax/attribute/2 (clsql:sql (clsql:sql-expression :table 'foo :attribute "bar")) "FOO.\"bar\"") (deftest :syntax/attribute/3 (clsql:sql (clsql:sql-expression :table "foo" :attribute 'bar)) "\"foo\".BAR") (deftest :syntax/attribute/4 (clsql:sql (clsql:sql-expression :table "foo" :attribute "bar")) "\"foo\".\"bar\"") (deftest :syntax/subquery/1 (clsql:sql [any '(3 4)]) "ANY((3,4))") (deftest :syntax/subquery/2 (clsql:sql [in [foo] '(foo bar baz)]) "(FOO IN (FOO,BAR,BAZ))") (deftest :syntax/subquery/3 (clsql:sql [all '(foo bar baz)]) "ALL((FOO,BAR,BAZ))") (deftest :syntax/subquery/4 (clsql:sql [exists '(foo bar baz)]) "EXISTS((FOO,BAR,BAZ))") (deftest :syntax/subquery/5 (clsql:sql [some '(foo bar baz)]) "SOME((FOO,BAR,BAZ))") (deftest :syntax/aggregate/1 (clsql:sql [max [+ [foo] [* 1000 [bar]]]]) "MAX((FOO + (1000 * BAR)))") (deftest :syntax/aggregate/2 (clsql:sql [avg [+ [foo] [* 1000 [bar]]]]) "AVG((FOO + (1000 * BAR)))") (deftest :syntax/aggregate/3 (clsql:sql [min [+ [foo] [* 1000 [bar]]]]) "MIN((FOO + (1000 * BAR)))") (deftest :syntax/aggregate/4 (clsql:sql [sum [foo] [bar]]) "SUM(FOO,BAR)") (deftest :syntax/aggregate/5 (clsql:sql [count [foo]]) "COUNT(FOO)") (deftest :syntax/logical/1 (values (clsql:sql [and [foo] [bar]]) (clsql:sql [or [foo] [bar]])) "(FOO AND BAR)" "(FOO OR BAR)") (deftest :syntax/logical/2 (clsql:sql [not [foo]]) "(NOT (FOO))") ;;; Test how we apply logical operators when we have different numbers of children ;;; This is useful if we wish to (apply #'sql-and some-list) without having to do ;;; alot of length checking (deftest :syntax/logical/3 (values (clsql:sql [and ]) (clsql:sql [and [foo]]) (clsql:sql [and [not [foo]]]) (clsql:sql [and [foo] [bar] [baz]])) "" "FOO" "(NOT (FOO))" "(FOO AND BAR AND BAZ)") (deftest :syntax/logical/4 (clsql:sql [and [= [foo] [bar]]]) "(FOO = BAR)") (deftest :syntax/logical/5 (clsql:sql [and [= [foo] [bar]] [= [bar] [bast]] [= [block] [blech]]]) "((FOO = BAR) AND (BAR = BAST) AND (BLOCK = BLECH))") (deftest :syntax/logical/6 (clsql:sql (apply #'sql-and (list [= [foo] [bar]] [and ] [and [= [bar] [bast]]]))) "((FOO = BAR) AND (BAR = BAST))") (deftest :syntax/null/1 (clsql:sql [null [foo]]) "(FOO IS NULL)") (deftest :syntax/null/2 (clsql:sql [not [null [foo]]]) "(NOT ((FOO IS NULL)))") (deftest :syntax/null/3 (clsql:sql [null]) "NULL") (deftest :syntax/null/4 (clsql:sql [not [null]]) "(NOT (NULL))") (deftest :syntax/null/5 (clsql:sql [is [foo.bar] [null]]) "(FOO.BAR IS NULL)") (deftest :syntax/null/6 (clsql:sql [is [foo.bar] [not-null]]) "(FOO.BAR IS NOT NULL)") (deftest :syntax/null/7 (clsql:sql [not-null [foo.bar]]) "(FOO.BAR IS NOT NULL)") (deftest :syntax/relational/1 (clsql:sql [> [baz] [beep]]) "(BAZ > BEEP)") (deftest :syntax/relational/2 (let ((x 10)) (clsql:sql [> [foo] x])) "(FOO > 10)") (deftest :syntax/relational/3 (clsql:sql [>= [baz] [beep]]) "(BAZ >= BEEP)") (deftest :syntax/relational/4 (clsql:sql [< [baz] [beep]]) "(BAZ < BEEP)") (deftest :syntax/relational/5 (clsql:sql [= [baz] [beep]]) "(BAZ = BEEP)") (deftest :syntax/relational/6 (clsql:sql [<> [baz] [beep]]) "(BAZ <> BEEP)") (deftest :syntax/between/1 (clsql:sql [between [- [foo] 1] [* [bar] 5] [/ [baz] 9]]) "(FOO - 1) BETWEEN (BAR * 5) AND (BAZ / 9)") (deftest :syntax/between/2 (clsql:sql [not [between [- [foo] 1] [* [bar] 5] [/ [baz] 9]]]) "(NOT ((FOO - 1) BETWEEN (BAR * 5) AND (BAZ / 9)))") (deftest :syntax/arithmetic/1 (clsql:sql [+ [foo bar] [baz]]) "(FOO.BAR + BAZ)") (deftest :syntax/arithmetic/2 (clsql:sql [- [foo bar] [baz]]) "(FOO.BAR - BAZ)") (deftest :syntax/arithmetic/3 (clsql:sql [/ [foo bar] [baz]]) "(FOO.BAR / BAZ)") (deftest :syntax/arithmetic/4 (clsql:sql [* [foo bar] [baz]]) "(FOO.BAR * BAZ)") (deftest :syntax/arithmetic/5 (clsql:sql [- [foo bar]]) "(- (FOO.BAR))") (deftest :syntax/arithmetic/6 (clsql:sql [* 2 3]) "(2 * 3)") (deftest :syntax/substr/1 (clsql:sql [substr [hello] 1 4]) "SUBSTR(HELLO,1,4)") (deftest :syntax/substring/1 (clsql:sql [substring [hello] 1 4]) "SUBSTRING(HELLO,1,4)") (deftest :syntax/concat/1 (clsql:sql [|| [foo] [bar] [baz]]) "(FOO || BAR || BAZ)") (deftest :syntax/concat/2 (clsql:sql [concat [foo] [bar]]) "CONCAT(FOO,BAR)") (deftest :syntax/pattern/1 (clsql:sql [like [foo] "%v"]) "(FOO LIKE '%v')") (deftest :syntax/pattern/2 (clsql:sql [not [like [foo] "%v"]]) "(NOT ((FOO LIKE '%v')))") (deftest :syntax/distinct/1 (clsql:sql [distinct [foo bar :string]]) "DISTINCT FOO.BAR") (deftest :syntax/distinct/2 (clsql:sql [distinct [foo :string] [bar :integer]]) "DISTINCT FOO, BAR") (deftest :syntax/order-by/1 (clsql:sql [order-by [foo]]) "ORDER BY FOO") (deftest :syntax/group-by/1 (clsql:sql [group-by [foo]]) "GROUP BY FOO") (deftest :syntax/group-by/2 (clsql:sql (clsql-sys::make-query [foo] [bar] [count [foo]] :from [table] :group-by '([foo] [bar]) :order-by '([foo] [bar]))) "SELECT FOO,BAR,COUNT(FOO) FROM TABLE GROUP BY FOO,BAR ORDER BY FOO,BAR") (deftest :syntax/coalesce/1 (clsql:sql [coalesce [foo] [bar] "not specified"]) "COALESCE(FOO,BAR,'not specified')") (deftest :syntax/coalesce/2 (clsql:sql [nvl [foo] "not specified"]) "COALESCE(FOO,'not specified')") (deftest :syntax/nvl/1 (clsql:sql [nvl [foo] "not specified"]) "COALESCE(FOO,'not specified')") (deftest :syntax/sets/1 (clsql:sql [union [select [foo] :from [bar]] [select [baz] :from [bar]]]) "SELECT FOO FROM BAR UNION SELECT BAZ FROM BAR") (deftest :syntax/sets/2 (clsql:sql [intersect [select [foo] :from [bar]] [select [baz] :from [bar]]]) "SELECT FOO FROM BAR INTERSECT SELECT BAZ FROM BAR") (deftest :syntax/sets/3 (clsql:sql [except [select [foo] :from [bar]] [select [baz] :from [bar]]]) "SELECT FOO FROM BAR EXCEPT SELECT BAZ FROM BAR") (deftest :syntax/sets/4 (clsql:sql [minus [select [foo] :from [bar]] [select [baz] :from [bar]]]) "SELECT FOO FROM BAR MINUS SELECT BAZ FROM BAR") (deftest :syntax/function/1 (clsql:sql [function "COS" [age]]) "COS(AGE)") (deftest :syntax/function/2 (clsql:sql [function "TO_DATE" "02/06/99" "mm/DD/RR"]) "TO_DATE('02/06/99','mm/DD/RR')") (deftest :syntax/query/1 (clsql:sql [select [person_id] [surname] :from [person]]) "SELECT PERSON_ID,SURNAME FROM PERSON") (deftest :syntax/query/2 (clsql:sql [select [foo] [bar *] :from '([baz] [bar]) :where [or [= [foo] 3] [> [baz.quux] 10]]]) "SELECT FOO,BAR.* FROM BAZ,BAR WHERE ((FOO = 3) OR (BAZ.QUUX > 10))") (deftest :syntax/query/3 (clsql:sql [select [foo bar] [baz] :from '([foo] [quux]) :where [or [> [baz] 3] [like [foo bar] "SU%"]]]) "SELECT FOO.BAR,BAZ FROM FOO,QUUX WHERE ((BAZ > 3) OR (FOO.BAR LIKE 'SU%'))") (deftest :syntax/query/4 (clsql:sql [select [count [*]] :from [emp]]) "SELECT COUNT(*) FROM EMP") (deftest :syntax/expression/1 (clsql:sql (clsql:sql-operation 'select (clsql:sql-expression :table 'foo :attribute 'bar) (clsql:sql-expression :attribute 'baz) :from (list (clsql:sql-expression :table 'foo) (clsql:sql-expression :table 'quux)) :where (clsql:sql-operation 'or (clsql:sql-operation '> (clsql:sql-expression :attribute 'baz) 3) (clsql:sql-operation 'like (clsql:sql-expression :table 'foo :attribute 'bar) "SU%")))) "SELECT FOO.BAR,BAZ FROM FOO,QUUX WHERE ((BAZ > 3) OR (FOO.BAR LIKE 'SU%'))") (deftest :syntax/expression/2 (clsql:sql (apply (clsql:sql-operator 'and) (loop for table in '(thistime nexttime sometime never) for count from 42 collect [function "BETWEEN" (clsql:sql-expression :table table :attribute 'bar) (clsql:sql-operation '* [hip] [hop]) count] collect [like (clsql:sql-expression :table table :attribute 'baz) (clsql:sql table)]))) "(BETWEEN(THISTIME.BAR,(HIP * HOP),42) AND (THISTIME.BAZ LIKE 'THISTIME') AND BETWEEN(NEXTTIME.BAR,(HIP * HOP),43) AND (NEXTTIME.BAZ LIKE 'NEXTTIME') AND BETWEEN(SOMETIME.BAR,(HIP * HOP),44) AND (SOMETIME.BAZ LIKE 'SOMETIME') AND BETWEEN(NEVER.BAR,(HIP * HOP),45) AND (NEVER.BAZ LIKE 'NEVER'))" ) (deftest :syntax/subqueries/query (clsql:sql (clsql:sql-operation 'select [*] :from [foo] :where [in [id] [select [id] :from [bar]]])) "SELECT * FROM FOO WHERE (ID IN (SELECT ID FROM BAR))") (deftest :syntax/subqueries/delete (clsql:sql (make-instance 'clsql-sys::sql-delete :from [foo] :where [in [id] [select [id] :from [bar]]])) "DELETE FROM FOO WHERE (ID IN (SELECT ID FROM BAR))") (deftest :syntax/subqueries/update (clsql:sql (make-instance 'clsql-sys::sql-update :attributes (list [id]) :values '(0) :table [foo] :where [in [id] [select [id] :from [bar]]])) "UPDATE FOO SET ID = 0 WHERE (ID IN (SELECT ID FROM BAR))") )) (let ((tests '(((:foo) "FOO") ((:foo-bar) "FOO_BAR") (("foo") "\"foo\"") (('|foo bar|) "\"foo bar\"") ((:foo :table-alias :bar) "FOO BAR" ) ((:foo_bar :table-alias :bar-bast) "FOO_BAR BAR_BAST") (("foo" :table-alias "Bar") "\"foo\" \"Bar\"") (('|foo bar| :table-alias :bast) "\"foo bar\" BAST")))) (push `(deftest :syntax/sql-ident-table (values ,@(mapcar #'(lambda (args) `(clsql:sql (make-instance 'clsql-sys:sql-ident-table :name ,@args))) (mapcar #'first tests))) ,@(mapcar #'second tests)) *rt-syntax*)) cl-sql-6.4.1/tests/test-fddl.lisp0000644000175000017500000003200711616055736015664 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; FILE IDENTIFICATION ;;;; ;;;; Name: test-fddl.lisp ;;;; Purpose: Tests for the CLSQL Functional Data Definition Language ;;;; Authors: Marcus Pearce and Kevin M. Rosenberg ;;;; Created: March 2004 ;;;; ;;;; This file is part of CLSQL. ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* (in-package #:clsql-tests) (clsql-sys:file-enable-sql-reader-syntax) (def-dataset *ds-fddl* (:setup (lambda () (create-table [alpha] '(([a] integer) ([c] (varchar 30)) ([d] date) ([f] float))) (create-table [bravo] '(([foo] integer) ([bar] integer))))) (:sqldata "ALPHA" "A,C,D,F" "1,'asdf','2010-01-01',3.14" "2,'blarg','2012-12-21',0.1" "3,'matey','1992-02-29',0.0") (:cleanup "DROP TABLE ALPHA" "DROP TABLE BRAVO")) (def-dataset *ds-fddl-parsing-oddities* (:setup "CREATE TABLE ATEST ( A varchar (32), B varchar(32))") (:cleanup "DROP TABLE ATEST")) (setq *rt-fddl* '( ;; list current tables (deftest :fddl/table/1 (with-dataset *ds-fddl* (sort (mapcar #'string-downcase (clsql:list-tables )) #'string<)) ("alpha" "bravo")) ;; create a table, test for its existence, drop it and test again (deftest :fddl/table/2 (progn (clsql:create-table [foo] '(([id] integer) ([height] float) ([name] (string 24)) ([comments] longchar))) (values (clsql:table-exists-p [foo]) (progn (clsql:drop-table [foo] :if-does-not-exist :ignore) (clsql:table-exists-p [foo])))) t nil) ;; create a table, list its attributes and drop it (deftest :fddl/table/3 (apply #'values (progn (clsql:create-table [foo] '(([id] integer) ([height] float) ([name] (char 255)) ([comments] longchar))) (prog1 (sort (mapcar #'string-downcase (clsql:list-attributes [foo])) #'string<) (clsql:drop-table [foo] :if-does-not-exist :ignore)))) "comments" "height" "id" "name") (deftest :fddl/table/4 (values (clsql:table-exists-p "MyMixedCase") (progn (clsql:create-table "MyMixedCase" '(([a] integer))) (clsql:table-exists-p "MyMixedCase")) (progn (clsql:drop-table "MyMixedCase") (clsql:table-exists-p "MyMixedCase"))) nil t nil) (deftest :fddl/table/5 (prog1 (progn (clsql:create-table "MyMixedCase" '(([a] integer))) (clsql:execute-command "insert into \"MyMixedCase\" values (5)") (clsql:insert-records :into "MyMixedCase" :values '(6)) (clsql:select [a] :from "MyMixedCase" :order-by '((a :asc)))) (clsql:drop-table "MyMixedCase")) ((5) (6))) (deftest :fddl/table/6 (values (clsql:table-exists-p [foo]) (progn (let ((*backend-warning-behavior* (if (member *test-database-type* '(:postgresql :postgresql-socket)) :ignore :warn))) (case *test-database-underlying-type* (:mssql (clsql:create-table [foo] '(([bar] integer :not-null :primary-key) ([baz] string :not-null :unique)))) (t (clsql:create-table [foo] '(([bar] integer :not-null :unique :primary-key) ([baz] string :not-null :unique)))))) (clsql:table-exists-p [foo])) (progn (clsql:drop-table [foo]) (clsql:table-exists-p [foo]))) nil t nil) (deftest :fddl/table/7 (values (clsql:table-exists-p [foo]) (progn (let ((*backend-warning-behavior* (if (member *test-database-type* '(:postgresql :postgresql-socket)) :ignore :warn))) (clsql:create-table [foo] '(([bar] integer :not-null) ([baz] string :not-null)) :constraints '("UNIQUE (bar,baz)" "PRIMARY KEY (bar)"))) (clsql:table-exists-p [foo])) (progn (clsql:drop-table [foo]) (clsql:table-exists-p [foo]))) nil t nil) (deftest :fddl/attributes/1 (apply #'values (with-dataset *ds-fddl* (sort (mapcar #'string-downcase (clsql:list-attributes [alpha] )) #'string<))) "a" "c" "d" "f") (deftest :fddl/attributes/2 (with-dataset *ds-fddl* (apply #'values (sort (mapcar #'(lambda (a) (string-downcase (car a))) (clsql:list-attribute-types [alpha])) #'string<))) "a" "c" "d" "f") ;; Attribute types are vendor specific so need to test a range (deftest :fddl/attributes/3 (with-dataset *ds-fddl* (and (member (clsql:attribute-type [a] [alpha]) '(:int :integer :int4 :number)) t)) t) (deftest :fddl/attributes/4 (with-dataset *ds-fddl* (multiple-value-bind (type length scale nullable) (clsql:attribute-type [c] [alpha]) (values (clsql-sys:in type :varchar :varchar2) length scale nullable))) t 30 nil 1) (deftest :fddl/attributes/5 (with-dataset *ds-fddl* (and (member (clsql:attribute-type [d] [alpha]) '(:datetime :timestamp :date :smalldatetime)) t)) t) (deftest :fddl/attributes/6 (with-dataset *ds-fddl* (and (member (clsql:attribute-type [f] [alpha]) '(:float :float8 :number)) t)) t) (deftest :fddl/attributes/7 (with-dataset *ds-bigint* (and (member (clsql:attribute-type [t_bigint] [TYPE_BIGINT]) '(:bigint :int8)) t)) t) (deftest :fddl/attributes/8 ;;this is mostly from sqlite3 sending back (with-dataset *ds-fddl-parsing-oddities* (values (clsql-sys:in (clsql:attribute-type [a] [atest]) :varchar :varchar2) (clsql-sys:in (clsql:attribute-type [b] [atest]) :varchar :varchar2))) t t) ;; create a view, test for existence, drop it and test again (deftest :fddl/view/1 (with-dataset *ds-fddl* (progn (clsql:create-view [v1] :as [select [a] [c] [d] :from [alpha] :where [= [a] 1]]) (values (clsql:view-exists-p [v1]) (progn (clsql:drop-view [v1] :if-does-not-exist :ignore) (clsql:view-exists-p [v1]))))) t nil) ;; create a view, list its attributes and drop it (deftest :fddl/view/2 (with-dataset *ds-fddl* (progn (clsql:create-view [v1] :as [select [a] [c] [d] :from [alpha] :where [= [a] 1]]) (unwind-protect (sort (mapcar #'string-downcase (clsql:list-attributes [v1])) #'string<) (clsql:drop-view [v1] :if-does-not-exist :ignore)))) ("a" "c" "d")) ;; create a view, select stuff from it and drop it (deftest :fddl/view/3 (with-dataset *ds-fddl* (progn (clsql:create-view [v1] :as [select [a] [c] [d] :from [alpha] :where [= [a] 1]]) (unwind-protect (let ((result (list ;; Shouldn't exist (clsql:select [a] [c] :from [v1] :where [= [a] -1]) ;; Should exist (car (clsql:select [a] [c] :from [v1] :where [= [a] 1]))))) (apply #'values result)) (clsql:drop-view [v1] :if-does-not-exist :ignore)))) nil (1 "asdf")) (deftest :fddl/view/4 (with-dataset *ds-fddl* (progn (clsql:create-view [v1] :column-list '([x] [y] [z]) :as [select [a] [c] [d] :from [alpha] :where [= [a] 1]]) (unwind-protect (let ((result (list (sort (mapcar #'string-downcase (clsql:list-attributes [v1])) #'string<) ;; Shouldn't exist (clsql:select [x] [y] :from [v1] :where [= [x] -1]) ;; Should exist (car (clsql:select [x] [y] :from [v1] :where [= [x] 1]))))) (apply #'values result)) (clsql:drop-view [v1] :if-does-not-exist :ignore)))) ("x" "y" "z") nil (1 "asdf")) ;; create an index, test for existence, drop it and test again (deftest :fddl/index/1 (with-dataset *ds-fddl* (progn (clsql:create-index [bar] :on [alpha] :attributes '([a] [c]) :unique t) (values (clsql:index-exists-p [bar] ) (progn (clsql:drop-index [bar] :on [alpha] :if-does-not-exist :ignore) (clsql:index-exists-p [bar]))))) t nil) ;; create indexes with names as strings, symbols and in square brackets (deftest :fddl/index/2 (with-dataset *ds-fddl* (let ((names '("foo" foo [foo])) (result '())) (dolist (name names) (clsql:create-index name :on [alpha] :attributes '([a])) (push (clsql:index-exists-p name ) result) (clsql:drop-index name :on [alpha] :if-does-not-exist :ignore)) (apply #'values result))) t t t) ;; test list-indexes with keyword :ON (deftest :fddl/index/3 (progn (clsql:create-table [i3test] '(([a] (string 10)) ([b] integer))) (clsql:create-index [foo] :on [i3test] :attributes '([b]) :unique nil) (clsql:create-index [bar] :on [i3test] :attributes '([a]) :unique t) (values (clsql:table-exists-p [i3test]) (clsql:index-exists-p [foo]) (clsql:index-exists-p [bar]) (sort (mapcar #'string-downcase (clsql:list-indexes :on [i3test])) #'string-lessp) (progn (clsql:drop-index [bar] :on [i3test]) (clsql:drop-index [foo] :on [i3test]) (clsql:drop-table [i3test]) t))) t t t ("bar" "foo") t) ;; create an sequence, test for existence, drop it and test again (deftest :fddl/sequence/1 (progn (clsql:create-sequence [foo]) (values (clsql:sequence-exists-p [foo]) (progn (clsql:drop-sequence [foo] :if-does-not-exist :ignore) (clsql:sequence-exists-p [foo])))) t nil) ;; create and increment a sequence (deftest :fddl/sequence/2 (let ((val1 nil)) (clsql:create-sequence [foo]) (setf val1 (clsql:sequence-next [foo])) (prog1 (< val1 (clsql:sequence-next [foo])) (clsql:drop-sequence [foo] :if-does-not-exist :ignore))) t) ;; explicitly set the value of a sequence (deftest :fddl/sequence/3 (progn (clsql:create-sequence [foo]) (clsql:set-sequence-position [foo] 5) (prog1 (clsql:sequence-next [foo]) (clsql:drop-sequence [foo] :if-does-not-exist :ignore))) 6) (deftest :fddl/owner/1 (with-dataset *ds-fddl* (and ;; user tables are an improper subset of all tables (= (length (intersection (clsql:list-tables :owner nil) (clsql:list-tables :owner :all) :test #'string=)) (length (clsql:list-tables :owner nil))) ;; user tables are a proper subset of all tables (> (length (clsql:list-tables :owner :all)) (length (clsql:list-tables :owner nil))))) t) (deftest :fddl/owner/table (with-dataset *ds-fddl* (values (clsql-sys:table-exists-p [alpha]) (clsql-sys:table-exists-p [alpha] :owner *test-database-user*) (clsql-sys:table-exists-p [alpha] :owner *test-false-database-user*))) t t nil) (deftest :fddl/owner/attributes (with-dataset *ds-fddl* (values (length (clsql-sys:list-attributes [alpha])) (length (clsql-sys:list-attributes [alpha] :owner *test-database-user*)) (length (clsql-sys:list-attributes [alpha] :owner *test-false-database-user*)))) 4 4 0) (deftest :fddl/owner/attribute-types (with-dataset *ds-fddl* (values (length (clsql:list-attribute-types [alpha])) (length (clsql:list-attribute-types [alpha] :owner *test-database-user*)) (length (clsql:list-attribute-types [alpha] :owner *test-false-database-user*)))) 4 4 0) (deftest :fddl/owner/index (with-dataset *ds-fddl* (progn (clsql:create-index [bar] :on [alpha] :attributes '([a] [c])) (values (clsql:index-exists-p [bar] ) (clsql:index-exists-p [bar] :owner *test-database-user*) (clsql:index-exists-p [bar] :owner *test-false-database-user*) (length (clsql-sys:list-indexes :on [alpha])) (length (clsql-sys:list-indexes :on [alpha] :owner *test-database-user*)) (length (clsql-sys:list-indexes :on [alpha] :owner *test-false-database-user*)) (progn (clsql:drop-index [bar] :on [alpha] :if-does-not-exist :ignore) (clsql:index-exists-p [bar] :owner *test-database-user*)) (clsql:index-exists-p [bar] )))) t t nil 1 1 0 nil nil) (deftest :fddl/owner/sequence (progn (clsql:create-sequence [foo]) (values (clsql:sequence-exists-p [foo]) (clsql:sequence-exists-p [foo] :owner *test-database-user*) (clsql:sequence-exists-p [foo] :owner *test-false-database-user*) (progn (clsql:drop-sequence [foo] :if-does-not-exist :ignore) (clsql:sequence-exists-p [foo] )))) t t nil nil) (deftest :fddl/cache-table-queries/1 (with-dataset *ds-fddl* (list (gethash "ALPHA" (clsql-sys::attribute-cache clsql:*default-database*)) (progn (clsql:cache-table-queries "ALPHA" :action t) (gethash "ALPHA" (clsql-sys::attribute-cache clsql:*default-database*))) (progn (clsql:list-attribute-types "ALPHA") (not (null (cadr (gethash "ALPHA" (clsql-sys::attribute-cache clsql:*default-database*)))))) (progn (clsql:cache-table-queries "ALPHA" :action :flush) (gethash "ALPHA" (clsql-sys::attribute-cache clsql:*default-database*))))) (nil (t nil) t (t nil))) )) cl-sql-6.4.1/tests/utils.lisp0000644000175000017500000000750411616055736015142 0ustar kevinkevin;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; FILE IDENTIFICATION ;;;; ;;;; Name: utils.lisp ;;;; Purpose: Classes and utilities for testing ;;;; Author: Kevin M. Rosenberg ;;;; Created: Mar 2002 ;;;; ;;;; This file, part of CLSQL, is Copyright (c) 2002-2010 by Kevin M. Rosenberg ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* (in-package #:clsql-tests) (defun %get-int (v) (etypecase v (string (parse-integer v :junk-allowed t)) (integer v) (number (truncate v)))) (defvar *config-pathname* (make-pathname :defaults (user-homedir-pathname) :name ".clsql-test" :type "config")) (defvar +all-db-types+ '(:postgresql :postgresql-socket :postgresql-socket3 :mysql :sqlite :sqlite3 :odbc :oracle #+allegro :aodbc)) (defclass conn-specs () ((aodbc :accessor aodbc-spec :initform nil) (mysql :accessor mysql-spec :initform nil) (postgresql :accessor postgresql-spec :initform nil) (postgresql-socket :accessor postgresql-socket-spec :initform nil) (postgresql-socket3 :accessor postgresql-socket3-spec :initform nil) (sqlite :accessor sqlite-spec :initform nil) (sqlite3 :accessor sqlite3-spec :initform nil) (odbc :accessor odbc-spec :initform nil) (oracle :accessor oracle-spec :initform nil)) (:documentation "Connection specs for CLSQL testing")) (defun read-specs (&optional (path *config-pathname*)) (if (probe-file path) (with-open-file (stream path :direction :input) (let ((specs (make-instance 'conn-specs))) (dolist (spec (read stream) specs) (push (second spec) (slot-value specs (intern (symbol-name (first spec)) (find-package '#:clsql-tests))))))) (progn (warn "CLSQL test config file ~S not found" path) nil))) (defun spec-fn (db-type) (intern (concatenate 'string (symbol-name db-type) (symbol-name '#:-spec)) (find-package '#:clsql-tests))) (defun db-type-spec (db-type specs) (funcall (spec-fn db-type) specs)) (defun summarize-test-report (sexp &optional (output *standard-output*)) (flet ((db-title (db-type underlying-db-type) (format nil "~A~A" db-type (if (eq db-type underlying-db-type) "" (format nil "/~A" underlying-db-type))))) (with-open-file (in sexp :direction :input) (let ((eof (cons nil nil))) (do ((form (read in nil eof) (read in nil eof))) ((eq form eof)) (destructuring-bind (db-type underlying-db-type utime total-tests failed-tests impl-type impl-version machine-type) form (declare (ignorable utime impl-version)) (if failed-tests (format output "~&~A: ~D of ~D tests failed (~A, ~A).~&" (db-title db-type underlying-db-type) (length failed-tests) total-tests machine-type impl-type) (format output "~&~A: All ~D tests passed (~A, ~A).~%" (db-title db-type underlying-db-type) total-tests machine-type impl-type)))))))) cl-sql-6.4.1/tests/package.lisp0000644000175000017500000000206311616055736015370 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; FILE IDENTIFICATION ;;;; ;;;; Name: package.lisp ;;;; Purpose: Package definition for CLSQL test suite ;;;; Authors: Marcus Pearce and Kevin M. Rosenberg ;;;; Created: March 2004 ;;;; ;;;; This file is part of CLSQL. ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* (in-package #:cl-user) (defpackage #:clsql-tests (:use #:clsql #:common-lisp #:rtest) (:shadowing-import-from #:clsql-sys #:%get-int ) (:export #:run-tests #:run-tests-append-report-file #:run-benchmarks #:run-benchmarks-append-report-file #:summarize-test-report #:test-initialise-database #:test-connect-to-database ) (:documentation "Regression tests for CLSQL.")) cl-sql-6.4.1/TODO0000644000175000017500000000177411345753563012444 0ustar kevinkevinTESTS TO ADD * Test that ":db-kind :key" adds an index for that key. This is complicated by different backends showing autogenerated primary key in different ways. * :db-constraint tests * Number and Char field types * symbol slot * generalized-boolean slot * tests for db-reader and db-writer OPTIMIZATIONS * Revisit result-type list creation, perhaps caching * Rework LIST-ATTRIBUTE-TYPES and LIST-INDEXES such that they exhibit their current behaviours using single database queries. * Possible use of cached attribute type information for operations which insert/update records as mentioned in the CommonSQL user guide. * Extend caching of generated SQL strings to more complex expressions which are likely to be repeatedly executed many times. POSSIBLE EXTENSIONS * improve large object api and extend to databases beyond postgresql * add support for prepared statements RACE CONDITIONS * sql/databases.lisp: *connected-databases* is shared globally but not modified in a threadsafe manner. cl-sql-6.4.1/COPYING.CLSQL0000644000175000017500000000146711251607553013654 0ustar kevinkevinCLSQL is written and Copyright (c) 2002-2009 by Kevin M. Rosenberg and is based on the MaiSQL package written and Copyright (c) 1999-2001 by Pierre R. Mai. In addition, CLSQL contains code from the UncommonSQL project Copyright (C) 1999-2003 by onShore Development, Inc and code from SQL/ODBC Copyright (C) 1999-2001 by Paul Meurer. CLSQL is licensed under the terms of the Lisp Lesser GNU Public License (http://opensource.franz.com/preamble.html), known as the LLGPL. The LLGPL consists of a preamble (see above URL) and the LGPL. Where these conflict, the preamble takes precedence. CLSQL is referenced in the preamble as the "LIBRARY." CLSQL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. cl-sql-6.4.1/notes/0000755000175000017500000000000010667176647013103 5ustar kevinkevincl-sql-6.4.1/notes/add-type-hints.txt0000644000175000017500000000170510667176647016501 0ustar kevinkevinHow to Add a Type to CL-SQL (Alan Shields - Alan-Shields@omrf.ouhsc.edu) I made this small guide to eliminate some of the work I went through. I hope it is useful and/or correct. To add a type to CL-SQL, the following methods need to be declared. "sql/expressions.lisp" (defmethod database-output-sql (self database)) SELF is specialized for the lisp type, such as (self integer). "sql/oodml.lisp" (defmethod database-get-type-specifier (type args database db-type)) TYPE is a symbol for the clsql type, such as (type (eql 'integer)). Note that DB-TYPE is the database type, not DATABASE. "sql/oodml.lisp" (defmethod read-sql-value (val type database db-type)) TYPE is a symbol for the clsql type, as above. Same warnings as above. If your type is stored in different ways in different sql servers, you'll need to specialize these methods. These specializations usually go in either db-/-objects.lisp or sql/generic-.lisp. cl-sql-6.4.1/doc/0000755000175000017500000000000012134026703012472 5ustar kevinkevincl-sql-6.4.1/doc/clsql.xml0000644000175000017500000000351410667176647014363 0ustar kevinkevin %myents; %xinclude; ]> cl-sql-6.4.1/doc/schemas.xml0000644000175000017500000000232510667176647014667 0ustar kevinkevin cl-sql-6.4.1/doc/ref-connect.xml0000644000175000017500000023775711616055736015460 0ustar kevinkevin %myents; ]> Connection and Initialisation This section describes the &clsql; interface for initialising database interfaces of different types, creating and destroying databases and connecting and disconnecting from databases. DATABASE DATABASE The super-type of all &clsql; databases Class Class Precedence List database standard-object t Description This class is the superclass of all &clsql; databases. The different database back-ends derive subclasses of this class to implement their databases. No instances of this class are ever created by &clsql;. *CONNECT-IF-EXISTS* *CONNECT-IF-EXISTS* Default value for the if-exists parameter of connect. Variable Value Type A valid argument to the if-exists parameter of connect, that is, one of :new :warn-new :error :warn-old :old . Initial Value :error Description The value of this variable is used in calls to connect as the default value of the if-exists parameter. See connect for the semantics of the valid values for this variable. Examples None. Affected By None. See Also connect Notes None. *DB-POOL-MAX-FREE-CONNECTIONS* *DB-POOL-MAX-FREE-CONNECTIONS* How many free connections should the connection pool try to keep. Parameter Value Type Integer Initial Value 4 Description Threshold of free-connections in the pool before we disconnect a database rather than returning it to the pool. NIL for no limit. This is really a heuristic that should, on avg keep the free connections about this size. This is not a hard limit, the number of connections in the pool may exceed this value. Examples (setf clsql-sys:*db-pool-max-free-connections* 2) Affected By None See Also connect disconnect Notes *DEFAULT-DATABASE* *DEFAULT-DATABASE* The default database object to use. Variable Value Type Any object of type database, or &nil; to indicate no default database. Initial Value &nil; Description Any function or macro in &clsql; that operates on a database uses the value of this variable as the default value for it's database parameter. The value of this parameter is changed by calls to connect, which sets *default-database* to the database object it returns. It is also changed by calls to disconnect, when the database object being disconnected is the same as the value of *default-database*. In this case disconnect sets *default-database* to the first database that remains in the list of active databases as returned by connected-databases, or &nil; if no further active databases exist. The user may change *default-database* at any time to a valid value of his choice. If the value of *default-database* is &nil;, then all calls to &clsql; functions on databases must provide a suitable database parameter, or an error will be signalled. Examples (connected-databases) => NIL (connect '("dent" "newesim" "dent" "dent") :database-type :mysql) => #<CLSQL-MYSQL:MYSQL-DATABASE {48385F55}> (connect '(nil "template1" "dent" nil) :database-type :postgresql) => #<CLSQL-POSTGRESQL:POSTGRESQL-DATABASE {483868FD}> (connect '("dent" "newesim" "dent" "dent") :database-type :mysql :if-exists :new) => #<CLSQL-MYSQL:MYSQL-DATABASE {48387265}> *default-database* => #<CLSQL-MYSQL:MYSQL-DATABASE {48387265}> (disconnect) => T *default-database* => #<CLSQL-POSTGRESQL:POSTGRESQL-DATABASE {483868FD}> (disconnect) => T *default-database* => #<CLSQL-MYSQL:MYSQL-DATABASE {48385F55}> (disconnect) => T *default-database* => NIL (connected-databases) => NIL Affected By connect disconnect See Also connected-databases Notes This variable is intended to facilitate working with &clsql; in an interactive fashion at the top-level loop, and because of this, connect and disconnect provide some fairly complex behaviour to keep *default-database* set to useful values. Programmatic use of &clsql; should never depend on the value of *default-database* and should provide correct database objects via the database parameter to functions called. *DEFAULT-DATABASE-TYPE* *DEFAULT-DATABASE-TYPE* The default database type to use Variable Value Type Any keyword representing a valid database back-end of &clsql;, or &nil;. Initial Value &nil; Description The value of this variable is used in calls to initialize-database-type and connect as the default value of the database-type parameter. If the value of this variable is &nil;, then all calls to initialize-database-type or connect will have to specify the database-type to use, or a general-purpose error will be signalled. Examples (setf *default-database-type* :mysql) => :mysql (initialize-database-type) => t Affected By None. See Also intitialize-database-type Notes None. *INITIALIZED-DATABASE-TYPES* *INITIALIZED-DATABASE-TYPES* List of all initialized database types Variable Value Type A list of all initialized database types, each of which represented by it's corresponding keyword. Initial Value &nil; Description This variable is updated whenever initialize-database-type is called for a database type which hasn't already been initialized before, as determined by this variable. In that case the keyword representing the database type is pushed onto the list stored in *INITIALIZED-DATABASE-TYPES*. Attempts to modify the value of this variable will result in undefined behaviour. Examples (setf *default-database-type* :mysql) => :mysql (initialize-database-type) => t *initialized-database-types* => (:MYSQL) Affected By initialize-database-type See Also intitialize-database-type Notes Direct access to this variable is primarily provided because of compatibility with Harlequin's Common SQL. CONNECT CONNECT create a connection to a database. Function Syntax connect connection-spec &key if-exists database-type pool make-default => database Arguments and Values connection-spec A SQL backend specific connection specification supplied as a list or as a string. For the MySQL backend, this list includes an optional associative list of connection options. The options list is parsed and supplied to the MySQL API using mysql_options in between the calls to mysql_init and mysql_real_connect. if-exists This indicates the action to take if a connection to the same database exists already. See below for the legal values and actions. It defaults to the value of *connect-if-exists*. database-type A database type specifier, i.e. a keyword. This defaults to the value of *default-database-type* pool A boolean flag. If &t;, acquire connection from a pool of open connections. If the pool is empty, a new connection is created. The default is &nil;. make-default A boolean flag. If &t;, *default-database* is set to the new connection, otherwise *default-database* is not changed. The default is &t;. database The database object representing the connection. Description This function takes a connection specification and a database type and creates a connection to the database specified by those. The type and structure of the connection specification depend on the database type. The parameter if-exists specifies what to do if a connection to the database specified exists already, which is checked by calling find-database on the database name returned by database-name-from-spec when called with the connection-spec and database-type parameters. The possible values of if-exists are: :new Go ahead and create a new connection. :warn-new This is just like :new, but also signals a warning of type clsql-exists-warning, indicating the old and newly created databases. :error This will cause connect to signal a correctable error of type clsql-exists-error. The user may choose to proceed, either by indicating that a new connection shall be created, via the restart create-new, or by indicating that the existing connection shall be used, via the restart use-old. :old This will cause connect to use an old connection if one exists. :warn-old This is just like :old, but also signals a warning of type clsql-exists-warning, indicating the old database used, via the slots old-db and new-db The database name of the returned database object will be the same under string= as that which would be returned by a call to database-name-from-spec with the given connection-spec and database-type parameters. Examples (database-name-from-spec '("dent" "newesim" "dent" "dent") :mysql) => "dent/newesim/dent" (connect '("dent" "newesim" "dent" "dent") :database-type :mysql) => #<CLSQL-MYSQL:MYSQL-DATABASE {48036F6D}> (database-name *) => "dent/newesim/dent" (connect '("dent" "newesim" "dent" "dent") :database-type :mysql) >> In call to CONNECT: >> There is an existing connection #<CLSQL-MYSQL:MYSQL-DATABASE {48036F6D}> to database dent/newesim/dent. >> >> Restarts: >> 0: [CREATE-NEW] Create a new connection. >> 1: [USE-OLD ] Use the existing connection. >> 2: [ABORT ] Return to Top-Level. >> >> Debug (type H for help) >> >> (CONNECT ("dent" "newesim" "dent" "dent") :IF-EXISTS NIL :DATABASE-TYPE ...) >> Source: >> ; File: /prj/CLSQL/sql/sql.cl >> (RESTART-CASE (ERROR 'CLSQL-EXISTS-ERROR :OLD-DB OLD-DB) >> (CREATE-NEW NIL :REPORT "Create a new connection." >> (SETQ RESULT #)) >> (USE-OLD NIL :REPORT "Use the existing connection." >> (SETQ RESULT OLD-DB))) >> 0] 0 => #<CLSQL-MYSQL:MYSQL-DATABASE {480451F5}> Side Effects A database connection is established, and the resultant database object is registered, so as to appear in the list returned by connected-databases. *default-database* may be rebound to the created object. Affected by *default-database-type* *connect-if-exists* Exceptional Situations If the connection specification is not syntactically or semantically correct for the given database type, an error of type sql-user-error is signalled. If during the connection attempt an error is detected (e.g. because of permission problems, network trouble or any other cause), an error of type sql-database-error is signalled. If a connection to the database specified by connection-spec exists already, conditions are signalled according to the if-exists parameter, as described above. See Also connected-databases disconnect reconnect *connect-if-exists* find-database status Notes The pool and make-default keyword arguments to connect are &clsql; extensions. CONNECTED-DATABASES CONNECTED-DATABASES Return the list of active database objects. Function Syntax connected-databases => databases Arguments and Values databases The list of active database objects. Description This function returns the list of active database objects, i.e. all those database objects created by calls to connect, which have not been closed by calling disconnect on them. The consequences of modifying the list returned by connected-databases are undefined. Examples (connected-databases) => NIL (connect '(nil "template1" "dent" nil) :database-type :postgresql) => #<CLSQL-POSTGRESQL:POSTGRESQL-DATABASE {4830BC65}> (connect '("dent" "newesim" "dent" "dent") :database-type :mysql) => #<CLSQL-MYSQL:MYSQL-DATABASE {4830C5AD}> (connected-databases) => (#<CLSQL-MYSQL:MYSQL-DATABASE {4830C5AD}> #<CLSQL-POSTGRESQL:POSTGRESQL-DATABASE {4830BC65}>) (disconnect) => T (connected-databases) => (#<CLSQL-POSTGRESQL:POSTGRESQL-DATABASE {4830BC65}>) (disconnect) => T (connected-databases) => NIL Side Effects None. Affected By connect disconnect Exceptional Situations None. See Also disconnect connect status find-database Notes None. DATABASE-NAME DATABASE-NAME Get the name of a database object Generic Function Syntax database-name database => name Arguments and Values database A database object, either of type database or of type closed-database. name A string describing the identity of the database to which this database object is connected to. Description This function returns the database name of the given database. The database name is a string which somehow describes the identity of the database to which this database object is or has been connected. The database name of a database object is determined at connect time, when a call to database-name-from-spec derives the database name from the connection specification passed to connect in the connection-spec parameter. The database name is used via find-database in connect to determine whether database connections to the specified database exist already. Usually the database name string will include indications of the host, database name, user, or port that where used during the connection attempt. The only important thing is that this string shall try to identify the database at the other end of the connection. Connection specifications parts like passwords and credentials shall not be used as part of the database name. Examples (database-name-from-spec '("dent" "newesim" "dent" "dent") :mysql) => "dent/newesim/dent" (connect '("dent" "newesim" "dent" "dent") :database-type :mysql) => #<CLSQL-MYSQL:MYSQL-DATABASE {48391DCD}> (database-name *default-database*) => "dent/newesim/dent" (database-name-from-spec '(nil "template1" "dent" nil) :postgresql) => "/template1/dent" (connect '(nil "template1" "dent" nil) :database-type :postgresql) => #<CLSQL-POSTGRESQL:POSTGRESQL-DATABASE {48392D2D}> (database-name *default-database*) => "/template1/dent" (database-name-from-spec '("www.pmsf.de" "template1" "dent" nil) :postgresql) => "www.pmsf.de/template1/dent" Side Effects None. Affected By database-name-from-spec Exceptional Situations Will signal an error if the object passed as the database parameter is neither of type database nor of type closed-database. See Also connect find-database connected-databases disconnect status Notes None. DATABASE-NAME-FROM-SPEC DATABASE-NAME-FROM-SPEC Return the database name string corresponding to the given connection specification. Generic Function Syntax database-name-from-spec connection-spec database-type => name Arguments and Values connection-spec A connection specification, whose structure and interpretation are dependent on the database-type. database-type A database type specifier, i.e. a keyword. name A string denoting a database name. Description This generic function takes a connection specification and a database type and returns the database name of the database object that would be created had connect been called with the given connection specification and database types. This function is useful in determining a database name from the connection specification, since the way the connection specification is converted into a database name is dependent on the database type. Examples (database-name-from-spec '("dent" "newesim" "dent" "dent") :mysql) => "dent/newesim/dent" (connect '("dent" "newesim" "dent" "dent") :database-type :mysql) => #<CLSQL-MYSQL:MYSQL-DATABASE {48391DCD}> (database-name *default-database*) => "dent/newesim/dent" (database-name-from-spec '(nil "template1" "dent" nil) :postgresql) => "/template1/dent" (connect '(nil "template1" "dent" nil) :database-type :postgresql) => #<CLSQL-POSTGRESQL:POSTGRESQL-DATABASE {48392D2D}> (database-name *default-database*) => "/template1/dent" (database-name-from-spec '("www.pmsf.de" "template1" "dent" nil) :postgresql) => "www.pmsf.de/template1/dent" (find-database "dent/newesim/dent") => #<CLSQL-MYSQL:MYSQL-DATABASE {484E91C5}> (find-database "/template1/dent") => #<CLSQL-POSTGRESQL:POSTGRESQL-DATABASE {48392D2D}> (find-database "www.pmsf.de/template1/dent" nil) => NIL (find-database **) => #<CLSQL-POSTGRESQL:POSTGRESQL-DATABASE {48392D2D}> Side Effects None. Affected by None. Exceptional Situations If the value of connection-spec is not a valid connection specification for the given database type, an error of type clsql-invalid-spec-error might be signalled. See Also connect Notes database-name-from-spec is a &clsql; extension. DATABASE-TYPE DATABASE-TYPE Get the type of a database object. Generic Function Syntax database-type DATABASE => type Arguments and Values database A database object, either of type database or of type closed-database. type A keyword symbol denoting a known database back-end. Description Returns the type of database. Examples (connect '(nil "template1" "dent" nil) :database-type :postgresql) => #<CLSQL-POSTGRESQL:POSTGRESQL-DATABASE {48392D2D}> (database-type *default-database*) => :postgresql Side Effects None. Affected by None. Exceptional Situations Will signal an error if the object passed as the database parameter is neither of type database nor of type closed-database. See Also connect find-database connected-databases disconnect status Notes database-type is a &clsql; extension. DISCONNECT DISCONNECT close a database connection Function Syntax disconnect &key database error => result Arguments and Values error A boolean flag indicating whether to signal an error if database is non-&nil; but cannot be found. database The database to disconnect, which defaults to the database indicated by *default-database*. result A Boolean indicating whether a connection was successfully disconnected. Description This function takes a database object as returned by connect, and closes the connection. If no matching database is found and error and database are both non-&nil; an error is signaled, otherwise &nil; is returned. If the database is from a pool it will be released to this pool. The status of the object passed is changed to closed after the disconnection succeeds, thereby preventing further use of the object as an argument to &clsql; functions, with the exception of database-name and database-type. If the user does pass a closed database to any other &clsql; function, an error of type sql-fatal-error is signalled. Examples (disconnect :database (find-database "dent/newesim/dent")) => T Side Effects The database object is removed from the list of connected databases as returned by connected-databases. If the database object passed is the same under eq as the value of *default-database*, then *default-database* is set to the first remaining database from connected-databases or to &nil; if no further active database exists. Non-pooled The database connection is closed and the state of the database object is changed to closed. Pooled Unless there are already *db-pool-max-free-connections* free connections in the pool it is returned to the pool, with the backend having an opportunity to run generic cleanup on the connection first. If the max free connections has already been reached then it is disconnected as if it were not in the pool. Affected by *default-database* *db-pool-max-free-connections* Exceptional Situations If during the disconnection attempt an error is detected (e.g. because of network trouble or any other cause), an error of type sql-error might be signalled. See Also connect disconnect-pooled Notes None. DISCONNECT-POOLED DISCONNECT-POOLED closes all pooled database connections Function Syntax disconnect-pooled &optional clear => t Description This function disconnects all database connections that have been placed into the pool by calling connect with :pool &t;. If optional argument clear is non-&nil; then the connection-pool objects are also removed. Examples (disconnect-pool) => T Side Effects Database connections will be closed and *all* entries in the pool are removed. This is done with great prejudice and no thought to thread safety or whether that connection is currently in use. Affected by disconnect Exceptional Situations If during the disconnection attempt an error is detected (e.g. because of network trouble or any other cause), an error of type clsql-error might be signalled. See Also connect disconnect Notes disconnect-pooled is a &clsql; extension. FIND-DATABASE FIND-DATABASE >Locate a database object through it's name. Function Syntax find-database database &optional errorp => result Arguments and Values database A database object or a string, denoting a database name. errorp A generalized boolean. Defaults to t. db-type A keyword symbol denoting a known database back-end. result Either a database object, or, if errorp is &nil;, possibly &nil;. Description find-database locates an active database object given the specification in database. If database is an object of type database, find-database returns this. Otherwise it will search the active databases as indicated by the list returned by connected-databases for a database of type db-type whose name (as returned by database-name is equal as per string= to the string passed as database. If it succeeds, it returns the first database found. If db-type is &nil; all databases matching the string database are considered. If no matching databases are found and errorp is &nil; then &nil; is returned. If errorp is &nil; and one or more matching databases are found, then the most recently connected database is returned as a first value and the number of matching databases is returned as a second value. If no, or more than one, matching databases are found and errorp is true, an error is signalled. Examples (database-name-from-spec '("dent" "newesim" "dent" "dent") :mysql) => "dent/newesim/dent" (connect '("dent" "newesim" "dent" "dent") :database-type :mysql) => #<CLSQL-MYSQL:MYSQL-DATABASE {48391DCD}> (database-name *default-database*) => "dent/newesim/dent" (database-name-from-spec '(nil "template1" "dent" nil) :postgresql) => "/template1/dent" (connect '(nil "template1" "dent" nil) :database-type :postgresql) => #<CLSQL-POSTGRESQL:POSTGRESQL-DATABASE {48392D2D}> (database-name *default-database*) => "/template1/dent" (database-name-from-spec '("www.pmsf.de" "template1" "dent" nil) :postgresql) => "www.pmsf.de/template1/dent" (find-database "dent/newesim/dent") => #<CLSQL-MYSQL:MYSQL-DATABASE {484E91C5}> (find-database "/template1/dent") => #<CLSQL-POSTGRESQL:POSTGRESQL-DATABASE {48392D2D}> (find-database "www.pmsf.de/template1/dent" nil) => NIL (find-database **) => #<CLSQL-POSTGRESQL:POSTGRESQL-DATABASE {48392D2D}> Side Effects None. Affected By connected-databases Exceptional Situations Will signal an error of type clsql-error if no matching database can be found, and errorp is true. Will signal an error if the value of database is neither an object of type database nor a string. See Also database-name database-name-from-spec disconnect connect status connected-databases Notes The db-type keyword argument to find-database is a &clsql; extension. INITIALIZE-DATABASE-TYPE INITIALIZE-DATABASE-TYPE Initializes a database type Function Syntax initialize-database-type &key database-type => result Arguments and Values database-type The database type to initialize, i.e. a keyword symbol denoting a known database back-end. Defaults to the value of *default-database-type*. result Either &nil; if the initialization attempt fails, or t otherwise. Description If the back-end specified by database-type has not already been initialized, as seen from *initialized-database-types*, an attempt is made to initialize the database. If this attempt succeeds, or the back-end has already been initialized, the function returns t, and places the keyword denoting the database type onto the list stored in *initialized-database-types*, if not already present. If initialization fails, the function returns &nil;, and/or signals an error of type clsql-error. The kind of action taken depends on the back-end and the cause of the problem. Examples *initialized-database-types* => NIL (setf *default-database-type* :mysql) => :MYSQL (initialize-database-type) >> Compiling LAMBDA (#:G897 #:G898 #:G901 #:G902): >> Compiling Top-Level Form: >> => T *initialized-database-types* => (:MYSQL) (initialize-database-type) => T *initialized-database-types* => (:MYSQL) Side Effects The database back-end corresponding to the database type specified is initialized, unless it has already been initialized. This can involve any number of other side effects, as determined by the back-end implementation (like e.g. loading of foreign code, calling of foreign code, networking operations, etc.). If initialization is attempted and succeeds, the database-type is pushed onto the list stored in *initialized-database-types*. Affected by *default-database-type* *initialized-database-types* Exceptional Situations If an error is encountered during the initialization attempt, the back-end may signal errors of kind clsql-error. See Also *initialized-database-types* *default-database-type* Notes None. RECONNECT RECONNECT Re-establishes the connection between a database object and its RDBMS. Function Syntax reconnect &key database error force => result Arguments and Values database The database to reconnect, which defaults to the database indicated by *default-database*. error A boolean flag indicating whether to signal an error if database is non-nil but cannot be found. The default value is &nil;. force A Boolean indicating whether to signal an error if the database connection has been lost. The default value is &t;. result A Boolean indicating whether the database was successfully reconnected. Description Reconnects database which defaults to *default-database* to the underlying database management system. On success, &t; is returned and the variable *default-database* is set to the newly reconnected database. If database is a database instance, this object is closed. If database is a string, then a connected database whose name matches database is sought in the list of connected databases. If no matching database is found and error and database are both non-&nil; an error is signaled, otherwise &nil; is returned. When the current database connection has been lost, if force is non-&nil; as it is by default, the connection is closed and errors are suppressed. If force is &nil; and the database connection cannot be closed, an error is signalled. Examples *default-database* => #<CLSQL-SQLITE:SQLITE-DATABASE :memory: OPEN {48CFBEA5}> (reconnect) => #<CLSQL-SQLITE:SQLITE-DATABASE :memory: OPEN {48D64105}> Side Effects A database connection is re-established and *default-database* may be rebound to the supplied database object. Affected by *default-database* Exceptional Situations An error may be signalled if the specified database cannot be located or if the database cannot be closed. See Also connect disconnect disconnect-pooled Notes None. STATUS STATUS Print information about connected databases. Function Syntax status &optional full => Arguments and Values full A boolean indicating whether to print additional table information. The default value is &nil;. Description Prints information about the currently connected databases to *STANDARD-OUTPUT*. The argument full is &nil; by default and a value of t means that more detailed information about each database is printed. Examples (status) CLSQL STATUS: 2004-06-13 15:07:39 -------------------------------------------------------- DATABASE TYPE RECORDING -------------------------------------------------------- localhost/test/petrov mysql nil localhost/test/petrov postgresql nil localhost/test/petrov postgresql-socket nil test/petrov odbc nil * :memory: sqlite nil -------------------------------------------------------- (status t) CLSQL STATUS: 2004-06-13 15:08:08 ------------------------------------------------------------------------------- DATABASE TYPE RECORDING POOLED TABLES VIEWS ------------------------------------------------------------------------------- localhost/test/petrov mysql nil nil 7 0 localhost/test/petrov postgresql nil nil 7 0 localhost/test/petrov postgresql-socket nil nil 7 0 test/petrov odbc nil nil 7 0 * :memory: sqlite nil nil 0 0 ------------------------------------------------------------------------------- Side Effects None. Affected by None. Exceptional Situations None. See Also connected-databases connect disconnect *connect-if-exists* find-database Notes None. CREATE-DATABASE CREATE-DATABASE create a database Function Syntax create-database connection-spec &key database-type => success Arguments and Values connection-spec A connection specification database-type A database type specifier, i.e. a keyword. This defaults to the value of *default-database-type* success A boolean flag. If &t;, a new database was successfully created. Description This function creates a database in the database system specified by database-type. Examples (create-database '("localhost" "new" "dent" "dent") :database-type :mysql) => T (create-database '("localhost" "new" "dent" "badpasswd") :database-type :mysql) => Error: While trying to access database localhost/new/dent using database-type MYSQL: Error database-create failed: mysqladmin: connect to server at 'localhost' failed error: 'Access denied for user: 'root@localhost' (Using password: YES)' has occurred. [condition type: CLSQL-ACCESS-ERROR] Side Effects A database will be created on the filesystem of the host. Exceptional Situations An exception will be thrown if the database system does not allow new databases to be created or if database creation fails. See Also destroy-database probe-database list-databases Notes This function may invoke the operating systems functions. Thus, some database systems may require the administration functions to be available in the current PATH. At this time, the :mysql backend requires mysqladmin and the :postgresql backend requires createdb. create-database is a &clsql; extension. DESTROY-DATABASE DESTROY-DATABASE destroys a database Function Syntax destroy-database connection-spec &key database-type => success Arguments and Values connection-spec A connection specification database-type A database type specifier, i.e. a keyword. This defaults to the value of *default-database-type* success A boolean flag. If &t;, the database was successfully destroyed. Description This function destroys a database in the database system specified by database-type. Examples (destroy-database '("localhost" "new" "dent" "dent") :database-type :postgresql) => T (destroy-database '("localhost" "new" "dent" "dent") :database-type :postgresql) => Error: While trying to access database localhost/test2/root using database-type POSTGRESQL: Error database-destroy failed: dropdb: database removal failed: ERROR: database "test2" does not exist has occurred. [condition type: CLSQL-ACCESS-ERROR] Side Effects A database will be removed from the filesystem of the host. Exceptional Situations An exception will be thrown if the database system does not allow databases to be removed, the database does not exist, or if database removal fails. See Also create-database probe-database list-databases Notes This function may invoke the operating systems functions. Thus, some database systems may require the administration functions to be available in the current PATH. At this time, the :mysql backend requires mysqladmin and the :postgresql backend requires dropdb. destroy-database is a &clsql; extension. PROBE-DATABASE PROBE-DATABASE tests for existence of a database Function Syntax probe-database connection-spec &key database-type => success Arguments and Values connection-spec A connection specification database-type A database type specifier, i.e. a keyword. This defaults to the value of *default-database-type* success A boolean flag. If &t;, the database exists in the database system. Description This function tests for the existence of a database in the database system specified by database-type. Examples (probe-database '("localhost" "new" "dent" "dent") :database-type :postgresql) => T Side Effects None Exceptional Situations An exception maybe thrown if the database system does not receive administrator-level authentication since function may need to read the administrative database of the database system. See Also create-database destroy-database list-databases Notes probe-database is a &clsql; extension. LIST-DATABASES LIST-DATABASES List databases matching the supplied connection spec and database type. Function Syntax list-databases connection-spec &key database-type => result Arguments and Values connection-spec A connection specification database-type A database type specifier, i.e. a keyword. This defaults to the value of *default-database-type* result A list of matching databases. Description This function returns a list of databases existing in the database system specified by database-type. Examples (list-databases '("localhost" "new" "dent" "dent") :database-type :postgresql) => ("address-book" "sql-test" "template1" "template0" "test1" "dent" "test") Side Effects None. Affected by None. Exceptional Situations An exception maybe thrown if the database system does not receive administrator-level authentication since function may need to read the administrative database of the database system. See Also create-database destroy-database probe-database Notes list-databases is a &clsql; extension. WITH-DATABASE WITH-DATABASE Execute a body of code with a variable bound to a specified database object. Macro Syntax with-database db-var connection-spec &rest connect-args &body body => result Arguments and Values db-var A variable which is bound to the specified database. connection-spec A vendor specific connection specification supplied as a list or as a string. connect-args Other optional arguments to connect. This macro use a value of &nil; for connect's make-default key, This is in contrast to to the connect function which has a default value of &t; for make-default. body A Lisp code body. result Determined by the result of executing the last expression in body. Description Evaluate body in an environment, where db-var is bound to the database connection given by connection-spec and connect-args. The connection is automatically closed or released to the pool on exit from the body. Examples (connected-databases) => NIL (with-database (db '(":memory:") :database-type :sqlite :make-default nil) (database-name db)) => ":memory:" (connected-databases) => NIL Side Effects See connect and disconnect. Affected by See connect and disconnect. Exceptional Situations See connect and disconnect. See Also connect disconnect disconnect-pooled with-default-database Notes with-database is a &clsql; extension. WITH-DEFAULT-DATABASE WITH-DEFAULT-DATABASE Execute a body of code with *default-database* bound to a specified database. Macro Syntax with-default-database database &rest body => result Arguments and Values database An active database object. body A Lisp code body. result Determined by the result of executing the last expression in body. Description Perform body with DATABASE bound as *default-database*. Examples *default-database* => #<CLSQL-ODBC:ODBC-DATABASE new/dent OPEN {49095CAD}> (let ((database (clsql:find-database ":memory:"))) (with-default-database (database) (database-name *default-database*))) => ":memory:" Side Effects None. Affected by None. Exceptional Situations Calls to &clsql; functions in body may signal errors if database is not an active database object. See Also with-database *default-database* Notes with-default-database is a &clsql; extension. cl-sql-6.4.1/doc/preface.xml0000644000175000017500000000113510667176647014647 0ustar kevinkevin %myents; ]> Preface This guide provides reference to the features of &clsql;. The first chapter provides an introduction to &clsql; and installation instructions. The reference sections document all user accessible symbols with examples of usage. There is a glossary of commonly used terms with their definitions. cl-sql-6.4.1/doc/ref-recording.xml0000644000175000017500000007021310667176647015773 0ustar kevinkevin %myents; ]> SQL I/O Recording &clsql; provides a facility for recording SQL commands sent to and/or results returned from the underlying RDBMS to user sprecified streams. This is useful for monitoring &clsql; activity and for debugging applications. This section documents the functions provided for enabling and disabling SQL recording as well as for manipulating the streams on to which SQL commands and results are recorded. START-SQL-RECORDING START-SQL-RECORDING Start recording SQL commands or results. Function Syntax start-sql-recording &key type database => Arguments and Values type One of the following keyword symbols: :commands, :results or :both, defaulting to :commands. database A database object. This will default to *default-database*. Description Starts recording of SQL commands sent to and/or results returned from database which defaults to *default-database*. The SQL is output on one or more broadcast streams, initially just *standard-output*, and the functions add-sql-stream and delete-sql-stream may be used to add or delete command or result recording streams. The default value of type is :commands which means that SQL commands sent to database are recorded. If type is :results then SQL results returned from database are recorded. Both commands and results may be recorded by passing type value of :both. Examples (start-sql-recording :type :both) => (select [last-name] :from [employee] :where [= [emplid] 1] :field-names nil :flatp t) ;; 2004-07-02 16:42:12 dent/test/dent => SELECT last_name FROM employee WHERE (emplid = 1) ;; 2004-07-02 16:42:12 dent/test/dent <= (Lenin) => ("Lenin") Side Effects The command and result recording broadcast streams associated with database are reinitialised with only *standard-output* as their component streams. Affected by None. Exceptional Situations None. See Also stop-sql-recording sql-recording-p sql-stream add-sql-stream delete-sql-stream list-sql-streams Notes None. STOP-SQL-RECORDING STOP-SQL-RECORDING Stop recording SQL commands or results. Function Syntax stop-sql-recording &key type database => Arguments and Values type One of the following keyword symbols: :commands, :results or :both, defaulting to :commands. database A database object. This will default to *default-database*. Description Stops recording of SQL commands sent to and/or results returned from database which defaults to *default-database*. The default value of type is :commands which means that SQL commands sent to database will no longer be recorded. If type is :results then SQL results returned from database will no longer be recorded. Recording may be stopped for both commands and results by passing type value of :both. Examples (start-sql-recording :type :both) => (select [last-name] :from [employee] :where [= [emplid] 1] :field-names nil :flatp t) ;; 2004-07-02 16:42:12 dent/test/dent => SELECT last_name FROM employee WHERE (emplid = 1) ;; 2004-07-02 16:42:12 dent/test/dent <= (Lenin) => ("Lenin") (stop-sql-recording :type :results) => (select [last-name] :from [employee] :where [= [emplid] 1] :field-names nil :flatp t) ;; 2004-07-02 16:44:11 dent/test/dent => SELECT last_name FROM employee WHERE (emplid = 1) => ("Lenin") Side Effects The command and result recording broadcast streams associated with database are reinitialised to &nil;. Affected by None. Exceptional Situations None. See Also start-sql-recording sql-recording-p Notes None. SQL-RECORDING-P SQL-RECORDING-P Tests whether SQL commands or results are being recorded. Function Syntax sql-recording-p &key type database => result Arguments and Values type One of the following keyword symbols: :commands, :results, :both or :either defaulting to :commands. database A database object. This will default to *default-database*. result A Boolean. Description Predicate to test whether the SQL recording specified by type is currently enabled for database which defaults to *default-database*. type may be one of :commands, :results, :both or :either, defaulting to :commands, otherwise &nil; is returned. Examples (start-sql-recording :type :commands) => (sql-recording-p :type :commands) => T (sql-recording-p :type :both) => NIL (sql-recording-p :type :either) => T Side Effects None. Affected by start-sql-recording stop-sql-recording Exceptional Situations None. See Also start-sql-recording stop-sql-recording Notes The :both and :either values for the type keyword argument are &clsql; extensions. SQL-STREAM SQL-STREAM Returns the broadcast stream used for recording SQL commands or results. Function Syntax sql-stream &key type database => result Arguments and Values type One of the following keyword symbols: :commands or :results, defaulting to :commands. database A database object. This will default to *default-database*. result A broadcast stream or &nil;. Description Returns the broadcast stream used for recording SQL commands sent to or results returned from database which defaults to *default-database*. type must be one of :commands or :results, defaulting to :commands, and determines whether the stream returned is that used for recording SQL commands or results. Examples (start-sql-recording :type :commands) => (sql-stream :type :commands) => #<Broadcast Stream> (sql-stream :type :results) => NIL Side Effects None. Affected by None. Exceptional Situations An error is signalled if type is not one of :commands or :results. See Also start-sql-recording add-sql-stream delete-sql-stream list-sql-streams Notes None. ADD-SQL-STREAM ADD-SQL-STREAM Add a component to the broadcast streams used for recording SQL commands or results. Function Syntax add-sql-stream stream &key type database => result Arguments and Values stream A stream or &t;. type One of the following keyword symbols: :commands, :results or :both, defaulting to :commands. database A database object. This will default to *default-database*. result The added stream. Description Adds the supplied stream stream (or &t; for *standard-output*) as a component of the recording broadcast stream for the SQL recording type specified by type on database which defaults to *default-database*. type must be one of :commands, :results, or :both, defaulting to :commands, depending on whether the stream is to be added for recording SQL commands, results or both. Examples (start-sql-recording :type :commands) => (with-output-to-string (s) (add-sql-stream s :type :commands) (print-query [select [emplid] [first-name] [last-name] [email] :from [employee]] :stream s)) ;; 2004-07-02 17:38:45 dent/test/dent => SELECT emplid,first_name,last_name,email FROM employee => ";; 2004-07-02 17:38:45 dent/test/dent => SELECT emplid,first_name,last_name,email FROM employee 1 Vladimir Lenin lenin@soviet.org 2 Josef Stalin stalin@soviet.org 3 Leon Trotsky trotsky@soviet.org 4 Nikita Kruschev kruschev@soviet.org 5 Leonid Brezhnev brezhnev@soviet.org 6 Yuri Andropov andropov@soviet.org 7 Konstantin Chernenko chernenko@soviet.org 8 Mikhail Gorbachev gorbachev@soviet.org 9 Boris Yeltsin yeltsin@soviet.org 10 Vladimir Putin putin@soviet.org " Side Effects The specified broadcast stream(s) associated with database are modified. Affected by None. Exceptional Situations None. See Also start-sql-recording sql-stream delete-sql-stream list-sql-streams Notes None. DELETE-SQL-STREAM DELETE-SQL-STREAM Remove a component from the broadcast streams used for recording SQL commands or results. Function Syntax delete-sql-stream stream &KEY type database => result Arguments and Values stream A stream or &t;. stream A stream or &t;. type One of the following keyword symbols: :commands, :results or :both, defaulting to :commands. database A database object. This will default to *default-database*. result The added stream. Description Removes the supplied stream stream from the recording broadcast stream for the SQL recording type specified by type on database which defaults to *default-database*. type must be one of :commands, :results, or :both, defaulting to :commands, depending on whether the stream is to be added for recording SQL commands, results or both. Examples (list-sql-streams :type :both) => (#<Stream for descriptor 7> #<Stream for descriptor 7>) (delete-sql-stream *standard-output* :type :results) => #<Stream for descriptor 7> (list-sql-streams :type :both) => (#<Stream for descriptor 7>) Side Effects The specified broadcast stream(s) associated with database are modified. Affected by None. Exceptional Situations None. See Also start-sql-recording stop-sql-recording sql-recording-p sql-stream add-sql-stream delete-sql-stream list-sql-streams Notes None. LIST-SQL-STREAMS LIST-SQL-STREAMS List the components of the broadcast streams used for recording SQL commands or results. Function Syntax list-sql-streams &key type database => result Arguments and Values type One of the following keyword symbols: :commands, :results or :both, defaulting to :commands. database A database object. This will default to *default-database*. result A list. Description Returns the list of component streams for the broadcast stream recording SQL commands sent to and/or results returned from database which defaults to *default-database*. type must be one of :commands, :results, or :both, defaulting to :commands, and determines whether the listed streams contain those recording SQL commands, results or both. Examples (list-sql-streams :type :both) => NIL (start-sql-recording :type :both) => (list-sql-streams :type :both) => (#<Stream for descriptor 7> #<Stream for descriptor 7>) Side Effects None. Affected by add-sql-stream delete-sql-stream Exceptional Situations An error is signalled if type is passed a value other than :commands, :results or :both. See Also sql-stream add-sql-stream delete-sql-stream Notes None. cl-sql-6.4.1/doc/catalog-mandrake.xml0000644000175000017500000000262610667176647016442 0ustar kevinkevin cl-sql-6.4.1/doc/ref-clsql.xml0000644000175000017500000024046111251607553015122 0ustar kevinkevin %myents; ]> <symbol>CLSQL</symbol> This part gives a reference to the symbols exported from the CLSQL package. These symbols constitute the normal user-interface of &clsql;. Currently, the symbols of the &commonsql;-API are not documented here. SQL-CONDITION the super-type of all &clsql;-specific conditions Condition Type Class Precedence List sql-condition condition t Description This is the super-type of all &clsql;-specific conditions defined by &clsql;, or any of it's database-specific interfaces. There are no defined initialization arguments nor any accessors. SQL-ERROR the super-type of all &clsql;-specific errors Condition Type Class Precedence List sql-error error serious-condition sql-condition condition t Description This is the super-type of all &clsql;-specific conditions that represent errors, as defined by &clsql;, or any of it's database-specific interfaces. There are no defined initialization arguments nor any accessors. SQL-WARNING the super-type of all &clsql;-specific warnings Condition Type Class Precedence List sql-warning warning sql-condition condition t Description This is the super-type of all &clsql;-specific conditions that represent warnings, as defined by &clsql;, or any of it's database-specific interfaces. There are no defined initialization arguments nor any accessors. CLSQL-USER-ERROR condition representing errors because of invalid parameters from the library user. Condition Type Class Precedence List sql-error sql-condition condition t Description This condition represents errors that occur because the user supplies invalid data to &clsql;. This includes errors such as an invalid format connection specification or an error in the syntax for the LOOP macro extensions. SQL-CONNECTION-ERROR condition representing errors during connection Condition Type Class Precedence List sql-connection-error sql-database-error sql-error sql-condition condition t Description This condition represents errors that occur while trying to connect to a database. The following initialization arguments and accessors exist: Initarg Accessor Description :database-type sql-connection-error-database-type Database type for the connection attempt :connection-spec sql-connection-error-connection-spec The connection specification used in the connection attempt. :errno sql-connection-error-errno The numeric or symbolic error specification returned by the database back-end. The values and semantics of this are interface specific. :error sql-connection-error-error A string describing the problem that occurred, possibly one returned by the database back-end. SQL-DATABASE-ERROR condition representing errors during query or command execution Condition Type Class Precedence List sql-database-error sql-error error serious-condition sql-condition condition t Description This condition represents errors that occur while executing SQL statements, either as part of query operations or command execution, either explicitly or implicitly, as caused e.g. by with-transaction. The following initialization arguments and accessors exist: Initarg Accessor Description :database sql-database-error-database The database object that was involved in the incident. :expression sql-database-error-expression The SQL expression whose execution caused the error. :errno sql-database-error-errno The numeric or symbolic error specification returned by the database back-end. The values and semantics of this are interface specific. :error sql-database-error-error A string describing the problem that occurred, possibly one returned by the database back-end. *DEFAULT-DATABASE-TYPE* The default database type to use Variable Value Type Any keyword representing a valid database back-end of &clsql;, or nil. Initial Value nil Description The value of this variable is used in calls to initialize-database-type and connect as the default value of the database-type parameter. If the value of this variable is nil, then all calls to initialize-database-type or connect will have to specify the database-type to use, or a general-purpose error will be signalled. Examples (setf *default-database-type* :mysql) => :mysql (initialize-database-type) => t Affected By None. See Also None. Notes None. *INITIALIZED-DATABASE-TYPES* List of all initialized database types Variable Value Type A list of all initialized database types, each of which represented by it's corresponding keyword. Initial Value nil Description This variable is updated whenever initialize-database-type is called for a database type which hasn't already been initialized before, as determined by this variable. In that case the keyword representing the database type is pushed onto the list stored in *INITIALIZED-DATABASE-TYPES*. Attempts to modify the value of this variable will result in undefined behaviour. Examples (setf *default-database-type* :mysql) => :mysql (initialize-database-type) => t *initialized-database-types* => (:MYSQL) Affected By initialize-database-type See Also None. Notes Direct access to this variable is primarily provided because of compatibility with Harlequin's Common SQL. INITIALIZE-DATABASE-TYPE Initializes a database type Function Syntax initialize-database-type &key database-type => result Arguments and Values database-type The database type to initialize, i.e. a keyword symbol denoting a known database back-end. Defaults to the value of *default-database-type*. result Either nil if the initialization attempt fails, or t otherwise. Description If the back-end specified by database-type has not already been initialized, as seen from *initialized-database-types*, an attempt is made to initialize the database. If this attempt succeeds, or the back-end has already been initialized, the function returns t, and places the keyword denoting the database type onto the list stored in *initialized-database-types*, if not already present. If initialization fails, the function returns nil, and/or signals an error of type clsql-error. The kind of action taken depends on the back-end and the cause of the problem. Examples *initialized-database-types* => NIL (setf *default-database-type* :mysql) => :MYSQL (initialize-database-type) >> Compiling LAMBDA (#:G897 #:G898 #:G901 #:G902): >> Compiling Top-Level Form: >> => T *initialized-database-types* => (:MYSQL) (initialize-database-type) => T *initialized-database-types* => (:MYSQL) Side Effects The database back-end corresponding to the database type specified is initialized, unless it has already been initialized. This can involve any number of other side effects, as determined by the back-end implementation (like e.g. loading of foreign code, calling of foreign code, networking operations, etc.). If initialization is attempted and succeeds, the database-type is pushed onto the list stored in *initialized-database-types*. Affected by *default-database-type* *initialized-database-types* Exceptional Situations If an error is encountered during the initialization attempt, the back-end may signal errors of kind clsql-error. See Also None. Notes None. *CONNECT-IF-EXISTS* Default value for the if-exists parameter of connect. Variable Value Type A valid argument to the if-exists parameter of connect, i.e. one of :new :warn-new :error :warn-old :old . Initial Value :error Description The value of this variable is used in calls to connect as the default value of the if-exists parameter. See connect for the semantics of the valid values for this variable. Examples None. Affected By None. See Also connect Notes None. CONNECTED-DATABASES Return the list of active database objects. Function Syntax connected-databases => databases Arguments and Values databases The list of active database objects. Description This function returns the list of active database objects, i.e. all those database objects created by calls to connect, which have not been closed by calling disconnect on them. The consequences of modifying the list returned by connected-databases are undefined. Examples (connected-databases) => NIL (connect '(nil "template1" "dent" nil) :database-type :postgresql) => #<CLSQL-POSTGRESQL:POSTGRESQL-DATABASE {4830BC65}> (connect '("dent" "newesim" "dent" "dent") :database-type :mysql) => #<CLSQL-MYSQL:MYSQL-DATABASE {4830C5AD}> (connected-databases) => (#<CLSQL-MYSQL:MYSQL-DATABASE {4830C5AD}> #<CLSQL-POSTGRESQL:POSTGRESQL-DATABASE {4830BC65}>) (disconnect) => T (connected-databases) => (#<CLSQL-POSTGRESQL:POSTGRESQL-DATABASE {4830BC65}>) (disconnect) => T (connected-databases) => NIL Side Effects None. Affected By connect disconnect Exceptional Situations None. See Also None. Notes None. *DEFAULT-DATABASE* The default database object to use Variable Value Type Any object of type database, or nil to indicate no default database. Initial Value nil Description Any function or macro in &clsql; that operates on a database uses the value of this variable as the default value for it's database parameter. The value of this parameter is changed by calls to connect, which sets *default-database* to the database object it returns. It is also changed by calls to disconnect, when the database object being disconnected is the same as the value of *default-database*. In this case disconnect sets *default-database* to the first database that remains in the list of active databases as returned by connected-databases, or nil if no further active databases exist. The user may change *default-database* at any time to a valid value of his choice. If the value of *default-database* is nil, then all calls to &clsql; functions on databases must provide a suitable database parameter, or an error will be signalled. Examples (connected-databases) => NIL (connect '("dent" "newesim" "dent" "dent") :database-type :mysql) => #<CLSQL-MYSQL:MYSQL-DATABASE {48385F55}> (connect '(nil "template1" "dent" nil) :database-type :postgresql) => #<CLSQL-POSTGRESQL:POSTGRESQL-DATABASE {483868FD}> (connect '("dent" "newesim" "dent" "dent") :database-type :mysql :if-exists :new) => #<CLSQL-MYSQL:MYSQL-DATABASE {48387265}> *default-database* => #<CLSQL-MYSQL:MYSQL-DATABASE {48387265}> (disconnect) => T *default-database* => #<CLSQL-POSTGRESQL:POSTGRESQL-DATABASE {483868FD}> (disconnect) => T *default-database* => #<CLSQL-MYSQL:MYSQL-DATABASE {48385F55}> (disconnect) => T *default-database* => NIL (connected-databases) => NIL Affected By connect disconnect See Also connected-databases Notes This variable is intended to facilitate working with &clsql; in an interactive fashion at the top-level loop, and because of this, connect and disconnect provide some fairly complex behaviour to keep *default-database* set to useful values. Programmatic use of &clsql; should never depend on the value of *default-database* and should provide correct database objects via the database parameter to functions called. DATABASE The super-type of all &clsql; databases Class Class Precedence List database standard-object t Description This class is the superclass of all &clsql; databases. The different database back-ends derive subclasses of this class to implement their databases. No instances of this class are ever created by &clsql;. CLOSED-DATABASE The class representing all closed &clsql; databases Class Class Precedence List closed-database standard-object t Description &clsql; database instances are changed to this class via change-class after they are closed via disconnect. All functions and generic functions that take database objects as arguments will signal errors of type clsql-closed-error when they are called on instances of closed-database, with the exception of database-name, which will continue to work as for instances of database. DATABASE-NAME Get the name of a database object Generic Function Syntax database-name database => name Arguments and Values database A database object, either of type database or of type closed-database. name A string describing the identity of the database to which this database object is connected to. Description This function returns the database name of the given database. The database name is a string which somehow describes the identity of the database to which this database object is or has been connected. The database name of a database object is determined at connect time, when a call to database-name-from-spec derives the database name from the connection specification passed to connect in the connection-spec parameter. The database name is used via find-database in connect to determine whether database connections to the specified database exist already. Usually the database name string will include indications of the host, database name, user, or port that where used during the connection attempt. The only important thing is that this string shall try to identify the database at the other end of the connection. Connection specifications parts like passwords and credentials shall not be used as part of the database name. Examples (database-name-from-spec '("dent" "newesim" "dent" "dent") :mysql) => "dent/newesim/dent" (connect '("dent" "newesim" "dent" "dent") :database-type :mysql) => #<CLSQL-MYSQL:MYSQL-DATABASE {48391DCD}> (database-name *default-database*) => "dent/newesim/dent" (database-name-from-spec '(nil "template1" "dent" nil) :postgresql) => "/template1/dent" (connect '(nil "template1" "dent" nil) :database-type :postgresql) => #<CLSQL-POSTGRESQL:POSTGRESQL-DATABASE {48392D2D}> (database-name *default-database*) => "/template1/dent" (database-name-from-spec '("www.pmsf.de" "template1" "dent" nil) :postgresql) => "www.pmsf.de/template1/dent" Side Effects None. Affected By database-name-from-spec Exceptional Situations Will signal an error if the object passed as the database parameter is neither of type database nor of type closed-database. See Also connect find-database Notes None. FIND-DATABASE Locate a database object through it's name. Function Syntax find-database database &optional errorp => result Arguments and Values database A database object or a string, denoting a database name. errorp A generalized boolean. Defaults to t. result Either a database object, or, if errorp is nil, possibly nil. Description find-database locates an active database object given the specification in database. If database is an object of type database, find-database returns this. Otherwise it will search the active databases as indicated by the list returned by connected-databases for a database whose name (as returned by database-name is equal as per string= to the string passed as database. If it succeeds, it returns the first database found. If it fails to find a matching database, it will signal an error of type clsql-error if errorp is true. If errorp is nil, it will return nil instead. Examples (database-name-from-spec '("dent" "newesim" "dent" "dent") :mysql) => "dent/newesim/dent" (connect '("dent" "newesim" "dent" "dent") :database-type :mysql) => #<CLSQL-MYSQL:MYSQL-DATABASE {48391DCD}> (database-name *default-database*) => "dent/newesim/dent" (database-name-from-spec '(nil "template1" "dent" nil) :postgresql) => "/template1/dent" (connect '(nil "template1" "dent" nil) :database-type :postgresql) => #<CLSQL-POSTGRESQL:POSTGRESQL-DATABASE {48392D2D}> (database-name *default-database*) => "/template1/dent" (database-name-from-spec '("www.pmsf.de" "template1" "dent" nil) :postgresql) => "www.pmsf.de/template1/dent" (find-database "dent/newesim/dent") => #<CLSQL-MYSQL:MYSQL-DATABASE {484E91C5}> (find-database "/template1/dent") => #<CLSQL-POSTGRESQL:POSTGRESQL-DATABASE {48392D2D}> (find-database "www.pmsf.de/template1/dent" nil) => NIL (find-database **) => #<CLSQL-POSTGRESQL:POSTGRESQL-DATABASE {48392D2D}> Side Effects None. Affected By connected-databases Exceptional Situations Will signal an error of type clsql-error if no matching database can be found, and errorp is true. Will signal an error if the value of database is neither an object of type database nor a string. See Also database-name database-name-from-spec Notes None. CONNECT create a connection to a database Function Syntax connect connection-spec &key if-exists database-type pool => database Arguments and Values connection-spec A connection specification if-exists This indicates the action to take if a connection to the same database exists already. See below for the legal values and actions. It defaults to the value of *connect-if-exists*. database-type A database type specifier, i.e. a keyword. This defaults to the value of *default-database-type* pool A boolean flag. If &t;, acquire connection from a pool of open connections. If the pool is empty, a new connection is created. The default is &nil;. database The database object representing the connection. Description This function takes a connection specification and a database type and creates a connection to the database specified by those. The type and structure of the connection specification depend on the database type. The parameter if-exists specifies what to do if a connection to the database specified exists already, which is checked by calling find-database on the database name returned by database-name-from-spec when called with the connection-spec and database-type parameters. The possible values of if-exists are: :new Go ahead and create a new connection. :warn-new This is just like :new, but also signals a warning of type clsql-exists-warning, indicating the old and newly created databases. :error This will cause connect to signal a correctable error of type clsql-exists-error. The user may choose to proceed, either by indicating that a new connection shall be created, via the restart create-new, or by indicating that the existing connection shall be used, via the restart use-old. :old This will cause connect to use an old connection if one exists. :warn-old This is just like :old, but also signals a warning of type clsql-exists-warning, indicating the old database used, via the slots old-db and new-db The database name of the returned database object will be the same under string= as that which would be returned by a call to database-name-from-spec with the given connection-spec and database-type parameters. Examples (database-name-from-spec '("dent" "newesim" "dent" "dent") :mysql) => "dent/newesim/dent" (connect '("dent" "newesim" "dent" "dent") :database-type :mysql) => #<CLSQL-MYSQL:MYSQL-DATABASE {48036F6D}> (database-name *) => "dent/newesim/dent" (connect '("dent" "newesim" "dent" "dent") :database-type :mysql) >> In call to CONNECT: >> There is an existing connection #<CLSQL-MYSQL:MYSQL-DATABASE {48036F6D}> to database dent/newesim/dent. >> >> Restarts: >> 0: [CREATE-NEW] Create a new connection. >> 1: [USE-OLD ] Use the existing connection. >> 2: [ABORT ] Return to Top-Level. >> >> Debug (type H for help) >> >> (CONNECT ("dent" "newesim" "dent" "dent") :IF-EXISTS NIL :DATABASE-TYPE ...) >> Source: >> ; File: /prj/CLSQL/sql/sql.cl >> (RESTART-CASE (ERROR 'CLSQL-EXISTS-ERROR :OLD-DB OLD-DB) >> (CREATE-NEW NIL :REPORT "Create a new connection." >> (SETQ RESULT #)) >> (USE-OLD NIL :REPORT "Use the existing connection." >> (SETQ RESULT OLD-DB))) >> 0] 0 => #<CLSQL-MYSQL:MYSQL-DATABASE {480451F5}> Side Effects A database connection is established, and the resultant database object is registered, so as to appear in the list returned by connected-databases. Affected by *default-database-type* *connect-if-exists* Exceptional Situations If the connection specification is not syntactically or semantically correct for the given database type, an error of type clsql-invalid-spec-error is signalled. If during the connection attempt an error is detected (e.g. because of permission problems, network trouble or any other cause), an error of type sql-connection-error is signalled. If a connection to the database specified by connection-spec exists already, conditions are signalled according to the if-exists parameter, as described above. See Also connected-databases disconnect Notes None. DISCONNECT close a database connection Function Syntax disconnect &key database pool => t Arguments and Values pool A boolean flag indicating whether to put the database into a pool of opened databases. If &t;, rather than terminating the database connection, the connection is left open and the connection is placed into a pool of connections. Subsequent calls to connect can then reuse this connection. The default is &nil;. database The database to disconnect, which defaults to the database indicated by *default-database*. Description This function takes a database object as returned by connect, and closes the connection. The class of the object passed is changed to closed-database after the disconnection succeeds, thereby preventing further use of the object as an argument to &clsql; functions, with the exception of database-name. If the user does pass a closed database object to any other &clsql; function, an error of type clsql-closed-error is signalled. Examples (disconnect :database (find-database "dent/newesim/dent")) => T Side Effects The database connection is closed, and the database object is removed from the list of connected databases as returned by connected-databases. The class of the database object is changed to closed-database. If the database object passed is the same under eq as the value of *default-database*, then *default-database* is set to the first remaining database from connected-databases or to nil if no further active database exists. Affected by *default-database* Exceptional Situations If during the disconnection attempt an error is detected (e.g. because of network trouble or any other cause), an error of type clsql-error might be signalled. See Also connect closed-database Notes None. DISCONNECT-POOLED closes all pooled database connections Function Syntax disconnect-pool => t Description This function disconnects all database connections that have been placed into the pool. Connections are placed in the pool by calling disconnection. Examples (disconnect-pool) => T Side Effects Database connections will be closed and entries in the pool are removed. Affected by disconnect Exceptional Situations If during the disconnection attempt an error is detected (e.g. because of network trouble or any other cause), an error of type clsql-error might be signalled. See Also connect closed-database Notes None. CREATE-DATABASE create a database Function Syntax create-database connection-spec &key database-type => success Arguments and Values connection-spec A connection specification database-type A database type specifier, i.e. a keyword. This defaults to the value of *default-database-type* success A boolean flag. If &t;, a new database was successfully created. Description This function creates a database in the database system specified by database-type. Examples (create-database '("localhost" "new" "dent" "dent") :database-type :mysql) => T (create-database '("localhost" "new" "dent" "badpasswd") :database-type :mysql) => Error: While trying to access database localhost/new/dent using database-type MYSQL: Error database-create failed: mysqladmin: connect to server at 'localhost' failed error: 'Access denied for user: 'root@localhost' (Using password: YES)' has occurred. [condition type: CLSQL-ACCESS-ERROR] Side Effects A database will be created on the filesystem of the host. Exceptional Situations An exception will be thrown if the database system does not allow new databases to be created or if database creation fails. Notes This function may invoke the operating systems functions. Thus, some database systems may require the administration functions to be available in the current PATH. At this time, the :mysql backend requires mysqladmin and the :postgresql backend requires createdb. DESTROY-DATABASE destroys a database Function Syntax destroy-database connection-spec &key database-type => success Arguments and Values connection-spec A connection specification database-type A database type specifier, i.e. a keyword. This defaults to the value of *default-database-type* success A boolean flag. If &t;, the database was successfully destroyed. Description This function destroy a database in the database system specified by database-type. Examples (destroy-database '("localhost" "new" "dent" "dent") :database-type :postgresql) => T (destroy-database '("localhost" "new" "dent" "dent") :database-type :postgresql) => Error: While trying to access database localhost/test2/root using database-type POSTGRESQL: Error database-destroy failed: dropdb: database removal failed: ERROR: database "test2" does not exist has occurred. [condition type: CLSQL-ACCESS-ERROR] Side Effects A database will be removed from the filesystem of the host. Exceptional Situations An exception will be thrown if the database system does not allow databases to be removed, the database does not exist, or if database removal fails. Notes This function may invoke the operating systems functions. Thus, some database systems may require the administration functions to be available in the current PATH. At this time, the :mysql backend requires mysqladmin and the :postgresql backend requires dropdb. PROBE-DATABASE tests for existence of a database Function Syntax probe-database connection-spec &key database-type => success Arguments and Values connection-spec A connection specification database-type A database type specifier, i.e. a keyword. This defaults to the value of *default-database-type* success A boolean flag. If &t;, the database exists in the database system. Description This function tests for the existence of a database in the database system specified by database-type. Examples (probe-database '("localhost" "new" "dent" "dent") :database-type :postgresql) => T Side Effects None Exceptional Situations An exception maybe thrown if the database system does not receive administrator-level authentication since function may need to read the administrative database of the database system. Notes None. DATABASE-NAME-FROM-SPEC Return the database name string corresponding to the given connection specification. Generic Function Syntax database-name-from-spec connection-spec database-type => name Arguments and Values connection-spec A connection specification, whose structure and interpretation are dependent on the database-type. database-type A database type specifier, i.e. a keyword. name A string denoting a database name. Description This generic function takes a connection specification and a database type and returns the database name of the database object that would be created had connect been called with the given connection specification and database types. This function is useful in determining a database name from the connection specification, since the way the connection specification is converted into a database name is dependent on the database type. Examples (database-name-from-spec '("dent" "newesim" "dent" "dent") :mysql) => "dent/newesim/dent" (connect '("dent" "newesim" "dent" "dent") :database-type :mysql) => #<CLSQL-MYSQL:MYSQL-DATABASE {48391DCD}> (database-name *default-database*) => "dent/newesim/dent" (database-name-from-spec '(nil "template1" "dent" nil) :postgresql) => "/template1/dent" (connect '(nil "template1" "dent" nil) :database-type :postgresql) => #<CLSQL-POSTGRESQL:POSTGRESQL-DATABASE {48392D2D}> (database-name *default-database*) => "/template1/dent" (database-name-from-spec '("www.pmsf.de" "template1" "dent" nil) :postgresql) => "www.pmsf.de/template1/dent" (find-database "dent/newesim/dent") => #<CLSQL-MYSQL:MYSQL-DATABASE {484E91C5}> (find-database "/template1/dent") => #<CLSQL-POSTGRESQL:POSTGRESQL-DATABASE {48392D2D}> (find-database "www.pmsf.de/template1/dent" nil) => NIL (find-database **) => #<CLSQL-POSTGRESQL:POSTGRESQL-DATABASE {48392D2D}> Side Effects None. Affected by None. Exceptional Situations If the value of connection-spec is not a valid connection specification for the given database type, an error of type clsql-invalid-spec-error might be signalled. See Also connect Notes None. EXECUTE-COMMAND Execute an SQL command which returns no values. Function Syntax execute-command sql-expression &key database => t Arguments and Values sql-expression An sql expression that represents an SQL statement which will return no values. database A database object. This will default to the value of *default-database*. Description This will execute the command given by sql-expression in the database specified. If the execution succeeds it will return t, otherwise an error of type sql-database-error will be signalled. Examples (execute-command "create table eventlog (time char(30),event char(70))") => T (execute-command "create table eventlog (time char(30),event char(70))") >> >> While accessing database #<CLSQL-POSTGRESQL:POSTGRESQL-DATABASE {480B2B6D}> >> with expression "create table eventlog (time char(30),event char(70))": >> Error NIL: ERROR: amcreate: eventlog relation already exists >> has occurred. >> >> Restarts: >> 0: [ABORT] Return to Top-Level. >> >> Debug (type H for help) >> >> (CLSQL-POSTGRESQL::|(PCL::FAST-METHOD DATABASE-EXECUTE-COMMAND (T POSTGRESQL-DATABASE))| >> #<unused-arg> >> #<unused-arg> >> #<unavailable-arg> >> #<unavailable-arg>) >> Source: (ERROR 'SQL-DATABASE-ERROR :DATABASE DATABASE :EXPRESSION ...) >> 0] 0 (execute-command "drop table eventlog") => T Side Effects Whatever effects the execution of the SQL statement has on the underlying database, if any. Affected by None. Exceptional Situations If the execution of the SQL statement leads to any errors, an error of type sql-database-error is signalled. See Also query Notes None. QUERY Execute an SQL query and return the tuples as a list Function Syntax query query-expression &key database result-types field-names => result Arguments and Values query-expression An sql expression that represents an SQL query which is expected to return a (possibly empty) result set. database A database object. This will default to the value of *default-database*. result-types A field type specifier. The default is &nil;. The purpose of this argument is cause &clsql; to import SQL numeric fields into numeric Lisp objects rather than strings. This reduces the cost of allocating a temporary string and the &clsql; users' inconvenience of converting number strings into number objects. A value of :auto causes &clsql; to automatically convert SQL fields into a numeric format where applicable. The default value of &nil; causes all fields to be returned as strings regardless of the SQL type. Otherwise a list is expected which has a element for each field that specifies the conversion. If the list is shorter than the number of fields, the a value of t is assumed for the field. If the list is longer than the number of fields, the extra elements are ignored. :int Field is imported as a signed integer, from 8-bits to 64-bits depending upon the field type. :double Field is imported as a double-float number. t Field is imported as a string. field-names A boolean with a default value of &t;. When &t;, this function results a second value of a list of field names. When &nil;, this function only returns one value - the list of rows. result A list representing the result set obtained. For each tuple in the result set, there is an element in this list, which is itself a list of all the attribute values in the tuple. Description This will execute the query given by query-expression in the database specified. If the execution succeeds it will return the result set returned by the database, otherwise an error of type sql-database-error will be signalled. Examples (execute-command "create table simple (name char(50), salary numeric(10,2))") => T (execute-command "insert into simple values ('Mai, Pierre',10000)") => T (execute-command "insert into simple values ('Hacker, Random J.',8000.50)") => T (query "select * from simple") => (("Mai, Pierre" "10000.00") ("Hacker, Random J." "8000.50")) (query "select salary from simple") => (("10000.00") ("8000.50")) (query "select salary from simple where salary > 10000") => NIL (query "select salary,name from simple where salary > 10000") => NIL (query "select salary,name from simple where salary > 9000") => (("10000.00" "Mai, Pierre")) (query "select salary,name from simple where salary > 8000") => (("10000.00" "Mai, Pierre") ("8000.50" "Hacker, Random J.")) ;; MySQL-specific: (query "show tables") => (("demo") ("log") ("newlog") ("simple") ("spacetrial")) Side Effects Whatever effects the execution of the SQL query has on the underlying database, if any. Affected by None. Exceptional Situations If the execution of the SQL query leads to any errors, an error of type sql-database-error is signalled. See Also execute-command Notes None. MAP-QUERY Map a function over all the tuples from a query Function Syntax map-query output-type-spec function query-expression &key database result-types => result Arguments and Values output-type-spec A sequence type specifier or nil. function A function designator. function takes a single argument which is the atom value for a query single with a single column or is a list of values for a multi-column query. query-expression An sql expression that represents an SQL query which is expected to return a (possibly empty) result set. database A database object. This will default to the value of *default-database*. result-types A field type specifier. The default is &nil;. See query for the semantics of this argument. result If output-type-spec is a type specifier other than nil, then a sequence of the type it denotes. Otherwise nil is returned. Description Applies function to the successive tuples in the result set returned by executing the SQL query-expression. If the output-type-spec is nil, then the result of each application of function is discarded, and map-query returns nil. Otherwise the result of each successive application of function is collected in a sequence of type output-type-spec, where the jths element is the result of applying function to the attributes of the jths tuple in the result set. The collected sequence is the result of the call to map-query. If the output-type-spec is a subtype of list, the result will be a list. If the result-type is a subtype of vector, then if the implementation can determine the element type specified for the result-type, the element type of the resulting array is the result of upgrading that element type; or, if the implementation can determine that the element type is unspecified (or *), the element type of the resulting array is t; otherwise, an error is signaled. Examples (map-query 'list #'(lambda (tuple) (multiple-value-bind (salary name) tuple (declare (ignorable name)) (read-from-string salary))) "select salary,name from simple where salary > 8000") => (10000.0 8000.5) (map-query '(vector double-float) #'(lambda (tuple) (multiple-value-bind (salary name) tuple (declare (ignorable name)) (let ((*read-default-float-format* 'double-float)) (coerce (read-from-string salary) 'double-float)) "select salary,name from simple where salary > 8000"))) => #(10000.0d0 8000.5d0) (type-of *) => (SIMPLE-ARRAY DOUBLE-FLOAT (2)) (let (list) (values (map-query nil #'(lambda (tuple) (multiple-value-bind (salary name) tuple (push (cons name (read-from-string salary)) list)) "select salary,name from simple where salary > 8000") list)) => NIL => (("Hacker, Random J." . 8000.5) ("Mai, Pierre" . 10000.0)) Side Effects Whatever effects the execution of the SQL query has on the underlying database, if any. Affected by None. Exceptional Situations If the execution of the SQL query leads to any errors, an error of type sql-database-error is signalled. An error of type type-error must be signaled if the output-type-spec is not a recognizable subtype of list, not a recognizable subtype of vector, and not nil. An error of type type-error should be signaled if output-type-spec specifies the number of elements and the size of the result set is different from that number. See Also query do-query Notes None. DO-QUERY Iterate over all the tuples of a query Macro Syntax do-query ((&rest args) query-expression &key database result-types) &body body => nil Arguments and Values args A list of variable names. query-expression An sql expression that represents an SQL query which is expected to return a (possibly empty) result set, where each tuple has as many attributes as function takes arguments. database A database object. This will default to *default-database*. result-types A field type specifier. The default is &nil;. See query for the semantics of this argument. body A body of Lisp code, like in a destructuring-bind form. Description Executes the body of code repeatedly with the variable names in args bound to the attributes of each tuple in the result set returned by executing the SQL query-expression on the database specified. The body of code is executed in a block named nil which may be returned from prematurely via return or return-from. In this case the result of evaluating the do-query form will be the one supplied to return or return-from. Otherwise the result will be nil. The body of code appears also is if wrapped in a destructuring-bind form, thus allowing declarations at the start of the body, especially those pertaining to the bindings of the variables named in args. Examples (do-query ((salary name) "select salary,name from simple") (format t "~30A gets $~2,5$~%" name (read-from-string salary))) >> Mai, Pierre gets $10000.00 >> Hacker, Random J. gets $08000.50 => NIL (do-query ((salary name) "select salary,name from simple") (return (cons salary name))) => ("10000.00" . "Mai, Pierre") Side Effects Whatever effects the execution of the SQL query has on the underlying database, if any. Affected by None. Exceptional Situations If the execution of the SQL query leads to any errors, an error of type sql-database-error is signalled. If the number of variable names in args and the number of attributes in the tuples in the result set don't match up, an error is signalled. See Also query map-query Notes None. LOOP-FOR-AS-TUPLES Iterate over all the tuples of a query via a loop clause Loop Clause Compatibility loop-for-as-tuples only works with &cmucl;. Syntax var [type-spec] being {each | the} {record | records | tuple | tuples} {in | of} query [from database] Arguments and Values var A d-var-spec, as defined in the grammar for loop-clauses in the ANSI Standard for Common Lisp. This allows for the usual loop-style destructuring. type-spec An optional type-spec either simple or destructured, as defined in the grammar for loop-clauses in the ANSI Standard for Common Lisp. query An sql expression that represents an SQL query which is expected to return a (possibly empty) result set, where each tuple has as many attributes as function takes arguments. database An optional database object. This will default to the value of *default-database*. Description This clause is an iteration driver for loop, that binds the given variable (possibly destructured) to the consecutive tuples (which are represented as lists of attribute values) in the result set returned by executing the SQL query expression on the database specified. Examples (defvar *my-db* (connect '("dent" "newesim" "dent" "dent")) "My database" => *MY-DB* (loop with time-graph = (make-hash-table :test #'equal) with event-graph = (make-hash-table :test #'equal) for (time event) being the tuples of "select time,event from log" from *my-db* do (incf (gethash time time-graph 0)) (incf (gethash event event-graph 0)) finally (flet ((show-graph (k v) (format t "~40A => ~5D~%" k v))) (format t "~&Time-Graph:~%===========~%") (maphash #'show-graph time-graph) (format t "~&~%Event-Graph:~%============~%") (maphash #'show-graph event-graph)) (return (values time-graph event-graph))) >> Time-Graph: >> =========== >> D => 53000 >> X => 3 >> test-me => 3000 >> >> Event-Graph: >> ============ >> CLOS Benchmark entry. => 9000 >> Demo Text... => 3 >> doit-text => 3000 >> C Benchmark entry. => 12000 >> CLOS Benchmark entry => 32000 => #<EQUAL hash table, 3 entries {48350A1D}> => #<EQUAL hash table, 5 entries {48350FCD}> Side Effects Whatever effects the execution of the SQL query has on the underlying database, if any. Affected by None. Exceptional Situations If the execution of the SQL query leads to any errors, an error of type sql-database-error is signalled. Otherwise, any of the exceptional situations of loop applies. See Also query map-query do-query Notes None. cl-sql-6.4.1/doc/xinclude.mod0000644000175000017500000000160110667176647015032 0ustar kevinkevin cl-sql-6.4.1/doc/catalog-redhat.xml0000644000175000017500000000265310667176647016127 0ustar kevinkevin cl-sql-6.4.1/doc/clsql.pdf0000644000175000017500000256377212064371661014341 0ustar kevinkevin%PDF-1.4 %ª«¬­ 4 0 obj << /Title (CLSQL Users' Guide) /Author (Kevin M. Rosenberg, Marcus T. Pearce, Pierre R. Mai, and onShore Development, Inc.) /Creator (DocBook XSL Stylesheets with Apache FOP) /Producer (Apache FOP Version 1.0) /CreationDate (D:20121219170445Z) >> endobj 5 0 obj << /N 3 /Length 11 0 R /Filter /FlateDecode >> stream xœ–wTSهϽ7½P’Š”ÐkhRH ½H‘.*1 JÀ"6DTpDQ‘¦2(à€£C‘±"Š…Q±ëDÔqp–Id­ß¼yïÍ›ß÷~kŸ½ÏÝgï}ÖºüƒÂLX € ¡Xáçň‹g` ðlàp³³BøF™|ØŒl™ø½º ùû*Ó?ŒÁÿŸ”¹Y"1P˜ŒçòøÙ\É8=Wœ%·Oɘ¶4MÎ0JÎ"Y‚2V“sò,[|ö™e9ó2„<ËsÎâeðäÜ'ã9¾Œ‘`çø¹2¾&cƒtI†@Æoä±|N6(’Ü.æsSdl-c’(2‚-ãyàHÉ_ðÒ/XÌÏËÅÎÌZ.$§ˆ&\S†“‹áÏÏMç‹ÅÌ07#â1Ø™YárfÏüYym²";Ø8980m-m¾(Ô]ü›’÷v–^„îDøÃöW~™ °¦eµÙú‡mi]ëP»ý‡Í`/в¾u}qº|^RÄâ,g+«ÜÜ\KŸk)/èïúŸC_|ÏR¾Ýïåaxó“8’t1C^7nfz¦DÄÈÎâpù 柇øþuü$¾ˆ/”ED˦L L–µ[Ȉ™B†@øŸšøÃþ¤Ù¹–‰ÚøЖX¥!@~(* {d+Ðï} ÆGù͋љ˜ûÏ‚þ}W¸LþÈ$ŽcGD2¸QÎìšüZ4 E@ê@èÀ¶À¸àA(ˆq`1à‚D €µ ”‚­`'¨u 4ƒ6ptcà48.Ë`ÜR0ž€)ð Ì@„…ÈR‡t CȲ…XäCP”%CBH@ë R¨ª†ê¡fè[è(tº C· Qhúz#0 ¦ÁZ°l³`O8Ž„ÁÉð28.‚·À•p|î„O×àX ?§€:¢‹0ÂFB‘x$ !«¤i@Ú¤¹ŠH‘§È[EE1PL” Ê…⢖¡V¡6£ªQP¨>ÔUÔ(j õMFk¢ÍÑÎèt,:‹.FW ›Ðè³èô8úƒ¡cŒ1ŽL&³³³ÓŽ9…ÆŒa¦±X¬:ÖëŠ År°bl1¶ {{{;Ž}ƒ#âtp¶8_\¡8áú"ãEy‹.,ÖXœ¾øøÅ%œ%Gщ1‰-‰ï9¡œÎôÒ€¥µK§¸lî.îžoo’ïÊ/çO$¹&•'=JvMÞž<™âžR‘òTÀT ž§ú§Ö¥¾N MÛŸö)=&½=—‘˜qTH¦ û2µ3ó2‡³Ì³Š³¤Ëœ—í\6% 5eCÙ‹²»Å4ÙÏÔ€ÄD²^2šã–S“ó&7:÷Hžrž0o`¹ÙòMË'ò}ó¿^ZÁ]Ñ[ [°¶`t¥çÊúUЪ¥«zWë¯.Z=¾Æo͵„µik(´.,/|¹.f]O‘VÑš¢±õ~ë[‹ŠEÅ76¸l¨ÛˆÚ(Ø8¸iMKx%K­K+Jßoæn¾ø•ÍW•_}Ú’´e°Ì¡lÏVÌVáÖëÛÜ·(W.Ï/Û²½scGÉŽ—;—ì¼PaWQ·‹°K²KZ\Ù]ePµµê}uJõHWM{­fí¦Ú×»y»¯ìñØÓV§UWZ÷n¯`ïÍz¿úΣ†Š}˜}9û6F7öÍúº¹I£©´éÃ~á~éˆ}ÍŽÍÍ-š-e­p«¤uò`ÂÁËßxÓÝÆl«o§·—‡$‡›øíõÃA‡{°Ž´}gø]mµ£¤ê\Þ9Õ•Ò%íŽë>x´·Ç¥§ã{Ëï÷Ó=Vs\åx٠‰¢ŸN柜>•uêééäÓc½Kz=s­/¼oðlÐÙóç|Ïé÷ì?yÞõü± ÎŽ^d]ìºäp©sÀ~ ãû:;‡‡º/;]îž7|âŠû•ÓW½¯ž»píÒÈü‘áëQ×oÞH¸!½É»ùèVú­ç·snÏÜYs}·äžÒ½Šûš÷~4ý±]ê =>ê=:ð`Áƒ;cܱ'?eÿô~¼è!ùaÅ„ÎDó#ÛGÇ&}'/?^øxüIÖ“™§Å?+ÿ\ûÌäÙw¿xü20;5þ\ôüÓ¯›_¨¿ØÿÒîeïtØôýW¯f^—¼Qsà-ëmÿ»˜w3¹ï±ï+?˜~èùôñî§ŒOŸ~÷„óû endstream endobj 6 0 obj [/ICCBased 5 0 R] endobj 7 0 obj << /Type /Metadata /Subtype /XML /Length 12 0 R >> stream CLSQL Users' Guide Kevin M. Rosenberg, Marcus T. Pearce, Pierre R. Mai, and onShore Development, Inc. 2012-12-19T17:04:45Z 1.4 Apache FOP Version 1.0 2012-12-19T17:04:45Z DocBook XSL Stylesheets with Apache FOP 2012-12-19T17:04:45Z endstream endobj 10 0 obj << /Length 13 0 R /Filter /FlateDecode >> stream xœu‘ËNÃ@ E÷ù ï ÌŒçé-O­Ô´a…X”2”H$¡ í÷ã(•ª¶ YÌèzν¶¼Ê4(9ý˜`Qe«­¦!ßKù¾( ý©÷¢‚evUd—wÈbŒÄÌP|ì’´&Ô™CÒH1(¥¼‡¢‚—ÓëÑ,½Bñ(æ?öha¶Á[Às—Úîî×å{ÚYiÚ÷ ‘`$µh¥%7ðOiSÖ0F˜6]ªßR»Lv¨üöVâƒfé%¢#ËlxÀÇóv±î @˜$y¦C˜z§™©ŸžÉ)eÔ6{R¦¶M0EÏËCÒy‰ Ì2³lÀô¡ž·`SÏ>!oÒ&}5ßUªÎá¡^à`r[Ȳòì’Õp% endstream endobj 8 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Contents 10 0 R >> endobj 11 0 obj 2596 endobj 12 0 obj 939 endobj 13 0 obj 276 endobj 15 0 obj << /Length 16 0 R /Filter /FlateDecode >> stream xœÅUMSÛ0½ûWì­0“¨úðG|lÓ´ ÃW:9ÇVb¶dC}W±‰í@{ÉA«Õî¾7ïÉÊÅ€âolÏçfÖ]càqnr\`6ádPǤ¦ªðç—ªƒVnQ8¶®nð0Š íŽÛ6_Zç-|sBß¿Í@0þ! Î_ºàqt¼Ùv‹*‡™j9JkÙ굚Z…¹jÝKŠ6œè°(5Ý7޼3xÏ ƒMam}[ŸlCdžùªý)1Nó)¥O2¸:˜Î.Ïg‡70ÿ‰-¢ßbOˆçO|ß÷ü~3ü.¤.>Áñ}Éç!0ÚAåqöQ—UË'ø%’N\¨BæK©×#8 tx_ÀœÀ™ÄPŽà,‘ZK¸ x–Œ È#Pùe¬0÷M>ÈTm2™—#ø‘‡¤!0éàÛ‚ø¶Ý"~͹ó\îvÊ'ýò"uÇ N(õP!›÷;áÆ®‹>$EOÕæI'ë¸lR×ÜaÍŽã„1§(ä.…’íâJ»ÝEÜÅ-5ÿŽ!{„£l®6¡ÁhámmÙíŒ?ÿ+šTmn¥uËGǾ?ÁK¾vûí F˜iñ˜ß5½5¸Wõ%MåZ+˜Î¬ h[Z®“¢”ZFPê ’Y oA­àHùŸaô ~7æ&ñ x·hª²L倗m³¤Ø,”¾E|Ô~[€Òƒ| C¨iš•QŸ£.yÞ+´úe§:Sù¶ Uݰ"Œïÿ Ûི“$ÔªP«I©ÇâmMË0›áuB W8¯Qé•–±Ô°ÔÛwHÃF«è>,!2YûË}îèŽWXš+‹ ËäAB¬ÒŸÓšî÷ùö…ÿ þp® endstream endobj 14 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Contents 15 0 R >> endobj 16 0 obj 656 endobj 18 0 obj << /Length 19 0 R /Filter /FlateDecode >> stream xœÅTMoÛ0 ½ëWðئIò‡ìë†mÀÐÂØ¡èÁµ•D€l§–Ý.ÿ~TäÌr>ì’Å$’"ùÞ£ìWÂáóÁ-2P5äuòq¢tr%)𘊘ö w*؈ã7[øIZÂàyzÆ` Þ ;-wH~$« ¿‹°›÷D\ü«å¤ôd6‡ìÈûÐã ¹™d›V_Õo=8¿^ÅfLì²(ÜÛ5g°!Ÿ òñkœA±ž/­T ÆC4¹û (xº{ÓúþŠïäKq6Ô‹w6O×û­DL³ø;‚S‘I$˜¦žÓ^­ËJy^‰3üSžeX‹g>§Øj ÷圦p·u­{×woè `Õ«¶ ]hlÃÐZ•ÃØ/*tëÀ8¢MOÑ ÄšD2ÏãèîÏ«‡«L…ÄÜ8c,æÉy. ÚK°º·C`WÛr7¨þï‚”m`èvè»z¬ݵ ®òÄ©¤ìŸØ!9Æqî¿ g©®©L©t¸êÙЭJcÊ#®ÙÛ{°–ÎîIo,æí]Vù”ÙSwÕØ¨vº3£õ"N¡ªRÖê–Ü7/ *¾ëaë•Âwšg9Rwoƒ£«~•ÍÎà<ðR¶Ü( ˆ¾W€×º„é¬-û½‹V]Ót­Ùã1UNµ±àšÞWÝC­ÖºÕ^‰à˰"¿uc“j endstream endobj 17 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Contents 18 0 R >> endobj 19 0 obj 535 endobj 21 0 obj << /Length 22 0 R /Filter /FlateDecode >> stream xœÅ]Oã8ð½¿ÂÚ‡;Àg;‰ãܴˉP»Ú“–Õ)mÜ6Ú4)IJ—ã8©ó}Ü ñŒÇó=ã1/Šü^ªë1´ÚM^JE.C/QGÔÆÌA;T®)ªÚ‚U+øh"XlÑ×IËe¦ …áϽPe.È/³ŸÏ{¢jA´„ŠqGÅvé“,ߤ²!ûæ[ôêB«ðªX`– ü ÂT®rtõx[l.¦(KV?dŽVIËb Íú4d0xÐQ¸åŒjØ¡ÕÂ\"¸'3à uÜÃÜv±ºx=:^:]ºs«¹K0gî:"F™wèfÚW³ë) ã\¦k%û$xi*šÑÑ~Ó¥{HýU$ÑÃô¶‡­M9¶¨8WÐ1¶]ºòvü5C³k£9$È•²å”ª¨Á.¼ÚšmÛ¢…çTÏ•,÷£¨QÀà Á´åÉÏqvP-f>»AÐË£Äd066:îEæ@Ga¥Ms5Z¼Gu=‡à¸Š…×™™‡9W/êö0ó³`#¸u Âc€%+åmŠ]•§æþ9+ôþt’ûéù¼g®‚cóúwg; (-Þªà®aã:ÚÊh/S…ËnP™u^Nà…J©fGp¾‡ÎÐb ´>īӔ«QÕ¯¡T¾ à ‚ۗ˰F y{?õw²»ÆS]'–ù! üêG™aƒ(#ô¥†4 7*…®Û¶wtÌ& [êª÷:⨰¦âúù;T²-x«¨«Ž0ë?OEª¾~ çâ¸X ³ 1ë8É P{‘i„ –†Ë`igkÔb{È. 85Ë2SOð)e Ê×™¡2UƒÉkŠ.Séÿ¨mme&Šv+ÈZwHi g˜S˜Ä@ù±¬’ݼ¸Œ¤ÁYì²—!6¨êU\Æn¸C£R™…¬³¬éSç¥ïû¤yz¸y1¸J, ÒªÇ)‡õ:Î*‡ Ÿ4’¡<Ç:'·íÆÁ`y¹{Ë^¢A±ïœÁµÿÁ> endobj 22 0 obj 1497 endobj 24 0 obj << /Length 25 0 R /Filter /FlateDecode >> stream xœÅZ_sܸ ßOÁ¹>ʼniQ¤(©}Ê5M›ŽÓ¹Ô¾¹v.÷ KZ¯­´YIñ¹Ÿþ@‚©¿Žû:ËD€H„”Ï;F<øw©~ÂØ'éq÷ÙÐ }Â¥!’0Aý€‰¤T³œßà'Áà@~ÞU;üu÷˯ð0#0<켩8Í|³ûଯžxß|}Üï~¸Ý]½ óÈíÞº(àÔã8ŽÂˆD”û±úóÉí‘ürñ®jÏuÖ¥mQW/%·ßýåvd gþÿÁ˜#`CC?¤“mÖÜi@AAêQivÀü¢T¢rø»ª”guò\•Æ;üM_ßÜ0 ŠF£Ñ¶òÕ½üÆ>›m£Z{°†+uÄȘèSÎbÏó|Ƽ/ÒsÝÔû–ü\TYýРq Îáõ™Oxr¿-ʼ!/É%iD.ªä˜gö¢â©¨8¦‘ â8äl.ó}ò)߃\zl¾¤«Ú°0ÜauHιMw:•…«â¾>[p×eVT÷–Ò;'çÂ5¸«²Ü`9ŒW©¥ÜUš£]®oE8õƒ+Ì—¡½0KÈêÜAUíÌMëcnÑCÑ,jÉxæ ü}~5#e–òæúÚ‚¤rž\¿ûÁôÑ£%ìûb8ÏŽRývÌÄg þæ0Èéa‘MÂ3Ö?_ß|¸^=G1°ªxð ºg¬´g[Œ¥HЈqÏ㉥Ÿþñî_[áü†Ì={Ž!~˜¤Ò‰„[ñ#¬ì…ñ‚Ð>€ÖcΚÓ8“ üV³[ÜàAŠ nð Å‚Qð i„Ê{ÔÂë:Ù·êáET†D.ØF“&[ß"îoñ:†·-é.çG˜±xÂßÖǤ-Ò¤,u|Dœ†ä¢¨¾ÔŸPް{=òÊ¢*Oó¦ø¢–vS¿r™«.)-v7)õÞŽGòò„Ûx´aFWglrÍD¯7p6qC­ b‘ÊǺi-R'À¢æ±ió#fN¤ü­~È¿˜<…”þLhPÖi¢®Z–‚Æ.L}ÿ9Áá´Y vƒ#'ß!€ô]vY¾:ù˜8‚ªŸÏ%SÒ6StP Óã.Zý·8©-ºfaÊÃqWµ‰Í C°Z«˜PEê>)––sl\HÜeðÊ`IU»zV4í¹¸ëúp@êáH¦çkKCYAeE|A„®Du:Ëbþܪ""Ðqˆ8æñ¤{P¾éó+އî¡ )݃ bPxºÚö«.¯„é’‹9¯]|Ú< uÈÒ,„Äà$$íëg›ÊyL=¦r)Ÿk*—À ûɸXp“£ÖP›’ЫiÞ’ŽZ8ø‘/`.‘Ù·¯wô>^×}ŸÏ%>»yàH“ž@™I£VSE˜*‚ sŒè]èîÑŽ*ÒOͧNAÊðJf:uË¿q4Ö¿//AD2´ˆF ’L‹`Ôd Éi3Ð7ˆœV£_ÐyºÞn@Ï*¤y™23á‰óëoÈPrÒOÉý¢@Fãå¾¢®Pß„ð=&ÍUáŸ]E m·¤é PñãE}Ri>){—ëšô=Ê9‹CÚ_-ÈÄóCý&97= BnqŸWݹòßò´kÍKR$uMŸPŒðÑR*ŸNVVîµt}¦ÍôrÖ+ô€2ôÔùL~"d`Ž ÜãP.0;ë’ÆAæEúà›Üu•:<#ߨï`ó£!¹?YÎ=zø]O@glK/"=Ëñ !÷tHEYºŒÝäc†¡÷ͨëžVÿ«!‚˜gpu›kÿ„§…z«è—1 ÌÔQàµ3Nëj_Üwçá¡«$ê@ý n+©HX~²"öõÊ‘WÙ¸ƒÉzùHÀ1Í="Œã…+³Ìî8~¬»³E‡þÓ¯FN6h½ggJâ‚¢‚Œ×¥mw6×;M­ÕúC¤Üìà$8ÿ%âÃîw-%j endstream endobj 23 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Contents 24 0 R >> endobj 25 0 obj 2400 endobj 27 0 obj << /Length 28 0 R /Filter /FlateDecode >> stream xœÅSMo£0½ûWÌ­‰Ô8¶÷–ªÉj+í![¤Ú‰@ŽªþûÚ˜ iO©sð|xæ½™NˆÑ¿…¹„dÑ©‹Q <Þ…ÔÇ,€#tv…yåìÛÒ—}¤<£ø…^ÞtrD| rÙ®-~B[ßdÈÕñ ìÑ}„–›((ëWx˜ )e(B±Ç¤9 ¢#¼Ì~—ª®vçDåU9ƒè­£Á0e?0ÌvÀA *˜À2·ÕžéˆmdRE§@wÛ®Ö´äì=IŠôœˆKi¨ðUÁ§Å61dõ'µ¼òÎF2ìéiüñ?´Ê` F0…™:Ī÷²¼H{//ÝwN®b¹‘—`”†˜rn¾ 6‚Ui£šåßõêáÏú»Ãˆ.• B„Œ:àžÂ*SiÝ»IÆ*/÷ÿÁ‘>&!‘Òãÿ@HŠæT, UœTe–ï'™zœM÷¹í‰|Vg‡gìì´>O-Øà÷^sÎUjy¸²êäô#WX==lî&‡×ez|}8µeð:‹›]vW½§u¬R¸i=CbQ½ÃM»“×ù˜çãVíq¾•-ú›Xy endstream endobj 26 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Contents 27 0 R >> endobj 28 0 obj 444 endobj 30 0 obj << /URI (http://www.lispworks.com/documentation/lw44/LWUG/html/lwuser-204.htm) /S /URI >> endobj 31 0 obj << /Type /Annot /Subtype /Link /Rect [ 130.0 407.813 339.935 416.813 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 30 0 R /H /I >> endobj 33 0 obj << /Type /Annot /Subtype /Link /Rect [ 345.551 407.813 540.001 416.813 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 30 0 R /H /I >> endobj 34 0 obj << /Type /Annot /Subtype /Link /Rect [ 130.0 395.813 246.94 404.813 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 30 0 R /H /I >> endobj 35 0 obj << /URI (http://www.lispworks.com/documentation/lw44/LWRM/html/lwref-424.htm) /S /URI >> endobj 36 0 obj << /Type /Annot /Subtype /Link /Rect [ 130.0 372.92 338.535 381.92 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 35 0 R /H /I >> endobj 37 0 obj << /Type /Annot /Subtype /Link /Rect [ 345.548 372.92 539.998 381.92 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 35 0 R /H /I >> endobj 38 0 obj << /Type /Annot /Subtype /Link /Rect [ 130.0 360.92 242.5 369.92 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 35 0 R /H /I >> endobj 39 0 obj << /URI (http://www.lispworks.com/documentation/sql-tutorial/index.html) /S /URI >> endobj 40 0 obj << /Type /Annot /Subtype /Link /Rect [ 130.0 338.027 316.017 347.027 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 39 0 R /H /I >> endobj 41 0 obj << /Type /Annot /Subtype /Link /Rect [ 328.328 338.027 539.998 347.027 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 39 0 R /H /I >> endobj 42 0 obj << /Type /Annot /Subtype /Link /Rect [ 130.0 326.027 183.06 335.027 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 39 0 R /H /I >> endobj 43 0 obj << /URI (http://philip.greenspun.com/sql/data-modeling.html) /S /URI >> endobj 44 0 obj << /Type /Annot /Subtype /Link /Rect [ 77.0 73.2 272.088 80.4 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 43 0 R /H /I >> endobj 45 0 obj << /Type /Annot /Subtype /Link /Rect [ 276.752 73.2 441.872 80.4 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 43 0 R /H /I >> endobj 46 0 obj << /Length 47 0 R /Filter /FlateDecode >> stream xœÅËrÛ8ò®¯@Íe“* &Á÷Ü&Ï-gòrʇÄJ‚,®ùI*Šÿ~hIHÎÖTe“ƒ»›èF¿Ñ€>ñàÿRüI2FÖÕâAÑ|’0ÄŠÅÄ)‹HE‘R¬²6@ð°#7‹zá‘·‹¯·ðqC<`8.¼©8ÉüyñÑÚ_|ñ~ùþ¶Ïþ/|G!a ÄFrH ŸJå6õ¥"ˆÊáß“JyF'Ïí¥î¯ÛÜ#w‹׋Ë7ñ=r½5I›DTÐhÊ2ñ‘ëŠ|}=¿%×ÿY¼¾žÅòûlF±·¶& ,¤©T}d”G˜OYšxžÇhÑË]¾ïyK%/›ªjêϯÈõ¡oÚ"/ÑÚË7¡0/‰ Sf4H’,Kƒe½È;¾!MMú'_êõIy ŸGècåRF³ÄÊ%(ðϺo›ÍaÝM=ðÎ"𸍀*I"ç5hðœ,ƒ ²ûÙ]“—k¶îwEgaJMC}m,‰‡bcm°æGƒløw^6{p¯µc{°1KʾmÖ¼ëÜš®[ž÷E}çÜ´ã½›kpZøHȦµX îÃÎG®ŠnOO— ¨§”СXêÿL¡$)õD?cpZÏyÁø0ÆcòóNúc£áM±Ýòó):ï-³îxUÎÊÐ#)×ЛC-«ìwÉÖzËÖà¤&‘K½‰¹Z¸¨ eœ’¡I p¤Œ¤ØÕ- kÈQ¨ènÀ±Ï (€nÏ×…Ñ=Ö}þcÀ¶M;€¼ZñÍFf¢ÄÑgøédSש‚Pš H ‡­›ØŠ^ƒ²ŽGÑEB R4²U†›Ï¨'¨ÂâÉÇKËâž›µ¯¯^¿¼Ö¨­Â—¯þ¸~M5ŽŽWb1’é®H×þŸÛ˼pb¯e£èý™9<æQQ@¤‚*6gT!jü ]¥0L:k“ÏÐá+ƒƒz|ÿYö-Ei¦,`Vc0] –âÒozõºLÎx`"¸’Cé€ÉäBg/„Íè;Pöùú>¿3+¶mSiD¤å8R ¥—ç"]ãÜdÓ¬á4‚–$dVÈcp"Øáð8˜X[å÷˜¸¡(÷ïyQŠc{ 4uYÔ+ôBˆæöP˜ÊPž “ŸEÔOÄ%(v©q>`Œs&"'øœY«¯õ;ò²¤òg?7 ;ÜÝñ[•$(JXOÜz¹ª1¹°yÒÖÐOàÊê&ûŸm ÃDÞÓ8JÎØ*†;G|áÆ9^¹Sˆèø)MæÙƒTé7…ã.\òúÑHQÓH[ñþȹ‘ià a£á“® BQ›!¸NX?³æ¼ëQذ>Sæ`6š´\Ãr¨£=W;iâ¬QÛ¦,›£hšƒ‡;¢‹é÷¹,èy`f QfÊú9~Ò+‘‹C¨zTý®B0O}éä¸È[u»Dl©!<¶¶ƒ„”ºc!~º$ãˆÆaоž+7`±%4 B˜Å£øÛ×)_Ð(ò²,Lß®ï÷¿_^GZn¡p’\Žþ²<†áåD²ð-cSßÞ|y{¹ë«X ×µK1­>áõ“f¡êKs)·ŽÀ‡À!Ξ`x;y2ð3;ðKòŽ×O\U¤E{—לcaiÁjlV˜š]¦’àLìM#?K!Šý,I³èÇ4 "\{–Ñÿ0õ¼ÐwmùãÅSß|z7Ä¿åÛeÈÜá/lsnWÜ“Œ¦^ày™üdÜgvµÂT•RÂh½6)ÒêÑBþ*Ö÷zwÜúL`ƒˆzA”e‘SeKÐ4<ûggïé7¤9çO¶{(—øð¶t„7ó'Róò²¨7ü‡ˆi9 ªïS\€jÆzûÄó£Èß‹`¾ÌTx%^ŒÞ5^Šó_Zô“¨C†Ÿ…4ñ|B9Ä=1=¤$Œ<&Paªòñ‡ §8Ù\¼–÷ñ‘o+† /U÷Dª¼.ö‡ ídB3–Q?–ó_âÐð‰ñ/æ$Å(Ì™ÍööÍfnj͹¥¾šã$¼áÛaÌE9‡Öúˆ/~ƒÕ"–G:K~ã|Ä¡[ކ ý°+ÊbOÞ¶03uûCMŒñ ô”Q>Œ&bšôëñ¼m óÏæBÑ †ãÆ"\~³“CZjÃX©ô¼PøcsPÎJêa4Äk¡Äv}xû“Mh+.Lƒì¼†Ã¤Âǧ@¾¨¨ ·@¾=ûôêÅ;¼nåê™Ê1?E\#H§(ö§íÔ.ýùº1çó’㌦.˜ÒÂfyg•¯ºÔ±iWÅHtú,=»élÝ¿›#)óæ*ž¯wÃöDÔÞʹSí4„Á"~9±Ól4ïš›0­¨¡î+œõg¯hžEíÚ=-€ä'ììî³ucçVù#˜GJ¾íɪÌë{×^t|è¯p”ÎáÑ^³u7»ÂXÓ6ä©xÜë[0 êÊ;'Ûâ€m^ß¹¼3QXÇX8›Åì½çë ˆ mZ"ú¡xÿž·âé˜à“·Ôö¶õ=ßPýƒßƒýóœ/œ‹ƒ2qß#•øΠø+úaqzÌÄ¢åÄpÕûô¬¤ã[,†c==¥éÐ2'Vž^#šùX`âX<ígÿêÈobRyӴ䆯È_¼Ýt¿‘%†§T†þF½T½Ø?­=4dzËg3 ó ̯à=Çr5rì¥Eôn°HN0g\Šf±¦k‚bÈUѱ3–:äßZ?ÿ~\ü æÅÓó endstream endobj 32 0 obj [ 31 0 R 33 0 R 34 0 R 36 0 R 37 0 R 38 0 R 40 0 R 41 0 R 42 0 R 44 0 R 45 0 R ] endobj 29 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 32 0 R /Contents 46 0 R >> endobj 47 0 obj 2444 endobj 49 0 obj << /Length 50 0 R /Filter /FlateDecode >> stream xœÅXIoÛ8¾ûW99€­j_|Kw¸I3ñ (êb@K´­©–D’íúß÷Q¤HY¢\Ï%ãÉ·}ocû:2¦ôã& ÓÑ+ß3g"Ëå[Ž‹ [3”"¾vPBoµf³‚»‹ú<ÊF:úmôõFH†ãH™ŸGO-ýôDsý:ÚŽÞ/Gï>8ÈÐÑr#!²LÍñu]7| ùšeôg¢eоŽïó4ͳç§Zˆqrû -ÿÍ—g.Y†ù?¸ôtf„Õ3=­ìšÛb{°ÃÑ£„Ç™T¶dƱï Qº´Io›tç7U>bÏÑèžæŸ×ŒåcÖ #Õ=ìí÷òôs\íÐ-2Í@cš®Í:Â^ã’ˆ<“ëc¾O"y5Ëj—‚XŸä²‰³8ÛŠ ,V%©¤ŽX$ÁUœgåDžR^'¤u´É“$?’H¥û—ª^÷¤ˆIÉ‚ÚËÔ;hmj`;@ãóÆ#FW;"×µy’Ì·Ž%oœ‰e^D­ƒ*Ë|¯Š}XµvÒ—„ütABà.5±ñ;@p ÅDlYtÁü{÷Áíõ1ßÔ<à |Owû>ß/ -Þ~JÀkzAàBìñJC$6QÞ‚,– ­Oý@‡µ,Þak­<²tÍfÁe+\¶®ƒË–÷‹ÇgA„ .K–7œé…„ñæÔ–¸Ëb A; â'‰ ÖD^ÚYyŒŒ³:ˆüLä)77‹~­(Ä™JM8õA²íHµþ©§knSµœÀYÎÓob, QqrkMª#!™Üö¸Å«ªˆ×ûŠÔIÈ7—»–JÖRnFÃßÒu$5¼Š“ª-«Ü`5É ^”}· ÒŽ¤H&. ‚+$¸/†¹ !N’Ó•ø@³6Ež¢ˆà„Òu…•yJä5$Äû”RàºÖ7Äó´€¢[3dy RË ‡QÓJG䮿Tô1§Q!M$ªN­‰uLkê5PŒÃ04Ç"õ`œ°ÿk~·œ£åÝûÅÍ?~Z<~™ÏÑjŒ¨#DKôð÷b²}º&Åjlù«ÛIß?ô:ÒÑÀoeõO†;!ü€‹p‡ Äëjñ–s¥x(u.ý¿ˆ·½+Å“ÇIgOŠ7ôùNp¥|Úìqv¢è_ ½× ìðgx uµöÚÂW· éAù³´¹üøéîá Íš–éWÛnêWÏ"Ê~ЏoWÿR2ŽHVùJãlÔï+Ó64ƒÖ·íûLÏ’9ø Eæû^T´n¡Ççí-¬ªù¿šŠŸ ÚE‹-º¿ªE#1]˜¼ ÉЃ€iú£nÔŽuqØCZ®@(E\ö>ðzÀë©X'Ry=í›5*rr‡­CÚÕqsˆÉQ’|VßÈU=í9±ÁYxj«)ZZøL`îÈ”dŠ_^H‹î>_ó^Ýjr"¤x²˜žÝ†!ƒ¼~¼€>˜mì½ZÎ.õiK‡Ç:¤¬ïX“´Ê×d‚¦¬)ó‡véüDÔžªp-ú,;“ƒèÍ1kîŠûôÕÕ¹Ð,ZO¿Ç0ufßUn[ô¢dbïX Ø–hi¶O…:¡ûªÓ AÀK ])˜Ü.D5¼`šnÑŒ¹¨ÅÔ3iJ{Œ‚%Pâ‚Ô%$Ü%^[WÂS{·>ô-Ag’‚ÕP#|”j•ܦ¡Õ˜Ç!Sm2-7/±:J„®òÒU$¼Z•Ìž"šà0¢·}eÒ›ršð;º s/ë9¤à5”Ñ’(§ùwT)XÌËÈÔV*uYJTÄtVpØJd.× ã*áö }J=«±xŸ(8üáJ¶1PÖÐ%ØÝ^÷=wK˜¨~-¹Ê¦;£CdZ¿áEš ð÷úé@óçð¶zýßRO£Ÿôÿ)š endstream endobj 48 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Contents 49 0 R >> endobj 50 0 obj 1471 endobj 52 0 obj << /Length 53 0 R /Filter /FlateDecode >> stream xœÅZK“Û¸¾ëW ö’™*‰áC|ÍÍëõ¦œšlÊm|Xm¥ qM‘4£üúèÆC$$ÏɱêDýB£Ì×E@|þ%~Ò<$ûÓâ+¶$ I”`Sœ`í…19¤cR‰^*Šÿ@'NÉçE½ðÉß¿ýÎ?Äç ç…?N2?->Yó‹/þwŸß'Ï‹7‹¿þ“À'›ƒ1Qzqæû~E$ó¢0ÿB²9‘ßîÞ7§SS?}z$›qhº’V÷¿“Íß6*EAøPéÓ… Ü­i˜zgKîÚx $>Uèü…Qáà÷ªP¾‘É·Eºôówüº‹ÓØm^váÜôª/¿³Ífnskmò©6ëLÄi,4IP…íÝönßœZZ¿–(f3„¾%<Èý$P„<»Õ—².ÈÃö:çá Ãͳoê~èhY=y¨›aUU5ç_¯]üÃkËgeϬ›óĉ‹§¬ËvÏäAk¸½Ÿó&Ùœw{WÓ›÷Íœö²mï¸reýÌÍÉfÑ"Šù\lï0Çö®íX_¬\^ §9n›0v°´fÜÞ;%]ϳ½{ØÑž­º«A7vÇš%E˜Zå@›##÷då|EÜ)ÖY€'‰·^¯ExçŽ1~úðóêß?|^½|÷ôtuþ öù(±ï§Qèňq¢û®1°ì ýÇØUåKúÁV¥nº­ ~ÿøÏ§7(Ê%â9)öƒ0 ÜšÞÖ1Zg·ø':. fîY;ØÊP •}¤uQ±Þ%i4™®g/¬+¬#/%w}Õ 5íPòÄaÔ¤€®)X'^žð:ŽœÍúM#ùú¿‘ hX_ÿeðL מ½YŸ#}±:=²¡Ïåp´m`±œhÛŠÄc¦8\é)$q¸$‹'Êñ$!¦æÙ­Fº |%óíé–ÏæcSW¯Œ½ù@5u`gÓýàœ­…}´±—µ“‡îšƒØŸôÔVl©vã`³u£E›8ĹE×ÞsmŠÉÄ^Û0Œ'ýbW?¾UãIèÀK>ÅJSá€[ÒJ@VQ[*z2èp”¹Z€ÝÎËRV˜/µ§éŸØŽÕ`úÊX˜‹p1´Ù ñÑ-ôŒÃa³ ›ÆbOx­@(y¡UY¡8lC‡’uK“ïÁú=mY±$}CM³ÚÑŽìßoX/ð8v9’çª79rÖO—@BÍ¥F42¿²õ„ª©‹Ž¨$€Ž‰:M,SSÆŽUTdT#NczÕ2ã]g},Œœ/e7Œ2SNDuX†Ÿ¡.-#½%­ ç¿<~tÜÈ ¢Xç!.£ e× Î“ÉðWVð¬ŸXÁ£…T8…wWš‚ü%Iª)(ï—scÕœm Æûæ™k”~xèš“=ЦÕ2X:¿âñBÏXV•;Óo¼…™ªéšˆTB§…·Räg+W¼œŠ­2$±ŠY¸ý#’:¸cªB™3Nº¢y\=íò›6öwúvà]ŠÕ@å"@÷ºBÑ”éD…dÛ•'8bœçTǯ³Ý8Àæmj­!,­q;öu,áîB ÑzgI§5Ï4|¶>ª3‹5ÌqV [eÓQ*–èýÆ hro\5©õglŸÿÙ#óF endstream endobj 51 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Contents 52 0 R >> endobj 53 0 obj 2833 endobj 55 0 obj << /Length 56 0 R /Filter /FlateDecode >> stream xœÅMsã¶îî_Á[“[Õ‡õ•ž¶ûÞ¾Igg2û63ïÐô@[t¬®$º’×ýõ ~IbÒÝË>ç @@Pùc‘þ6â‘—1Ù·«?-"yL’L‘ÒŒDÛ NIKœ’Fp9@¬!x Gò¿U· ÉV¿þ/+‚ÀeÎÕIáÏ«OÎúâMøÝ×ÉóêçÇÕR…äñ`C”ÄAZ„a )‚$.Å/&-ùõæ=o[Þ}þô‘<žGÞ×´¹ý<þ²ú÷ãÄ¥$Šÿ.}šØÛšÇy0Ûl) (¨H¼jÔ>¨'jEÃç«F…Ö¦Ð5iºÏßuñ×·8OA ŠÉæ–¯îåwŽÙbÅÚÆ›rîͶyš O² ]!w=£ëÉž·'Ú]7¬=5üÊØ€>º²q$ä{˜EZ¸Úm¾Ô]Eî~çu·”€ ñHÔÝ“§)³Ù7tˆ^u©b»«€ßÝ‘·ló…]µÙuµ”L3Ÿä÷¬~îþI8+|ÂÉøtût»(®âïéæÔ³¡®X7.…¢Ðç\JmË[ÂÑÂÁÚ(^¸õÍmi0Ùc±/¬Qê ÓdSÄÊ^ÑÌ› bKºº±›â©b!]dÁv»éx‹Òï LàêØ\×dä¤b‡ºcd<2Ò³†Ž5ïÈŽÆ:B;€+ÁT÷¤¥}fý^ÖWn1ÔLZäe™oղ䧟È}'×1:‡†¤©Ï&Çò™(Ðy¥Ö÷È@ÍxeÈÝïÙ0ðÞ¬½y] ÔOZaç_™]1ÍRâ›’+.™ û³)¦löeI\ÆK_•_I¸õHzÒ+óìsgA–GòPI¿ÿ‡ÿ«™A‰d„|)Knɦˆ ÷߈ YLäÉ`Ñ=uÞõL”%ñŽmF¾ÇzA„^ªÈjƒˆwšÇ]«b,íÝŽ¿0‹^˜»Nsõ9)f¾)jˆÊ wM¶4eÛ„A›†DcÚÚÒ€íÓ Gá¥n‹±?O Å(#áÈ/Î`à–WÌœ‡ifKàñ> gÞ¨ûa\“†? ä™g/{ƒl ²'ÕR›î;„¾Ðº¡»†~zu<ò"ƒ ËU¸þ%%į¯dX U¡ ªžrU¥ãر“Èɵ‚/úe{´äpbûúpÕzŽT¿¨…“šV¢PW'ÕLütâ«æÝíèÀŒ;š¥(ø¡Û3cŸ':ÅvJ¨Vû æ® &ÝCp1k똴ËÉ2‡éÕ†¥y‹‰2Í9o·Ž¨aq¥ÛÒ#lVÇ4^X¸‡ÁbdŽ¿VÍFû l-ô“Á0_–r:åCy<ÖVÌ/˜ K"<;Uf3ïäa‚‰O*ΠÝ òø$ü@ .äX0/´9 ¦ÇIáX–žÝy&Ψ 1#CÉEŸâ8±¥6÷„ƒv&ADn6|”þ*ä¥f‹Í„°é |9Öû£ƒ::.»ýRHXXôÞaS‡";Gí8ìHÿ¦‰k‹s‡st=h;óÓ»$œÆ•ÏÏ=á»ßÙ~ôôµ-è aþ ó4sk|vv¸…ƒ»®Ü„p_ ðéfxº5YŽcݶ¬ª±’‚Vôräƒ})ѾÃV‚ÈÎÒå}¤—E­È½‹»ãÌÂrO8²téTžj­¹š4Lò ‚áÑG†äçûBÇxѯGQhrR˜Ì¿ÜL,ÚiªžCÝ=7š(œÙtHkcƒ¶ê+TÉV äŽF ½¾Ss †¿² óøÍìZðMæËì66‘jöøbIË$ÛͦCl£LëEç®Çæ4,ƒx‡áöífµä““í-Áamc wÚqÞ0d5Ü©F„X}0à6ƒÜ(õ¦«ê=Æ`(jÐHmß8 5ÐdœÎžk‡©¹ºÖe¨¬ÆRS.¹Çsß±jS«8šÅê^8»‰ °¾?ã0-‘#öR„¥/¶ÕÀll$×§)³Ê_4K£cFµbŒm•¢[†ëÈŒ‰ÃE‡/Ä3}ႼixB“$³ÐÈlõ%fšI Gw¡G]¨Š-€›8Øà"æäAORyÖ[œvæ<7$œâ~uøŠ¸çmÅå+É=f¾=|ÅC1•Ð<Âk»þî3]¦¦ùòÁþ¤pM6mòÇ ‰ò –_»' IZ¦AÇežd ªzÀ|èk!ßË®÷_}1zë‰oŒ_ažÄßz^ÊŠHDaBnN=©+Ù’€…+ÁÝ0ª­Ö„Ñ‘ZÄÜÈ é#ížÏôÛ‚¤˜‘핵 ÔÒÓ Ž=ƒzÞĸ=‰ø¢:ñOZ)•…¹°JøýLJÏS $°”Ÿ¯†»&=7£%˜™Ѻƒ­GŠw+Mt VŠ›$ì®®ô¾9WÚWI¢êŽV­{ÞœÛÎQmâ"1qZú¾‡fâSñ$6ÒFëNFÇZÕp{¬›ÊbB,0¨ºÌ Ò‘h±«W5RA¢¨«©š„÷GÖRƒîõŽ5pÕ¿Z½g™2JëxßÒ¦þ (Ç65Ñù/ħÕß_+ª^ endstream endobj 54 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Contents 55 0 R >> endobj 56 0 obj 1991 endobj 58 0 obj << /Length 59 0 R /Filter /FlateDecode >> stream xœÅÛRÛFôÝ_±C€¤è~!%-IMB‡BgÒ0µ¼Æjt1Z‡>äÛ{vW+­¥5É´3©ÃÄç¬uî×ÕÃÈFü3ØW;(ÉGÍ™B¹AsäÈöLÇG9j`eì)p$_â!èã¨Yèíèæ~œ! Ö#«ÏŽ_.ùìë»Ë·ÐýèõdôâÄG¶…&óÎE®cú‘eYvä¢Èt˜}4ÉÑÍÞ›2ÏËâúò MVuY¥8Û¿C“_GãɆI®íü&]nèa Ðì›S»â N#öSÖÄ¡ù\(”ß[•²:,U¥Í8WáÛCºpbF¡µí­¡üÎ.D‘Én‰ûÆxr,Ó e­ÀƼ|‰ÞWiQ£3R¤Å.Eɪªà$Çi†ðlVJP²ÀÅ=Aip1C?r¸.Q½ ª¨Œ˜®ñSb"ô–T5*§‘¤FY‚›÷B4¯Êœ1oé†Rd‡Y™à,{2H§1àȨž‘ʬn÷‡Ìl«ïÇÛ½yYå|ˆv&Ò2P9G_ŽÙ8ìËñކ¡ôMŽiEk£À9c·ÌÊ'Bl­6ÎÀ/·{þ6Z¯ï •†°Ba e AI=–ÚÉXÎEI—8ÿ™–)$’YV÷;Z‘&ÿ>,!ÑÉW2Þ±¶~ÅÉ!ØIYͨÁªÇH Zã"ùŠÓgh1Ô|»%jpÓKp…¤4J2V¶»’±†«;Èþçp½ A7Gè†fem<âlE:žJgwȾc±ÒÇËñéÂ?j ¿ƒDeÍFÄm[Ö:øÖãÈwý–Ó ê­GT…4ƒƒ1ŒÓ‹bËvƒP0?’ê©^°&·Œ&2Ú#Ÿ²¬;Ôî– -Š Ã¶ö;„µÄ±â8°bgãÉV¥íØzŽTUšõk ±;¿¶0ÎX×yR¬Âyš¥X5­ìà•B:U¨ŠrmvØD¥( §±ìžmqkƒšÇ^Ï&¡F`zÏxÔ‡ó<ØóÂPÃwúÃëñÙøÍ3žu!¹<7Ž=ØØ†‡cÚ‰Ô°œ& )•Çx¿j; [Ìî@ÕofY‡‰vÔ Sœ|R´MPRÊ¢“RšK¤&º°Ølz¨i›lz5ºrXÉ3SžAyÐöa¥‹‘È•|`¯$2m)’2_¦™è“Íd-%,ÜÙ—,ä˜àƒºêTXÖižþÝq+cC¢é¾åô¬—ƒÈéhÎcëö\Hå ´´,KS‚üîÜÀ9ÁE‹4ô¸6cNH@_%˜µdIà¿¢å ¼ÅAQ­ïà"¡±Ûözv3{XŸ„ŠÅ°×úl½úìná–Y¡ò‚ẮÒé nkàøšU,bwSüJ¡2¸™—å:z…~ø‘5ãúëÃCœþ2>ŸÇ“ÉÕéë“1:¹¸x¥áy•Ræ°tžB&ŠöÄÕ{XáŒj8ÆFG4ÅÕ7ëi¾>¾Òè8}ëÿ«®{¯´©ëÚáï‹vÐ Ãð'‹ÄS]Cîõ7¼Wã³ãÉéÅùñ™1þý=ÜwÅ«1t„NN¯®'žÿ6¾Ý¥¼¼ýì®þ endstream endobj 57 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Contents 58 0 R >> endobj 59 0 obj 1791 endobj 61 0 obj << /Length 62 0 R /Filter /FlateDecode >> stream xœÅÙrÛ6ð]_±MlÏX,Q”œ¸3®­´ê(¾¤6ÍØž ,AŠ”yHñßwq€)(qóÚÚ]`ïÅbÁÇ–.þ·ÙOÔ÷aºl=Jš‘AW’Â.xÇa !a» À¯!ü›XÀûVÚrá÷ÖÍ.ÎÀE†MËmŠãÌãÖ•¡Ÿ­¸?\¿ ­ß&­_Þ†à¹0™ë¾ö\×õzôœÀï³?&K¸Ù?Í–Ë,_`R•Y“äà&¶“g.žÿ?¸tõÌLkäGN#Ùœ;4¤Al)‘y¿Bª…qâw§Q®¶É5Mzžçª|wŠ£)NïYj=g*pȶ²Èt+gúMg:=ð]'èbɺ]O8sónèr•ij;îàøWá›Éƒeþœ~~s:Âân?ŒŽp=L†ç'£öàŸK¸Ý¼» Ïà ·¡a·iIg`ZãßÁÍ1ÜÌã¼(?¦dIïàÕˆ¦qúêÎng·÷=v–ú·pr~¶-¹×Œ¼äïvÿíðz<ùx~ònǰÇß»=°ÆÃóšyý†sØPØ´„2ƒœÎiNÓ)E’•§@RÈî?ÑiÉ6N« (Ô"ßoFåÃxt1iÿ}2úkÅcôKIÓ"ÎR g«r09ÌŒöš$…=–·ì‰JˆeгçÉ ¿» .> ŽÌ×1xöHF[¥õ-K-Bz–bz&dš-W$}‚½UN‹xFÓÙö]Ký|çï.OÎ?8—׃ñðlp>ž©XšSí{NÈ;Š«ž,(@; a¿fÜjÝ®²†×ëD ºhvjöü¯J¨ ÈV4'x;Öx\(h¹Êò’¾$ÜÓ)© ez¬Zî)¶JAÍŸ”~D´ð´†H lˆÚ\.H¹mPžÝW…¢ãi¬%¤O–„AÃã邤”KÃuiƒJ‘ +Û¿–ä>QÄ%Y­âôá°Æ“ø³Z›fIµT’X‹T+Bâ!æúLá§ÆÇY mT)yÊ*‹»°á.É)ð  é²A¡1÷Š W0z,•Üõ]%è»]ÇŃãvüÈ¢à5èc»–`ßõ,€Ífªá9¯ŸÍt½nI¥1k¾  Œ‹³Ö«4ÛhdžåË*!¥±™iVHNq- ‰¦Ñ/¬©0» m‹xºØ¡ðÞŽ‘iŒ~¬HÏcš‹ºĺž¶]ZU¥!g^ÒÜ£¨×ˆ‘¬g¿ãt`ÿýƒëF?Ó§M–Ï4AË ¤(1`Kì©ÂTAÜ’¥ûjw^jTž¢dUn ¢M©K¨»5à‡‘vpÄïx¡ÅWÞÀwÖ_ÐCf|xŽÛÌZý*ÏÖxšB48¯Òii½‘ý¾Û¬ÏÁhp:áG•MŽºd*c&œ–UnಷÊx·a_5(F„yž-5Vw1ŽÌ6bÊk’¥ìT왆‰UÁîpâÞ2è®ßK7 0×$3¼%2´8ç-@ÜAáÂÒ?h“×§ËsÃFS…‘ü¡b%«Â+êÌpT\+®J5‡¦ )4µfG3j’BË]›¤‚êíÙ\Æñ{f°¡ò$×µ«Ól³çÌ¡ lDHêˆu YžeS®ÇÚQä·âjŠŒ¾éN$À8I‚µ3¥¹VG» ÉZœAI“'ƒ·\XÍ9Â[-רŒ¶kL6Uר8.Z ±D¢5"‘Ä¢<¼Û57àúJÔ”\Ãiœh$6ØbC„=ÇéLc8•8Ê I 1G+A•*àûîòžæÔѶ $Á¹©0yU”ä ²`þ†JºFí°%¶a¿[DÅwzur/NŒ«èýœ ‹AÂjÞ®UÂÍá¨!¬XdU2ÓûT08Î%5•9áÂÑXA²1Ší ¥QÖBSݵ2Š~á윎XHúØçpÆî…A¨tOJýº)¶ÃØq; ž[l;øò;*D¹«§Ñí…›=QmÅS(¶jdÏίj”ï(«ÂÐâ¢rX‹œU[x»/ud+ØýJÄÆ\¶ù‹ž¨öô¯?Tؼ Ùkð%!Ùe˜zyî0)ôšaÓß$^½gXs Ó©³Ã¾À’æŠ:¶1!cO±è|+çuhmŸ…šÁáfבà߈væIÆú #{Pì‘Õ’l¢zÍÒbrþk’ú¶ºÙJ5C]¿$ÌИ½åÊ+Ò/Sº*7n¼HYƒ¬ ÖYCÚün`9oõû„}mbìµcë˜n@Ì,Øg_ü”á.œíPÝ¡E~§8”_5³L|·¼„?³Ûä1oãYUr:Nj?_]¯Zÿ±ùÅ endstream endobj 60 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Contents 61 0 R >> endobj 62 0 obj 1797 endobj 64 0 obj << /Length 65 0 R /Filter /FlateDecode >> stream xœÅWÍrÛ6¾ë)p«=#1 HQääÔÚr›ŒãÔ±fÒ™8˜‚LÔ$!¤Y¿}(€¢äÞ\ûÀÝvñív¡çIˆ0üÏôg‘”W“g+ Ñ‚ (±¢y‚Â8 sT!KÏQ©wyé)ø˜M@èû¤ž`ôûäÇOX\# ÝšÛ)ßMn½óõ ~÷ó1zœü¶š|¸š££ÕÆ…("Á<Ňi„Ò "™þ#hU¡g¢ªD}w{Vm#$§åùO´ú{ïLvèLœê2kW’Äør–‹jKë׫¶¥xeL!+ ïÏŸ¾>”|”@Éã$4>~DJ¦øšÕ ô¯Y£Ð§:Æêq| ~¶Ýk¿un’ŽÏýBkúȤ>õ³PlƒîZòz¬œâÑ©½·³Êé¤?ýÃU„ÐñüB¨Ã¤i–¥±5wÉJÖðú}}ø›åê Œª °„Ü´êiÇFûFtèÍÒ9$û¬)h㸎9ú©ö÷%áè\2ÚxjÂ@r^{‹­tÌš6ô*6u"ß¶åÀ`S°Êq´^;æ¹eòõÔÎ{89/Û5Äiœ¡0΢Ò*PІ•Å©a dÖlÃk¶v2É&µr"C+úÂ×ú» o¡‘¢}(=A'y3BKÑx°6ކ^îizVT!ÚÒ[2*kÇÚdŽQç°ñH=‡Ix­íN . Ü4L:"§X¹ œäSó‹rÜsËMz «8\‡r*ËWO{Ux«›¶ÎuÔ¤¯ýQó!I`Ý{º»<¸\^/WËÙ§›»Õ¯7ËÙ·åÅ×o—w§¯Žß2çu¼,}w*ñâ9p4¼‹èÀš¹D6/Úm)*ǹ ŠÜ- œèѱ&§NÒ¬ö8OÝ×|Ž>DáëQ90¢¶p¸«dYHÇTôÉUµÎzëëë&t$,p‡aÑŽ÷þ"®PÉ6 ‚þB¡•K©±ªzÇ‘9@ða¼2ðÂy¡3öÕU8u¾q´ñÛÐ.^†§Ž´ãÄß °ÖÓã†jfº‰áÌ%´`8ø)ß8ÒÔ—a„‡“Û{fÍìç«Û,Oc9³ð°G”$Ö:=&Ãõ­×rÞ>Z‹Þ#°a œäš?±Ž+Ïœ‰¾¡;OîBÑwtïïô¸ªk‰?}òWm=Žñ·[¨8v$:Ña й7¾ºÐw…@]£]|¨‚Jµó?ø¡O$„`œ‘´àëq¦ ù½5îIš8ƒÇüDØ©Aû4®…Ñn~úL՗뎫…xRÞN3i “KZלy˶bwt(õ`I„áù·#»¸† vÒjÂ*>¢;u‡+Qy.Ùû°£»‚çÅ ×s¨#É<Í3ÅúVx;ÿ‚„•¯žçk‘·¼=Qw¤@"Œ‡˜%ÛôG&¤ ¦`8—ÜökÍ÷iÚ‚Ö$\¤ §íPÔäSMO÷Ðh?#w&öËMÁÕžæî'U^f;sZ™ï¹\¬÷´móš> endobj 65 0 obj 1261 endobj 67 0 obj << /Length 68 0 R /Filter /FlateDecode >> stream xœÅRÏOƒ0¾÷¯xG—hmKruQ£ñB$ñ`v`¬lM¶â€ÄøßÛÒ²âÐë’>ÞÏïû^ˆ1ï=ÒŒAu@Gï£2ˆïŠ ³àíö6kb°Ñ2‡K2ÆÞFÑûÊ7@LÁ'"çí†âW”OæÛ¹øü)‚ˆ²AÿÜBÊR|¶›¡:r>ãqlhïeó§ëêL΂"ù]÷rà lÑ]nb Š:\Ú42,XfÅÞ¯(_¬ xF÷Ål•–l¶E;ûD&Ʊ°ÿà$Rœqn¼IŒb&RBH’8rËFkYõªÑPê > endobj 68 0 obj 422 endobj 70 0 obj << /Length 71 0 R /Filter /FlateDecode >> stream xœÅTMoÛ0 ½ûWðØ&ɲŽéÚ ‚bA ôÐõàØÊâÍvR[ëÐ?ʲÇqÒ[–ÄP|äã#•W‡ÅïÌBrH çµõ1Ü uù0p hmr50xgáaƒÐØÀ“S:¾:Ï/x™EÀ_‡ŽÓ5àGg9¨onèÅ브ÿËÃ).Èh6 Úµ>ôØDæ*oekO›Õš–œ=O’¢{NtZ”–îåŠSøéÜFΧ/>0 Ñz¿´ÂE ¹4QÏWÌ¿~è›sòÂ’MÑÔî›Aê8ÕRÊzj&+ÚžlKq¡lSx!pIhà›øÐîæÑüvþxÕÇ2ê’Ð5%C÷õƒs1°sˆ6 ê?;UÍôûNÁv qžCG5Så”<ÇÙ>/—‹“mr±FL4 i¬ãU\«ºK &tò¡’"*h+æqÝNÏ#Äg¡”‚ɾW*Q©*‹¬Öç$QEÊ1³ôm†Žî Ô:.Ó¸JgÛÕ/•èÐbœãžyȈ·ùîTTÙNgÛòæÄw…”žÛ m²®ûø2®’¦¯î×àBãœ;»™÷a$ν3›ù·öÉ=`B8=.'8}°ÁÁ|ªŸ¾x¿¤wEƒ.Òl½V•*õ w¬âä÷L•é¾ÏTUÙÛP‰U£ƒ*1z@Ft?‘ÔFt+¡ÞBVìrU*(sVÁ€ùÞ–fC¬*€q¥@½© ’JÅZ¥°z?ýðÜ0$n°¤Üàs^paüŠ þg—Î?&9Ø& endstream endobj 69 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Contents 70 0 R >> endobj 71 0 obj 609 endobj 73 0 obj << /Length 74 0 R /Filter /FlateDecode >> stream xœÅXmoÛ6þî_AdÚ±FR)[tIŠ ]·,Þ†¡éŦc ¶äJrÓ`ØßQ¤^,‘Š]DÇ—;Þ=÷Âc>NÂð;UQ4ßL>š9‚E>7SG„y4@dè­Õ®Ak >z+ôÇ$`ôfòþ,.†Ç î‹«˜o'7óÕ þêçw5ð ý_4¸Ù÷‚ Âëù¦âöõÌhAjim`3_-U“Z9ýu*…[°£î×;£‡ÉëÙäÛ«ŒfË6h…3^H#õCÑlƒÞ¿$áñ4ûqr9¸ò+C6ð¢:»1T¯†c²gSåYalÒ&½‹7ReÁ€…ˆFæÚj†“‹Ë«óßÞΦç³ó×ç·—'Hó7\„SO8œ 2ä¿£TôÄš­$ZÈe¼[—h—ñ}\H”Ýÿ%ç%*3´+¤W[ ,0âáƒ<®åýçI|¿n¬vƒÅ#/ a Õ¬ëD³§í(d‘ï‰ Â˜rÃvž>ÕúfKT{cÇ)ÊrT ‹úˆ<&”f”ž»~ëTƒÀn7§‚-IÉ<.%J³ºÞóØ€\p'&9®Ó¤Lâ5ª@ršøÆ=†•áÀ’‘óBf`Ê4Û…,æy²-“,ó‰ ¤”ý`­CŽC/—»t®ØõH¹B}7ñ<Ï4™˜¥Z>/b*º¢ÀrÒoooF¼37?dÖG—«¸4úme+ÌȨëO“Õ’¢¨ÙÍÔ§*x5ë²^KŠzQ'…Ùç5ÒË[Ué)­Y–Iù¢hb,ï1dzTAg‘SÛã…V!.|jáGÛ8‡ÚVÊܳ¨íû&€•ÐBç‚Ó¬Ž%ÙL@W±Ì2É åÌ)'Ùó¶™17€år'iÑNTwT³µÃ·Nºrµc4í÷IÏìH‹î‘* «”23UNÚé ŸA…BL|h ‡v7QÚàX¸¯ñ€‰:혙õnÜ}Ö±.Šs J–ªgZîr;GÊAù`·Ü9>¦^$ ÷&k︨s´‰Ÿ®ZÈ[àü–2t„ðŠd\²@:ïÀ«*wæ«,™ïõÁ¬o‰OCÂ][Õ!ݜĻÑÞI1©š LHÓæUaÄÚ*Àº5€5€9E­ètg£é­Þ*õ«`¨Ç˜ß¨OÇXO;¤5 7CMÖ·„Þ“õ5ô€>ö=êC#ƒ©o9n¼ôáB†‡Ý­>¶îQ²Fç½´U›]ÑoÒ”¹ß“½Í³OÉBB,»¤ÔŸ»Qó#O5©˜‹¨çû´PŒ°·mZõŠS$óˆÇüq/Q‘<¤à¹8àMµžz< YhÞz—ŸãÍvÝÖ[I`>‡F’ùõóÈüÜÙJÔÝñ0µ:»ˆï_¡&P÷8úÜ¡èÅÝË£…LË#t”ÊGY$ ÌDõ¹;Fgµ^ÓêYy¶y*>®­*ræVñ›ïªþô'ü=«þ6Ï{ô7ƒæ1¸ ‚^YÄ ~ˆi²FG¥_Àû…4fÀ´Å†mV”¹tºÜÕ1ä—Ÿogo~½TÖ´dÏ$^]ØL °Ë™ÿkÐY²œV7D΀Õfa@\±q«åVWÔÃ2máö]Žþ2¥˜;ùÚΊɹ™e¿p¡zùáéóEQ¹iŽG§.à‚û_œ®:™ _›ùÕÿ_o&ÿ~¨ endstream endobj 72 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Contents 73 0 R >> endobj 74 0 obj 1578 endobj 76 0 obj << /Length 77 0 R /Filter /FlateDecode >> stream xœÅ]“Û¶ñ]¿OçæÄ’ ’žigÜ4É8“:ñXÓ>¤™ $A'Æ)“”/÷ï»À H‚¼ó‹?Ü.ì7öʧMDBø·•²‚’ÃeóI¯E$£$fz)e$Jš’ ÑpJ*¹Ë¨ànàLþ³©7!ùaóëoðñHB8𸠧äÔá›÷ù%üêü] âˆþ_$x?öBF³`âu:Æ5XABòS¥Í¦ÿ"UQ8ü»(T8Èú¢ÅýzÌCò°ùÇnó×ïS…dw‚6‹a%Èi!ÿ£dw!¿¾¢ô›ßÈîÇÍw»™+¿²Éf^”¼­2 :x5Ã0é¤<›iP¥wü"P) ’œÐ"Y*÷çxàÛŸß½ûîÛÁCvk‘• )Ÿù/¥Ùd® ‡Vð^NM]‹C_65éÀ¼ç{Þ‰Ày„N¢ ,B ÇÜ÷·Z‘0g–íÊ ò¢È"mŸOuÏÿ4 ³‚q´(ÓQ¢Ež(œï$†.PÑ—ƒ"Ûî*‹BE¹ç0ùËGñ´Â‚f‡ÊÓVüYv}·È‹f>^+lrãÔmÿt‹¬böe&Œ™G´kÓT˾ÐI±ÏKþQlâÄoU¿7Ì8äo·ñý|¨FQÄyÂÏ¿inQ÷áõ‘ü›W7Ñ- ¡%4 1\<šÄ«!6Ë ‘÷ôò ¡)Ô“WÞÿdá=?| Á%áòTì‚sǧ{øxõv½V¥Hñn-TAÀZ¤i×7w}[ÖÁ4;Iõ òRTT¤:(b[á  ¯ú³p°=¡Ê×Jß”ƒj1 ZÖ‡êvî^;Hs•¦à•û½ëšC &ú,–é6'ŸnY2Ñmäƒ-!6 Ï.p–vZëÑgÅrG´t¿]yÛ)ç™^»˜ã]³)ßAF¬•Á}ªål¢Ú›_ÞÊsqX yuëÀß¾œE LÞϘz¨^žºOÕïÚ‹÷„‚¡ –pO™‡ˆ#GY;È^ôB¸+ZyxUuî׿%A¶a çÔ' jTÖe¿Ü$«!ÀµË–•n*r/{¨ûÕï£ ê³ªlg‚Õ\GeºOŒ.7o–›ŸÛé{œ¦xo2M gIû n/•þØ80” ‡ÒÉ95€ã›é!ârë 0SL†TØáSm=wˆÆÑDgpËñIæ8—Þý „…÷¢j-vR9a” áJ<¨Ü…ØgU›,Šy@ÛspámoA]U‡ƒÊsfŠ¼Åš“ïÀ˜^…“x¢°4ùÖFÈÝ3±Å⠈㢓|¥£ñÇ×쬬¢[èøayP/IŠª+¥hïÅ2ƒr†.ð±iîgІç`e˳q‘³ËߨÚàÊÚ¹; ¯¹³t¢³â¸YínÝä…d0kéü&ö*Ûfª+S+¬ÂO,öödÁåÖ—FAžÃ˜Á2—Ån9mÁ¬í9poYñç[Ù ‹¯>ŠÙ6—a¿…¤ ,Ò Â7WQ{Èu^MÁ±gÅaîZš@¬ˆËµº‡i¬î„Ÿppƒð’‚Ž$¹¾R” ‘³_”0—×»·?- ÷Ìú-՘ɰHWZuoͪ@¢ªq" l(!ŠFx%˜hä1”³,ò°[ ª|íàýÀûNkj¯ÙÝðM÷i؇‰~@t6jÀ"]o‘!~ ìoËÎTrD ê‘„ª›žμ~ø¢JX@ ™ò4ñpZ¶eœÒµƒÓ)AêÁ¢€ÅЋäi<Îü>¥g›•F&Å7û?À†¤×Vt0ÆÉ>Uš|0®ïå©0Îó€¥|1o)ÿÝ¡-¯îû‡ï¡'‰"›Á°$„²~9ѨlXÌ'®ÿŽ’”\˜Înj³ªðî1§²)ÊXÕÆ{1™<ËPŨÎbB}ÆFOS:dÿ–n:1¦d‘RÀpx;ô7ÈÈRÇ® c-â*G\ùJåºTRòDM’$Ó˜<YÆ$èâzÑÎJÐ<­EüX–†a¦²/hqaÊ]!`E0¶êìÊã™÷Céh,xÀr¨-C©ò5çtïÂm~FBíÊÐÏ"—J5ª÷“CC2Víñ\Îòd’˜ü'¡ÃYÀä~4(D†ù3—“Õ¹º,‡âÉØÃöÃvúÊ3Ïê|Vˆ!ІÉ0JÐ5›Äk=H¸εO½•x$°­š¤>íñ¤½Y>U:—g•Bê9§†J˜õdÄé‘XaÒ¨ˆþZöç3ó²BVîOôýEšÅÞ/}£9ÉåS\Q¬ª _<ž+i,ŒÀ3sr/.dcµLc¦l qqçšïÚt>ý1Í®ÜW‚èÙN6¡«i‹2ù@Ï¡—¥-šA•Khæ!@x+^ÏE†47)À¯¡™Vêˆz6þÐ~†Ü¢ê‚ýubÜÿz2} 3B$,uÑyýÈÛz»Àv¶ÛŒfq0“¥þã†mˆU%¾$ &µºÐýÍÙÉ«®°®|¨yåå(5oejç „ÍŠØ¡ê>UÚg[}Î@¿‘À¢Oé8ž(-ïnS¡©A“êÉL¶°v>S§wY\d™5µhÛ¦õ±œmÕvŽPñ²ª,rà7•J[ÎúY¤¹üA Éœþ³/Z[;nù«J9®³($nÚxqyÍš²„Å”##×ÑÜêH`¿aF@,â5+K'r_¸ª/ ÿ¹i°*1§ê#|m›ƒø\Ž+¢”ãÀïJC<9Ôt;†vA=¨0OókÝ™+FŽˆ:î±>—ܧy–M47$…|~¾çm?, Ý­¹¦¸ˆ¿. ŒÚ"<Ö׌¶s˜)÷6•Æ5«´æçï±@ã'Ÿúy1Qßh ´¶p•=וEa«±5Ô?µ¾†âó겪Kª/çò¥Lƒr¹jnçtž¿”ÙÚqùƒ´d£¿ÌVî;È &Að"ùtà /R(VwU 0ÛmªÜ7Û»"lªb¦* &í{? º* bªbNUПЩ ¸€UaS[¬ ZÀ:QÚTÛÞbœÊ𔟺ªA6l{S9tþ‡÷›ÿƒñœŽ endstream endobj 75 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Contents 76 0 R >> endobj 77 0 obj 2373 endobj 79 0 obj << /Type /Action /S /GoTo /D [75 0 R /XYZ 72.0 720.0 null] >> endobj 80 0 obj << /Type /Annot /Subtype /Link /Rect [ 437.0 688.764 479.0 697.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 79 0 R /H /I >> endobj 82 0 obj << /Type /Annot /Subtype /Link /Rect [ 136.94 494.556 178.94 503.556 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 79 0 R /H /I >> endobj 83 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 336.348 162.0 345.348 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 79 0 R /H /I >> endobj 84 0 obj << /Length 85 0 R /Filter /FlateDecode >> stream xœÅVMoÜ8 ½ûWè˜-õmõ–¶é"{È"ˆ±[ íÁ;ãi xìÔv6í¿/eylÏhìÉ^² –i=’â#)~ü­ÜÃXNÖ»è{/cÄp"t/Rš0I¹";Ò¯)ܮɂïWøð›pqOþŽÊÈïÑç¯øqCO«ëÀwÑíľû/nê`üñàöà =â¦C /C‰Wä>}Øú§×ê—Þ9ÿœu FŸàtPzw_Î8oÑ»$úí£" H²“Ö”И[÷ÇI²#Ÿ/˜~õ•$DWI@å ‡,`ÑÙƒ®#«1°ƒ3uÌšþLþH7é.ó‡:n)håöÇðúýŸ77Wï“ÕõÇÕÕ§ë»äî5ñ S†2Ö…Ö¡‚/œ›c€^Ù6},ZòoZ|sÌaa‘7 64qŽx—róè7!K§áÌ›éǪ̖ š˜Æ³ß–ÙÓTïÛ§´.WǬ^iÅü` Ž”ÕUý†x U±Á%þ?n\RèR^šèùlfÂÝrH±Œû²¹.ó6O Ò¥õRF3S%ŒµRôP<:ý £±¦ÖUŸÌ#?dͺÎÚ¼*»*Éz“IW <Æ[äÂ÷¹ý[Ç¢_¶÷y3Ùå+}L¾=6Ùf”—ÃrŸ«+E¿œOkŽž*ƒ•cN¹}.¯¹×6Ž•8짯&‘Øôÿ‘É‚³„mD`Ï lŒ×ièÌù6"¹XÀ M„†åÁQÅ!ì.Ëæo-©•û›(€ž‹>½®Ò&Û¥e›¯w£9ïã]´›~f×>ãžQŽ[Ž–}_ýHwE¶Z Ñ*³Æôà ö³g ©Ôïq—Û-†KàÝÏ%ƒé2çÎÿ›=7ß`݃bbäð²hªa<§3gÇÊT7¢uãYÀ2Ì›ƒIó€ÙnÜ<3ØI¼@¬ØŠ”Þ¦]Ž·t-“ÐÁù;›·Ñ/€*N endstream endobj 81 0 obj [ 80 0 R 82 0 R 83 0 R ] endobj 78 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 81 0 R /Contents 84 0 R >> endobj 85 0 obj 925 endobj 88 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 163.5 216.08 172.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 87 0 R /H /I >> endobj 90 0 obj << /Type /Action /S /GoTo /D [78 0 R /XYZ 72.0 720.0 null] >> endobj 91 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 151.5 196.65 160.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 90 0 R /H /I >> endobj 92 0 obj << /Length 93 0 R /Filter /FlateDecode >> stream xœÅX[SÛF~÷¯8Cb$VWK´a†€héP¶2i&æA¶× Ô–Ia:ýï=»«»V®ûBÍ`íëwÎ^Ž¿ 4 ø§°ÇÈÕa¾|ËiŒt0ìœdÙ ™ªnÁò±+ÆUèÅ‚ Oði ü2øò€/@Pày@Úê¸ðdp_³ÏÞW·OàqðÞœ\Y ð—D–©Ž‹ÃG5t6DÌü5|^ÜÝÞzþáø¿ <¿‡¡éÿC÷ 0—#}¤¶2Ì¥ ACŠPÄ^­rðó§Ð*†Â9ñìuŠT>‘ºKÍ侪ñþ¼Ž ¤¨N#ŸºÑ›ÊW†¬“Ef»?ÓéÔ¦ÿDáF.‚,˜iEˆ‚u5‰—å0« %4Û&]ôk‰g_é<+§ÏájUNfTª4­ÞF š”3ýÉ•ÛÎ0,U×L×µ ³fš%aôø®î cŒFýÂ¥í ­yÔBz çOÕ,Þ®µ…ÑztÒ²PQsU¥^ÊaPŽæGNL²¸öB¢é®j‘‘ëZ¶Ö5Z$JaiV–I¼VÒ ÷b¤Û£ÚJožÃì©ò’'UŒÃï4ê8FÚ¹ÐÕµÑt]bgG–SG»½5µ]Z*t£Å.™†£¢*BFD’=¤ÒͲ¡«†APÌ1;{ÙÐ^§5¢wÅ`$˜¡Œ&©ZH⮄ë0¶†¶¦šÆM ï¼Áz³¢io• «.–¼23Ë…¦}Õo§Ãƒ²8ˆè3MÃ5ŽrLátý’~[M»˜h¸™6-½;r'¹¶®D"©ëóZØÏ§2 –].f×Å7?_ÜLîo”ß?ã÷)ÿV.Ïýó÷çþ2bØWöåßgu¦½[8’zaµS²7PÎkå¶:;ƒëø6…ÛS~í9•ímLPÏ¢„B˜Bý¦nÙP­÷½“ÀŒ—§P2UâÖý‘°íâE¶1M³ ÉRY˜f;ÑÅqIÌ/w|œßDù8¡év•QÖo­lZ:–úˆU'UÍPW6+άFÝlhTꢺ_Ý< ˜-`0´ Ê6µ½—~MS »Ä’(Êa¤ ¥ˆ¹?EºníR¥ÂÑ‚.„²Ôuëà°«Kè,ÆÆ ù9_ÿ °îqµ°u1±!ᩞ—¯'|Ù~WÝ/Íä?HÉ[_Òéê:¾óûΑ´µgÚ-ç?iÏqV¥·‘´®™kÙ¼kµ‚÷~Ìé†Õ~€­˜m6Þ¹¶lÖ¦`¡ˆ+t\³^Ѭª/Ë'••ÓØ]?\†ó Iæë GqV㉲u°ËßKEŽ“ ]ã’ksÌã$+-',ë2 ?‹2ŸÖÖlÁ <®¦AÔ]YvÞ^U°Ð$áñØ1‹_9ÌB[9ÁsWÙ¦4Qšìœ#|Äì¬èB-Iו²Å–ýQé~ªT7ठËèz“UóêU¯ývˆ|}„骕33:¶)­E*AÇ4[èlh²ÓT8§kªÃMÏVt—”ˆfÏqòg9Ï’x‹,åœ;,†AôR‘…ê ÷nzx\c-‡Eйܲ²$r$&,GåbnŠpœr®2Oµy?ø@†sV endstream endobj 89 0 obj [ 88 0 R 91 0 R ] endobj 86 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 89 0 R /Contents 92 0 R >> endobj 93 0 obj 1612 endobj 95 0 obj << /Length 96 0 R /Filter /FlateDecode >> stream xœÅWQoÛ6~ׯ8xK€Z£(Q$ƒ­€ã¸Å†,]jaÃP÷A±éXƒ-%–¼Ô(úßw”dI–)ÇmÌ,šâÝ}ßw§#õh9@ðÛ×.)LWÖc9ç§àúåóÁñlÊ`å˜ÁR¯j èn„—bð—[ÞZ>âÍ4x²HÛ]n<¶nñõòâñ›\‡þ/n÷³À)·[¹É­Ýbg GúÖ²”­¼^‹a®¸v‚"5&b¥„ûrÁ Ü[—õÓ`^-wqÆTê…`Î(;ÿÁoÖ(8Hå KvE»"ƒÐ1«‚âìqÊ3ËKN¥›p¥ R <TÚÄgz½( †ïnnFÃ`tÕ¿ƒËÁx4†ÂAeæpצ£{”:˜PÊÛ☼WÙfC¶P°ŒÒ ’9„Ó,úWÁ,Ì»0UÜý£¦Yjï¨pϱ‰$è×/ü¾ÙÄè%‰w6ݪùÒfŽ’;¥jãmœ…Ÿv†ÒÌ!Ìö…£kÇ)iäŸsáVN“8F6jÖßñKÛ‚Ic„_^CËâh-¸®-ÃÂ- Ö÷›•гÂx†ËMíÇT6…ñ¼ÂC'`ýˆ¬¾"£Gxßv¥CˆïñÂï•J§ëè¡™\cmãΨG%b(Jáú¨Œgó²@ê™u^‰%º&«?9•êrªÆ%¹êŲ^]Ð}UÏD¶²–ËfÔ$=Å[=1]« ªž¸Û6n¢ó&§äXaSJ[¢•åÚ©´$£W𴈦 X„¨Kœdp§T Ó%›‚Ó˜¢ø:¡P–7ÄCϳ(}‘ëtØB’·™U³x{¦¾Ôã6÷°‘p·|ð†áæh­i#ŽÝ‡ºRø‚ÖÅ@Sõ¸QñT¥ú!X%³h¾Õ¼«fW”\!J·÷xÝ19—†P ŤÇ\A¸V°‰gj!¨žNôe»Ô—’ V¸} WË‚©Ê\—Ùv\‰ÑËmÃÄbrÞê3ÚÓ³oŠmñæ×kÃJ&»‚À“³8ZB/Sˆ§½¶Æàôä.vúÙöAÁÅC’f÷k•>.˜PÇL?ü<¼ß^÷ÿx7Þ¾áð¢V»+|ö„K.‡>ûòÚàwÎ#JȽX=©4ZUŠ‹ÆjÛÅ@¶Ò`ðûß|þÛÂ=dƒ+n´“tr~=§5D29û,n;9z£þúìÁz‡ù©”Ñ‚„ ëüoWUð;˶šÏ1f¤­‘™1s¾¹'0zjO`n[x¾Ç1Ì÷]}€Ý£™‚Ñ|®wácG†j ‰§]ŸìäI¬Nh«>%6žñ,嗛Р†Åå¶zK©_0–ïú6îuúM!K8è»¶êæ ÏÞFš¿õèïc[·S endstream endobj 94 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Contents 95 0 R >> endobj 96 0 obj 1065 endobj 98 0 obj << /Length 99 0 R /Filter /FlateDecode >> stream xœÅXëoÛ6ÿî¿‚È>,)j…"õ,¶i“(ÚnY¼ CÓŠEÇÚôp%¹n0ìßñ!Š–hÅØ‡®¬»#ïø»yd>Ï\„áÿœ˜ e1û¬d. ¢ùr=‡ø¨@ŠöQÎgé(øÈI@¬Ñï³r†Ñõìã'L…Ý Í åÛÙ±>Áß|}uÉÿ‚àf? ! An„6•2HC|(WaS_iU’œü…{LØ÷Û-ŽÑÃìÕbvþÆG.F‹U_´!‰‘˜ÿ#hQ §$<û„ogW‹Q*¿qÈFYäkkg:d5»{>‰Ì†Ê'éÒ‡¤`Ò)K ¼‘ØÁÏçGRáòbqñêâöjþáâý’ªZÁ¥À²8pÇšw¤‹_?ß›˜®Y‹Ú5C%`DÕ %(MÚä>i€»ÿ“-Ûxh1X ¤µkV²:[¢7ÛrÙfUÙéŽU;¾ÅqèªXÝ>–mòµSŒ-‹Æ¾Q¶ z„Jx^ê8÷Γ`¬€:ó`|`ߥäðQ¹¶¬òãKT™Ÿ(@Ýy¨>¡{Q?l V¶ JÊý–ä[Ö Aq}âø4ŒcFvУÂsq`Q»æÿ9bHÍ‹£}Ü0c¼—-óªaé¼rYàÃ`°’-[Òhâ:C>E§M[gåƒbRÖ,ëì¾ð"–T–Bä²öQ±€q8C» *EìÖÙr­gg}ºŒK·X7iY•%ˆYª:OgžàÀ‰ù ©«¶¾ðkcîë‘A©CBc‚U”/!pFž®ÔÔ‚šµÛºì'ÈXHÚpO ÄYÐ1"|c¥‡ì +G&-Y½€;єεd»Ä¨Áª`óq‰ÏÄd]í@iÇÕÚ^$RŒQ6J"\·M5ꆫžîÀjͬ™RÕåÔá0fÃÓô:1¾âtí9½ ` ‘…Ò8 "²LE'й‘ŒŠ'MT 8«SYËê"+Å®Pvú‰ÏS3Šx&ƒØ‚Y¹{p@ïR×ë·YÁžkn·V!Ý÷v™äy¯Q= žFÞDœE“²/tÂ}U]ófÖ'8±èq„.v‡¿†mÚUÆÝ¸‘I%êÒ¯X⠺ʃÚÊÄVÕ¯Í/ÑÐB_o^Nš@9ßU §uëÜ.“ǧ³r™oSÖ³©ÚæM'’ýb°ØºjÚçS+ëA(ÏZ3²÷qjSÕmo7i-¾ûtà;䦿‹PÞ UÙ :Ý*÷hßÖ©ÑDå©%$IÛ²bÓ:¿è'W¥ˆ« ³‚Lʶ7j¬ ¶Ÿ'æ-×—ÜZ69­Ö«ˆZ¤ýEeõh C0¬e•/÷R"›±¤÷¦V]aK–•©1¶: ÔGÐé…¯÷š„”íõˆ¦—Ã)ØlžýÅÌÁ¦ÙUujLHLXËÚÖWi8êÄ7Æ }½™ý Ï|ムendstream endobj 97 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Contents 98 0 R >> endobj 99 0 obj 1616 endobj 101 0 obj << /Length 102 0 R /Filter /FlateDecode >> stream xœÅXmoÛ6þî_Ad–µÂ½[7qMÛÄÆ†¡éÅ¢m­¶äHrÝ`ØßQ¤$J¢,²ˆÈ#ïîásÇ;&÷‚0üŠP4[ "æ*‘ã"b[ÔAk¤ÆZ‰]Ú€V#øÈM0X¢ßÉ£ËÁ—¯°! »îš+•'ƒkÍ¿XÁ/î_GÀý_\·£àQÏêĦÔfRiH,­mê+­Ê¡'¿{Aá6“¢à¾œsŒƒwÓÁé…ƒFÓy“´‰åÓ@ü£hºF_ŽipòM߯Ó^(_˜²^…ïú0¢êcŒIëLed=u&y¤ášËC8°}D »ŽØïK…óÑtôn4?Ž®ÆÃ‹›OWÃÉçñ:K[µ8–ë ]ƒ­[J½ŽŇ*/7¼ØfI5+–¼FaÞ…y=OàxÕ8/²8YT³Yše<ߤI¤ ‹Ô`sçI£– ;%›Pèö­ Ÿqš |Ãgñ<ž…bfUD{¢fáÃQ]iá’'<‹gèb›”¦*Ýý±õ‰å€À# Ää!)•b`pJˆÀmŒi•¡Îñ\×°­ây(γt=GíÓ6¹¨ž$*D=à\ñ©91ˆa“öw <[ñ°áûùƳýú%Ú•:t]ËᲡ’—º£l±]ó¤ÈQ˜Dè·pµåù~ì"z±(cAÀv©ÞÅ&Fí‘HriV” •ů•p·Lå=óÊ«µÁ•¬æâr'Ï6/BÍ^XoŒø†'ZÍ«q ›Ûª#„ëͪé¦'” ÉÁàê;L%Çí¾×úùöøH > endobj 102 0 obj 1341 endobj 104 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 438.556 162.0 447.556 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 79 0 R /H /I >> endobj 106 0 obj << /Length 107 0 R /Filter /FlateDecode >> stream xœÅUKOÛ@¾ûWŒèªz³¿¶j‘DÅ+$RÀÁÄë`ÉqBl¨êïlüˆã8Ð^hrðxw¾ï›™? (þMýp%‡ÑÄx,Ö¸„S,Ù0‹p&PØ6ÄÚ«fðÒÂGî„Æü4ƒÂ‰qs‡›P, Ú¤[‚F¿¦¯wè‡ëSC£sl£0 W)²éÁ¥þqNàf÷¨;ìt=ó¢{Þ3¯/ÏÍÁUïpï†?ŒÞpí<‚ñÿpžþZ XS—»¤Qé%Zäk¸’é­¸(BñÌYs3.n Š®b¢õÖ‹ü¡âÛëë \!ÞZ}ÝZÊNÙFµvuÙ<Œåé^µõQ'?Ëín%ø™ï§ v‹™MÒª“©É,ö3Å:J²H¢øv/?{“S"Š?‡å¤ß÷áâôlÓQð†cSýóç6~ËÚäÿôíðlÐ?3¯.Óëš_W¦YÞ@øeyBò#~ô{“×v¼ûtޱèx<Übk ¤àYÄÕÝà2‘cQ  †j”¥%|£‹PŒQI¨ƒrÌ“9òbš(ò¾".±„’°»TSÜ¿¾©è0âQŽŒÒþ7E©›Ì¦Ôò¼Ø{©YM;/Êž|m¿y\®‡–p¥´DÁq˜‚Ânö JóÙŸª—iåQ2#oƒšQPÌ„ôœÑ4I05œ™ÎÔhk€LjLÃE MF”–V2ÍJÓ¯ÅåËJ¹\ÑDa4òë‹átÞ’…qô¬*—ê2”~¯3õ¥åÒq§µŸ€šÏQó¨A0ŠÓÇØŒ’e Ë„˜¹Ã$?dp¯ ÆXÒXÑܶˆ”ûP×e tãtZMÃÕ0Òº”HËÒ©}Ñg‘ÄÚt]"·Ç$¨K\îHOºU‹gªj̶(pQ†\ÒusH™p3ñ'Ê çÓÉ;̓­·ÉØ,~5@œ&ˆS‹8¬6›èå0۪ȅcžlüÄ´H«—L%)¶©¥®oü_0ƒ endstream endobj 105 0 obj [ 104 0 R ] endobj 103 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 105 0 R /Contents 106 0 R >> endobj 107 0 obj 773 endobj 109 0 obj << /Type /Action /S /GoTo /D [94 0 R /XYZ 72.0 720.0 null] >> endobj 110 0 obj << /Type /Annot /Subtype /Link /Rect [ 450.0 249.644 540.0 258.644 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 109 0 R /H /I >> endobj 112 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 237.644 150.0 246.644 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 109 0 R /H /I >> endobj 114 0 obj << /Type /Annot /Subtype /Link /Rect [ 220.876 97.484 358.519 106.484 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 113 0 R /H /I >> endobj 115 0 obj << /Length 116 0 R /Filter /FlateDecode >> stream xœÅÉŽÜ6ö^_Aä0h7ºdŠÔ 8gà è£{&‡8UÕ¥±Š*Kª^þ~‘”D©“‹cê=ŠoáÛÉþº †ÿ[ñ“æíO›¯z-D)A4ÑKq‚Â( 1:! Ǩ»€ ü¨Mѯ¾Á蟛ß~‡„àiƒ§ì$ñÝæ“#_|Áß\¾« É_¢Á§±R’ßHjªÖ`E1Ÿjm6ý«¸*P)§~•ÂV'ì7ŠV÷Û ÇèaóãýæíO1 1º/mЦV‚ŒäâA÷'ôÛ%o~G÷?o>ÜÏ\ùM6ó¢mªƒW3Œq8:“ôlªÏ¤Žt[œ˜:”ÇQ†Hà$û3Eðwïÿu{ûáý=RtfwÒ £BhFçtŸ I§díë¦c¨@‡¢/v€û†s¶ï«†§£0À9>‰âóÓ…h–“äAfyž†Ú8w/¼/žÂÜ#,'AŒi¤µ>TVszXìÙþö…½ A°ŸH£È#BÛcQ¯âu.jEJîQµmÓ.Š ÄwšþŽZÖ]êþu[‡QcLÒXQ¿k.'Æûü€þ[ÔÖ-ë 2ÃÂ'Oó<öh<‹å'3Šwè ÚBRtµkššÜ.”uñ`±Šª}ÑWÜY{:²þÈZ»Ð7îª^ÔwYKEÞ¥…—LI$P¦g˜FÃìà4¼„Ž…y÷ËcÈ-‚C¨ú]_ô—ÎâMiáÞÝhj•ÆÏE×Éú¤ñÊa²?üÁý¨&ýQÔ ç[Qöjèñµ^Õ×AiÑØ¡»‘µLÉA¿–=Âôç­+'›”—v˜½â ]]T PD@Z3¹hŒ!0Y·Ä ¤§OCÜ ÐTÉ|†ëyš@kÄÔ£âû_î>-G$‰8‹Us›‡^¥L'Vž*•ú“²ç=;VÛa1¡hŽ=¢‡XÞòW®†4Ì&¤ºfŠ…e© Ì0ýÃ0yXéýËye6ƒ!‡Ï4 =L£…ì` ÔÆ’0ÄKkC#[¢BDš¤0MEâ´5ż±DüÅÀͤ#“Ì"‰B0$I’çnžóã¬GÍ€8MÁ 0ωô!”nM hª¶R»ôä ÅÎÂC¨ûZoK°F½U, ¬¨2_ÿ¡ÆiaP>ÉôŒ÷á¹8k{õóݺiNA¨æ˜Pýºà”ô½qÏ竦T3!£ïâo9{b]uz+ï>¿ùüf~ZqÓK€»í½gŸ8ØhzýÐQ¤^a²ásWúP– |·–q /a&*N¹½LƒR-˜ª§PYñزSó(ãYá²g Hïð¬«Î2%EfŽŸI·B WžÕ‚¬üd½PÐÔwb#YzuëqI†'$R­E»¦>OcŽqP,^¨Rý²$‹ Ìæö&@÷ú&p㉙.,1é‘)ƒÊîÃx,ë‡D–G<šsÅÄ£&ûºÜ…¢lr\øô|/4æ”ÆókéC̽Û<^ŒC Ê$˜b’Z/^ ò<ÈÓI°c½Õ}ZJU —UÛÙMýEÅÕ[ŽZq¦TB(dÅði‹&N"êÑxªëQHãp•ÑEVéÙYWr¦ÿ<ƒfKbÛÕé?'k¤Ö¥¹ÕÈh / ÷<2Ÿá’?fl|Áž¡øtn‰`P—Ò8ÆAFyša]oá2$FkvX«¤qJ‚ŒÄy–¥ÎÃŽç¥Y44ÝüÅt#‚JŒà 5“É_ç¹Ø®§ið¢|åp‡9².Öi÷ïWÕO\…"(X™>õ8´L5Öâ ÑãµE‹R·¬8¼Ø…é+›( b®M±G’%»>줥·§ây[¶Œm­ÙºëEö$ƒ›Ü*CÅkìG‹9¬íbÅG'¶ˆ¼|Ùm½;äNW˜4óM(«¨ K2º1˜žÍânÛû/LÇ ?ºüHTb lÎç¦í/¼ê_,§Æ€íÅn}`œµÕÞà{ñ*w9[VÜ«Ë肦–dy ªúÚŒð4ü)dd˜eFÖ‘ns½u„î1„ÜŽApd2—¸¸!ƒKÜ—Aû¡¦ˆ«³ˆaÞÀ.s͹1Ë¿À}Úüâô endstream endobj 111 0 obj [ 110 0 R 112 0 R 114 0 R ] endobj 108 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 111 0 R /Contents 115 0 R >> endobj 116 0 obj 2088 endobj 113 0 obj << /Type /Action /S /GoTo /D [117 0 R /XYZ 72.0 720.0 null] >> endobj 118 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 263.548 162.0 272.548 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 79 0 R /H /I >> endobj 120 0 obj << /Type /Action /S /GoTo /D [108 0 R /XYZ 72.0 720.0 null] >> endobj 121 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 251.548 180.0 260.548 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 120 0 R /H /I >> endobj 122 0 obj << /Length 123 0 R /Filter /FlateDecode >> stream xœÅVKsÛ6¾óWà({BOìÍN”ÖDŽkNÒ™8J‚,NùI*¶úë» !zXv/.¥îÜýö ƒŠb xQH-æ×$[koV'óH‰ÄŠ0ÐÉNîªhôýk)7DB*”ÚŠ¦Mšd¨…>‰*–<Œ"Á­¨xž pd¢rÚ }Ðõ¬JW&#'k•RÌBAÀM‹/+ ‰¶y¦X¡Q¹èiS$þ~q´;iÑÓÛÒhS=7Õ‹²ì>èyZ[ÕýZ2ØNšdšÔ*¤jˆ› ¬¨t³®Š´¸9Ð U74ø°Vã{Á1®` "8F“«Oާ]”ŽÌÒ> endobj 123 0 obj 943 endobj 125 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 596.764 162.0 605.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 79 0 R /H /I >> endobj 127 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 584.764 180.0 593.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 120 0 R /H /I >> endobj 128 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 532.028 234.0 541.028 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 109 0 R /H /I >> endobj 129 0 obj << /Length 130 0 R /Filter /FlateDecode >> stream xœÅVOs›8¿ó)tt2kEB à°q¶ÉÎîd:Í„Nm ˆ˜-°Û~û>!Œ„Ìæ’ÚÞ{Òïý¾9ø¯Õ#ˆ\”ìœo½Œ¢ÀEŒ÷"Ÿ#êa×G;ÔÓ>*Ô-‹pO<ô% ¶è£S:ýí|ú‡)"øîsuøÁ¹·ì«òêö zr®cçêÖG” 83)r)#ŸâqbæFêç¢x‡>­.ßÞÜn>ÜÅë·›xs½y¸¹¼ø‚â›x£îoé~ä”5p|VìÍ´ $Z‘:*ú:ôO­U“Ú9ý\tŠŸˆíҸίj|¹Ä G¥¥Ñb)_9e“**ÛC0Ñy0^¨ÚÔW¡p®cAýïÏ7(ÖQÙ·]‚‡þ&œŽ¯_¦2‡¢]§¢¢‘—S0sÀ`ëÝ?wS€ç->¯’ª,eÒÊt0Ø|¾˜jðù Mòp /^ÝBña.B8§£Dq¨®(ÓÀM–u¢ëŸCw˜â€)J]èõ9_2Ù!}Գݦ4ºÞK5¦y3UÚ—C¥œbŸ†*ÖHkymЦZ4°§[ñ…Úåýÿþ¹Ýfƒ5ì…¡V÷®jO ®nµ#m´¾ëQ/ŠÂÀ‚œ“% ÜÇŒ…„ºÄÛ¼Ahí©Å¹:Š:…4û4/[Y¦Ðƒ¤­ ‰$/òV´ú{UÍË'K·[Ã<å“7R-ÁIrƦ>ÿu÷p·%#€ ìM±v4†å8ÊZ$m~”vpÍ6¯lDkea+í”ì×gªòÍ4ò£GY(”˱‡VEUíÿ0¬(SÃ<ÊDiUfèêgOY™4+æB#êÍh˜æ¾˜ÿ zÁïE_ Ë1÷ü¾BçÚÎg{®Äô9ƃ}]óÔÊ\Sí,.y]ü4|Ríö…üag~®”a4¶·Ǽ:Ôƒqôú¡ÐäW)÷3}Ù GlçàPõìP ìQÙà_WOµØíD›'6f »FÑä⨱€b¦ö‘Z;“Øž56‚®ð¸?Åšè¶Õ¡H¶”Ç™´2¥Ë†K•ÑîCd•ʽì:K³ÝjRž¦»ô˜KÙ@Î&^ Kíà¦fMóh>©êšÒ8Õ+3ÿƒóÆø“ ÛÏS!‡Ó½Ì(;›‚^ûbî)¼&(´Ð‚6Ê%¬±ªlP"ŠB¦ØzÝ;¿(éçä endstream endobj 126 0 obj [ 125 0 R 127 0 R 128 0 R ] endobj 124 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 126 0 R /Contents 129 0 R >> endobj 130 0 obj 922 endobj 132 0 obj << /Type /Annot /Subtype /Link /Rect [ 498.0 571.292 540.0 580.292 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 79 0 R /H /I >> endobj 134 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 213.612 162.0 222.612 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 79 0 R /H /I >> endobj 135 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 201.612 180.0 210.612 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 120 0 R /H /I >> endobj 136 0 obj << /Length 137 0 R /Filter /FlateDecode >> stream xœÅWQoÛ6~ׯ¸§!)fŽ)Q°]š-‚d ì¡éƒlÓ¶:Yr$¹‰ÿýŽ"eÉ–ì¤{È ⑼ãwwß™GÅß‘ùHåÃlí=º9Òº© &ˆÀÜ8€Ôìê üf„» +øÛË< z_¾ââ(*¯îno¯¯&£¿îîn®?€Uß+!VâÑ4d}íß—ÇûÃ3ûa–æ¥.!NSØäyªç0«x—fy–éY•äYÙx <ŒPEÑdhM~ÜfµR£s:X¡"‹”’Ìk¼Ëªø¹QT‡)N"î£-¤O­2OJ‡sdñ÷¢EûJðS¾1ãý×q¿ýÕËx™ï#GF¦ØdérV$›®»CIf"$—J îâ>Y%%\‚p±pñrbëP³Á䯭5©±b'An¦ZÅ•®âï;©ÖõMÏ0ÇVH²*ß+6›M½]sBH²¥“NçÇ\u(ÏÆ'ˆŽ”ž’j¿Z,§ŽSŒpnxÇÅ€…ÉÉ•<§GŽdàEôhÓ§ìËíZg•£æ5˳ÑIÔ,ò 3Ç+®,ß~º9 )|N0‰™ùөܺ( Ÿ~«ù+½Ì¡Ðëü»ž“—9ïÓˆ(SÞ’3{Ìõs¼Þ¤º> endobj 137 0 obj 1164 endobj 139 0 obj << /Type /Action /S /GoTo /D [72 0 R /XYZ 72.0 720.0 null] >> endobj 140 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 678.764 195.53 687.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 139 0 R /H /I >> endobj 142 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 666.764 251.63 675.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 113 0 R /H /I >> endobj 143 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 549.292 162.0 558.292 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 79 0 R /H /I >> endobj 144 0 obj << /Type /Action /S /GoTo /D [131 0 R /XYZ 72.0 720.0 null] >> endobj 145 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 537.292 222.0 546.292 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 144 0 R /H /I >> endobj 146 0 obj << /Length 147 0 R /Filter /FlateDecode >> stream xœÅUMsÚ0½ûWì2µªÙÇ4¥ô@‡™’ ੱÁ“ðï»FƲ $Í…ÂAÒÊzûö½•½uPü»Õ Cóµ³­c $1¨Cþ˜G¸k¨ç>¤ÕS­ ?Îp0ádNæPøé<>ãf ¼8ôîpxâŒ[ù«zõü–η©óõ‡ŒÂta%òD/ C@@«‡é{ßï'w¿G£áÝ´ÿ Ó_ÎpÚ)E0þJw8 ’Krbòá´01Œ j+­õ¯Gƒj¦†œ/’¢–mSêú{Õä—­•#$èX*ÄE+¯,Ù«ÜM1H] (¥¬SÓÁYY×dJº],Ô\«fû¦6 í (‘æÎŸ×‰¾iü›X-¢]ªÝ8ÒÑ,*ÕÍYÕÛãŸÇž¹›> endobj 147 0 obj 580 endobj 149 0 obj << /Length 150 0 R /Filter /FlateDecode >> stream xœÅYmoÛ6þî_AdÀÖ1CRoÔ°È–tÈÐuëlš}-:ÖjK®$Ï͆ý÷EŠ’%JJú¡kêHëîž{åQý0£ˆÀß¹|!CËíìƒÞ£(`Èñõ–ç#êbæ¡-Ò´‡6ò­Áj ê% Öè·Y:#èûÙ»?àÇ`8ÌHW\Å|3{ÛÒ/!Ÿ]CÙÿ‚àíqàNl*nGíÁŽ$Úh·é§’ªHN=A‘±;EÃý|Ê ºŸ}{;;{å!JÐíªIÚÀÌY(ÿ0t»Eïž9Þó?Ðí³«Û^(?³ËzQ”º1¢Ê !ôȦ*²¶I™ô&Ú e”Å.G,ÄÄ÷äû\1¼º~s9¿¼¸½øöâæ )VÃ@‚ÝôznØg½c,è2¸c èüu¶ŒJ"Ge´ˆ ²ÅŸbY¢rgûû5Jʯ ”‚¸¶"°XáRLB‚}mÄ>]–I–Ö<ÃóCìQ†Õ»yHËècÍZ”…PoÌeD§Í*Iãym@×Ìï3 Z<ïȧë¿,Û‚ŠrbÑòe¶“Nˆ6#ú˜kÁ'ò<ËwƒÚ·`D/ÏQ.Šý¦œv:e&¤uuÀ.òûýV¤e¢4F¿F›½(†AC¨ಋ¸Þ€“zÙN‰oa»è¥^–C>ež¤÷§(iVÕNÑ£t´£ u„0Nm.µcë1] {‘Š<Ú$‹-²l#¢£K±ŠÀÏ*3TN ÔÄ€j‘ñb^>ì&œÔeº@ïÅÃ!ËcTQ»ã±1V<]âÌupàxð‹¯“èRË<ÙµÛ²­»2Ÿc—ŸãûƒíÕ–¸Ðhû¼è9òì£g›ê )Ì:JŽŠ¿„Yš«7t[¨—÷ðrà Yièb'–É*E`£ÙMr8GãPö%ÙûfLZïŒ׫G qÁ Š€Ø2¸8épÉBKL£ÊùŠ4ÎÕË•!e›2‹Zå©Ù> }Y9²{ÔãqÙÄ`¢bPä¢ÜçicY¹N lV?ÉžuHЯޤ1õl6fQˆ(_®[b“žÇž(, Vöí#œ‘D6weÆ25á 1[‹‡†V*õb“e³RF1"„)ׇÁƒ«`Û2KS½h¢Q ÷#⎉jÀ¬àð6‹¨![E­wªL«mW©Ö1ÈR¥a€}˜9'®ÆÔÙê:á{ƒà°Îzƒ$ÄWzá˜EN"ÀV%ÆŠv+-«ˆUë*^e§…‚tß ,šjÎÓ± £lLH "1@Ň½OÕ¢Á¿ù$`¸Ð¤àdf~hÑ¥¸—Ã)Eý1öZ=ŒX5µ6®V² ب(W7FŒôW-àŽ¹z8<„×ú¯W–«;m¹DÅ~¹".`Ž*QÝѤ¹«$‡>`jg•í­ƒãpÌ ƒfzJhuÊÀ]qô”+¸GDÁ"bª˜B`ðÀ>³0êÕ©s„¤Ÿú$„üâPj‘56(QŒ±Ý‘êõ¤=`4ȶQ¹\«ŒRºÿW´I¶)2ŸB{[0Ì^6‡N¥•CÂ1þÆ–¼M¼Hb‘‹›½VðÓlØFgnÉ'ttW¾šÃQ¬•Wd•Žf¿!G.×4ÄÔÁDZØ×2qGó<à¦àÄZ{RtqX&Ž™Ëdî2‹¤Ñ|ãþk­ò'„Á Þœ»º> ƒ´aíû¢>p½Q%ÉD¸€¯ÆÐ'‡ËaÞ÷â%k!ôˆ½'úÉ7ÌiÉÝ,5é­&Im³&éë2²TÏ*^ZH=ÔÕ£èª|NÍR§ŒYz›U³ Zäb)ÒRÞ:õ†™âÌNkÔRIÑb7s‰ÔÂÖ «Žzõ—üÔ¼•ÆV”é~»¹Å+0%{E]1øqGâ¶Ì듃–˨Þô³à„ú× -Ö‹ëZUšjªŠj¥]U’åZ]ˆxÿÓÇÁ‹ {H‹åÐ*Ž-¯|7Xm¾‹CWçèóN~¿"cÜò+I™ïÁ6°´%wŠä>…ƒQÄøžàB˜a¨”m ¿}Œ¶»Msi°}Lp=˜G¡eó0ÐHîŽ'Ùù*϶syqG_Ý=;‰!¹OÐI*¢H¶@éêq÷}½}(>lîž÷½í‚ûŽ5½> endobj 150 0 obj 1950 endobj 152 0 obj << /Length 153 0 R /Filter /FlateDecode >> stream xœÅkoÛ6ð»CÄ,E½¬€»¤…‹´XcCW÷-щ=\INêýúEJÔƒvÛ}蜺;ñÞÇ»S¾Ì,Dào.~HQ”;(š…|ŠlO‘\Y¦.Ê‚]”ŠS=€¶<ä!Ð_³|FÐÛÙ§Ïð2Fžgd,®a¾›Ýöô‹7ä§ëï[`[ô±àv˜Ÿúx”›†Û–4 HAâUªÂ¦žRª¥qòyÔ(¢m"æ (sžr‚îg¯W³—o\d´Úê¢õm à€†âGÑ*CŸ^ØþÙg´z7»^MRù“C6É¢ÐÝ9¦CVBˆ5ð©É¬¯|’.}`—Nbàˆ†˜x®8H†å‡åj¹¸Yþ}=¿Z¬¯w×óÕÇ?®‘”ÒñZ½L Ž3•²¦Ô3„§Ð2Oê„¥É?¼B ŬfVqTvý¾Á~ÇÂ$$ Ç“rÞìó¨Nмå9*/Ä®„¡o©PÝòš}mCƒ2‹xØ¥!¶¯*5¿‘§c8™tþÍ[çæÂ9ôë#? i$Îv¨Ióo¯PÉ«}ZÛUËv±gCY¸ž%¹åý>ãy ±Îcô'K÷¼jå€ß×=‚=‸8ƒÉ†³` LyW¡9XÓ‰iñ&&-\´ŽÞEG·0kˆåsQÆ-Z²M‘vªx^ÔI~?åÊ‹ç|lи|…#>9²aÑãœç1FW|Ë £kpïIÄ[tË7ôŸã‘|ãÐÅ4tñlWŠï'xhÉäèuZKt´|-bÁÐ\¿)û‡åÍñä+J¶Ç]Ž˜¸€ˆÕ5Ïv5Ú²$­.PQ¢ÂÆç¤âøÛEK©ƒÛ#Äñ©èŠWQ™ìú×ÛØÒœ;D:¾j Ë­H.xA¡¦déI¤MŸ¦T;%Û„÷H›ƒ†ßËó°åزŸLMø¾Û>%DÛñÀ*@Uk„¥%gqÏä ç¹ÆôEŠ/zL=iÕàü¶,2+öù´x©gµ~„ª,„ŠaÍWçJ[ªÌ{°*•ŽTÎXÌ5&[‚=ò¥÷þ¡‡´Ú±&ÉRhÏöõLŒ¨öQÄy\õŒ†"6kj ÉßEÖšåá Í¡„uÖ$®’&‘QÎ$Qª—ðV ½ŽPòz_æZ|­ùXÏ‚]Ê"^EêF*ñ^ïœîõpõr:ÅD4w"WÍ2MªUuQ½KrtÞóxZBÐnDÅ·!ÛA“„Ifè§6 `9ðÂÀ  ìÇ”©À5TÕ«¦2#Üà:À z´ëR+Ä–-ö;4ØsªëRÛ?ÅÚY })ëR`UrŸ³´Ò/[ˆ—¥>UtqhÇ­€£´ú’Λƒ¸¥­t Ù(¥C¸)ÙÈdÌjöÕóT…„v­W¤ Dl_5S »²Ø¤<ûŽ1aC—¤vH`*új~eÙ.ÕûŒi“³SöFßVÑ©š3ø#~XǺlT2:¹†[Ý Ðev€4¬Ï ¢(*½|ÿñîÖ¤×v&zí FeÎ8B¯^¡ß‹l—¤¢ Ü,Þ¿¾Z õ‹_.ß¡šG  ù ë³Ëñj,»ãÐ ¯ŠÝü†?ñ½)ÊÌ(ÀGކh­ çÂq ~¬\2èY¿y1E¾:€Á"Ôìÿ’WŒœ¿Ù1ס£s?è˜ëLõœtÌóF èÛ÷×…}Ò—`Tª5ï.½Ýò¨®Níyô›ºÄ¢Ô|VøÃ‘ÔàýMOàQQÂÜØy¬>Q.¾ný&ImÇð`[¹PøÓ¡ÝÐö9´%}¢n!µÍùz˜¾ßFÞ¶‹Ø1ú°¦®ÔŠ#±ˆ žŠô‰kËÉ÷Ù†——CÁòK£E«$îIá2q=¹= b^ó2Kr±†¶é©mã._ôs&mÎ K–Kó02ÐýÅÇm7Ú=ÁK“GÞbßãN Ö@¥§ÚÂ>ã´E£"V_ŸaiúÃL9¯a©zìóíxÙ˜Yu‡xáõYgÝrÛûŸÔíì_›²&ú endstream endobj 151 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Contents 152 0 R >> endobj 153 0 obj 1545 endobj 87 0 obj << /Type /Action /S /GoTo /D [154 0 R /XYZ 72.0 720.0 null] >> endobj 155 0 obj << /Type /Action /S /GoTo /D [151 0 R /XYZ 72.0 720.0 null] >> endobj 156 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 215.548 270.0 224.548 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 155 0 R /H /I >> endobj 158 0 obj << /Length 159 0 R /Filter /FlateDecode >> stream xœÅWYoã6~ׯàcÄ,/‘bpo±E°ho‹b³ŠMÇÂÊ’#)ɺ¿~‡uØ’÷%u€hx|ss8|ò("ð7±¥Zl¼'7G‘bˆK7åKDf>Ú Gû(¶»:«)øT›€X£¿½Ä#èwïËWX\"€W²+ÁwÞmG¾]!ï.¿«§ìÑàv? Š)|›Í«9˜©٥عÍ}+®Y)W}*EZȰSœºï'œ GïjîýôÁG” ùªMZÅaLÛCó úrÆÈùW4ÿÛÍ{¡|g—õ¢he7Æ€êÕ€B÷l*#«œM•IŸÂ©ŒðÓ˜Hßî*ÀÅõìÃôóÍ|r=O¯¦w³ÉüŸ?g¨bÒ@©¦˜p€q¦ûLîSFÆh¾6hiVás\ eX„anP±Û¿=ç jÀœ5f²böW˜EáCÜ`Ž»KjìÓ@kEu Ÿ šƒÜ1§iŽ€ö+Ø4Ù¡of÷šfK”™mfr“QòˆBôÆÑ²5é!\|›˜d‰ÒªEÈCLq,@-Mï ûíæîöæ¨zœpÈ­è¥Y#P÷@Tcˆ‹¤¯úØOGÄq5‚Äo‡€2‰/ Ì>&Q…1*cqTeû\i-xÐÓtD¢XÛ|QœV°k“/²h[Di2vª5fJ0ÑɳY{Ž&L@g/eî4Càš.ÖQÞÝXåg;Ó]…d_vV’–^„qÜÙ£¡º‰qŽ9q* ˆ*_GÿšI¢“b,û¹RcüZÂdy‚z\XÈðv‹4IÌ¢8AÆàmº~[›ƒÚdë ¥àºUa…h6ØNÐã@ ­¶éÆ¡ñàv’wñ±çj®§>´ 3¨ç…Ép§Š=¤s‰¥ „H¡\ÉŸG“Û‚$ÁÄJó)wçÐ&0¥ÃU§¸¥Óv¹Lßj½Él;læÆŸÛŠAS*ŒUFØô²U>q$GÕ'©Ü¾¥$ƒk‚ {uéAÿù ÊGØÕÞÍÞÒJ°¡ Á‰™d· ®bûF•&{€$4Ag¯QéÇj°_L3¨*RIæ[³ˆV»viÝn9D”ÛH¸Aú*œxˆ¤ÄÊÖ}Æè˜m¡æ^6ƒÒõ6Ô£ILÆ“ís¶MóÖ“eý{®yhwåÑãPTlòïGòÒ,O¸5¡%Å>+âšžÙ÷p³M>varàÀö`’ ç ÷»?ËM±B®èígòúy³ËŸâûó~ÝäÃ,ùÕÁ@”cz;NƒÂÁG…ûµÜÿ¶¿ó1“ÜV×)NW+8BpU_íÆz! Å¾ÚŽ> endobj 159 0 obj 1137 endobj 161 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 203.548 270.0 212.548 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 155 0 R /H /I >> endobj 163 0 obj << /Length 164 0 R /Filter /FlateDecode >> stream xœÅV[oÛ6~÷¯8oIŒš£HI” l€Ód›‹,h£C×ôA–蚘.ŽDÇó~ýŽ$êbGv2 È쑇çò+ù8²€âR~„Ï LF†f`À]Cr\°lÂHÀ¬ˆK®Þ‚5+üÔL¸XÁï£tDá—Ñ×oxE툪«„ïGw=ûå }sû}Übÿ ‚»ý,&ÈAn*i^ÓR+*b6ó­µÖË\ý= Šv˜èpP Ü·3Náûèr>úág, óeW´‚#…xÌ/ æ |=gÖÅ7˜]ÏŸ¥òCö,‹¥íÖ„ŽYõ(¥ÖžOUf…ñ©vé6HdíÔ@ l˜O¨ë”ü^-0žÝÎæ³éÍìë«ÉÕt>½œÞ_Oæ_>]ß¡ÖÔÊ3Œ -JŒ=×ôÀ˜8`§àF²%q *UZ±ú[F:X…½[Ë¢qG ¸c[„úUºµÊÏA®‚E܆àxä\Ÿ8–çûÂòÑx#aŽOÅÏçÄ£ ÕùN-6…øU^¼„«’o»R¸Èå:—…L5r.v ôYa–#m¥‘J¿ÃŸr·Íòˆ¼ì F‹ÉFg˜A5«q@åT£ÀðDz]âpáû67Y¹Ý¼Â¢°‰_^p«»’E˜«µVYz*~–ï&lŠ14öæ+UÀpFœ?™üµ„ÞÙfÅh5ûíJ¦òIæ-᨟–çê`›p!tI›49›èSuÀ9E}œbéñ}CàC¬ŽöeÖÁÚU[1 ¡DÑóëæ ÁÊŽ¶¬û« HÏ4ÊÙŒx¨?ÎeíÚýBÊ´Ýô ¶c@xò]§ h—‘Ô2OTÚçî4ë:•õ¦I%i)³´ÇtÃÚ忤[›h÷mÏ`{ ‚ñƒ@”ºöºßzS¬~–ê J†ª} Gؾpj’Þ(²÷*ÂuÙqm‹R×µùÁæd;”B‚Zbv,næ‰Ö2Yë^’Ej¹«P>UÓ §Gã¶M¶ ‡Ædëü&ä²ÊÎB®‚'•mòWŒ,dâ0Ó5côú¯ YÇÝèšœ»Äãåèå¶©{ó{8/¤^±l¿©Æð>ÙñÃÅó r á°Ê2bB.=ŠãXgÇT5®ø=ûÿ¸×Tûv‹ñ€ÿXÑîÃùûß¾ÜßÝ ¶ép´^N¸ÍñÀÅ´SÛ\~ÓåR†åp½ÜµO¢îERs°¹¬ê‰_=IžUð½×Õé±Z½¹^xÝØž· ^Ò¬Ñy/%Lã"éP‡øûw õEéàpÜö=‡›Û÷6Ó]ï Ý‚Ž+µP^½æúT9&'Ý&åÌ CYݧA·®Ç¬Ùõ®LC韮s• C¼ë“²'UÜP2 6EOΙvfÉ:Ðj¡b¥{Z¶J¯ºÝ¯AËÇJÏz¶?dIÒŒ¿=ï…à=V8éünôI¸i endstream endobj 162 0 obj [ 161 0 R ] endobj 160 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 162 0 R /Contents 163 0 R >> endobj 164 0 obj 1111 endobj 166 0 obj << /Type /Action /S /GoTo /D [160 0 R /XYZ 72.0 720.0 null] >> endobj 167 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 515.292 288.0 524.292 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 166 0 R /H /I >> endobj 169 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 503.292 258.0 512.292 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 87 0 R /H /I >> endobj 170 0 obj << /Length 171 0 R /Filter /FlateDecode >> stream xœÅV]oÚ0}ϯðc‹×ù°©F'¦©ZE¤j«úQCÄh£¿~Nœ‡u•&¹¾Î½÷œ{ [ ¤¾vùð9ÑÚÚÖ> |¨W»\`¬Am» -ß2 ÒXê¡_RÆ åщʭ´FýÔYµ©Áéç (ÔbB&¤î°/Z|xÎj¾AÖ0eƒ£¼pËzS,k“qXO¬I–È$L“·P&y®M‰RÂUR´v(¥Xo¤ˆ Wf,Š} 7­K®D»Ðݺ½WhNâAŠB˜»=hq(ÃyX[6¢ÉÑãD‘3œâ<ŸÍ¾X™dòLæÐÓ¤Q™ïÌÀÄhب‘š='è´éo"¶;ôŠl*Á©³ÈbÔ!ŠT*è3ª6Ó*Ïx±Q9—ùá¨ÈVª²ç@__ÛçzÅbîSÙ…7:+xUÀ÷>\ਸ~Œ*UºáV`L¡‹™º1×y'¿"±)5ªÃ‘È}¥çbP6 ;¦>drôͽ¨æéA^*¼µÅn—ïÚe­%½•Eù>“¢ÑEåŒ÷»$[¶ëFR:ºâtA}ÊnÂæaôj‹Ì¨²í¢H–%ó.dgnP{MÌ4QZlÏ©;ü¤=UοÐ)ö™º¤\„ÆtäL0N‹ü¼J1W?MˆUÄÿ™Š:eò>\æÝÓðŽN‰C ç¨üŸ€uʇ\Š?Ê’x*—O9óiB2šÖoƒ†,¸ endstream endobj 168 0 obj [ 167 0 R 169 0 R ] endobj 165 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 168 0 R /Contents 170 0 R >> endobj 171 0 obj 666 endobj 173 0 obj << /Length 174 0 R /Filter /FlateDecode >> stream xœÅ]oÛ6ðÝ¿‚À€¡-"%k¤u‡ ]º6Æö°îA¶éX›-µ’ÜÌößw)J–(ºÛ€®Aáã‰÷}GÞIgaø»T?QBÑj?ûhpE1aP\ ”£=20G;µ«Ð‚½ €-úy–Ï0únö˯ðp0<Ìð]C|7{Û“¯žà/.¿¯#ôÑàíi"ƒØ4ÔL㣩G;ã6ó«¹jP+§'•ÂNØí£î—ŽÑýìz1ûæG£Å¦KÚˆ&ˆi¢þQ´Ø£_±äñ¯hñýl¾…ò »lE%ÛªCTcŒ19±©‰ldlÒ&ݦ{©rø ŒM,¸Úk‚wóonoç/H“ÙÍ„(¥GûßS wRçNôN^ʪN—»¬ÚÊ Õ[‰VEžËU9ZÊúAÊ¥h¦´’¨XþQš¯QVWèÝËëî‚ÖšÈaMHœ`)´ÈW‡¼aÞÒL;N$'q’DÄ8îî˜×é-aâFpà8š046ÿÞˆCÇÎRˇ®cN¾_ÿ.¨Õ4(C"—ŒÖ“6PJ]¦åPêÒN–eQN áN‹ôûW‡Ä …ÜÇIdZ¤V®Š3W¡çÜIÀ`.TI¬Îßaôpîè#ÆôV}1´+{A´ˆ¦48¾\»tÞkY֌€®4bŸæé½T÷¥EUÇêrëÊpŸÚPË}Dp Æèћ܂&Ö1þpÌÅ”Á Êü=éO‰‡ÎÊmÎt –²>”9ܯ-Bõ-¬}¦áOi™A§Û!œnñ¯dݱ+œœsù¹ß)dkÀâZ ÓFyŸñ•7ê° q |I Uq¨ZèU,>£Í±„+?»4°ò?h0µP/ÓÌ®fˆ|%/,¦Þö(ÍÌàโÓN »þ,Ëi¬úB8O8‹þ錅>z¿íU]BÑõ m.“á¶~tNsÕ^ ä·5lš°¢·Êar´‹}Z¯ÔÌÖ®=³‡>‹¨©DgF1ñÑ[ ²N™ª8ÜoëîInAsŠ50LÝžbcÁ¾÷4¦Õ± ,ê¦ÛŸ§^1Çâ ¥Ãõ<X4=]3^xî$H ò0…©fÌäL‡N½Äg$“ÔMÆ.ýÏW=4z”–-‹z‹T§ì™Y Ò!po¹x[XhÙ©îØ‰Û|¤;?…nåúªóxÈT%LéÄàRù$cŸN! }¤J•öŽqß1 x>¥‰iŸ~ÖGXj¯ ¯e©oc½î£fC¿uÕ(ݹjØ4®z¡úÖ »júc úÆx`–2!zûçšx‰;M:}½IÄÔ)èüÀÓÔÁÏ0Æb©•ßs]V»\»XèVàÂ8Gü“p ?Ó³ÔH{ÁukÝ›˜E“é½Íªúì¢:|øÝ»¹ òfÓÁž8c•ÐÃ<æýÎÄ™y‰;ù}3§ ¸-HªvN8¸y Á}¤>m‡Ãfq2êxœ‡×Îþf½”Ãø]ô…S Äb Üà Û}Ö42DG†Ëütÿa×½âr½ñ #Ī!âf†wµað:¥zö}õí‹×wo__Âÿ›Åü©þ¹|yµ¸º¾º›£§{¹/ÊãSôæÇù-ú3Œ_¼ºž_ñ¿ž;ØÃ5sÊþ}׿<&à8ùïú¼!ÁN}¸*¸À$Æí¡Þ{-ì‹ ç$à ìaļÁ¼ËÖÍ75kúfTE0V³$ é½;±è´ƒ6˜ÓÄÔ8]a.û/ê×Þ$¿^8ólŸ»ÅRö9/›žÇ"ô+o{;Õ‘´ËúÒ§›+'óõðu HD1ÃÐ'˜@W»›W¨ökP÷1¤ èâýÁÓýi £®õþ‡¥©2i>4©¿¿ØÁ endstream endobj 172 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Contents 173 0 R >> endobj 174 0 obj 1892 endobj 176 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 626.028 162.0 635.028 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 79 0 R /H /I >> endobj 178 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 614.028 180.0 623.028 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 120 0 R /H /I >> endobj 179 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 602.028 222.0 611.028 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 144 0 R /H /I >> endobj 180 0 obj << /Length 181 0 R /Filter /FlateDecode >> stream xœÅT=OÃ0Ýý+n„sŽ“8$†¢B$Ä"¥qi‚€Ϲ6mRZ %|ºw÷î9yfÞ#{¨4€bÆž½O€ @ÆÞÅ BD0oGPÛ¬ž|Zt¸$2žà–5 á‚ÝÝS°¤‚W†›pËâ6éõ·Ü{„Gvš±ãóB6]¯(L á2Hí@6ƒ»ƒëÑÙÕx<:Ëï!»d£l@@ŠàL3ˆ*P|CÚeµt>ò8 ªýÖýéPé†sçΡp=öGªº×æ»U’<<(âN)÷¼²/*ÚÞ+24:©š ¢pZ*«<'GiôVèyW™&'èª{É­Ý:šÛ¯¹L9Æ1A'⤽X˜ÌòwxÐÐV„Vëª)tOä˜ë¢šVä(ó.È[ EÞ4¦³Ùµ)òŽBTïÓ·$µiuÉ?ÇÚÍ/V<¢ÁR%üp7ZÃIÝš•pë½ÙOVòÐín¹·t“.~ù¨ Ó4ºè¶ÞL£ß–Uû¦@õwУ¹1$EûÇbb˜$ll:ýíqÂ#©Ò4”«’Fó^Ï û>Àb endstream endobj 177 0 obj [ 176 0 R 178 0 R 179 0 R ] endobj 175 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 177 0 R /Contents 180 0 R >> endobj 181 0 obj 438 endobj 183 0 obj << /Length 184 0 R /Filter /FlateDecode >> stream xœÅX[o›H~çWœ§UÉÓ¹0 DÚ•œÚ­²²r3iµjú@`£bp n›ßÁ€!ã1q£lJ¢0æ|çöäÞ"€ÕÏ < B¸°îkA9µˆ;@lD9, ^sHÊ]mVêTmR‹9|¶R ÃGëËWu3¬~XX‡Û(O­ËŽýò~uû]¡ăËÇUT ­6mVÉ”¤*o%uÚês…Z-+çªó^§pë6'¥v÷õŒc¸³N|ë݃?kI+˜’ —zåAÁ_À—76yûü­±¿SÊWNÙNKÛÛ`”몪.Ƙ<ŠiSYQÇT…t,d”!¶ ÔCØáå~·R˜úCÿz •Îv§ë"*ÊM rC©Ðö{}ûáb§Äé,[-‚"ÎRn³ua–¦2,dQP·A.sÔ8/ ÎÛa+`§þ°NîÑÙŸ'ÇCœ¸ž'H§éCZ?EÏ`Œ`Q¦°«ÍÁæÐ3evæEP¬sm'¡ØúW¶,ch¼!Xw‡¸ŽAu¶N’½Pb´ö÷?ðt¶ãs•hÛ•Þpu·^È´È!H#ø$k™ïw·Ì÷`DA8l×ÛfºÔ 1„Û,Kd*êDq¨˜“ÞÁ¹,ærEË ­‚(Šë*%²Ë3þ\B$gÁ:)à{é6Ä9ì/;c •ÁLNö÷'}ªè€¬«¦ãe3SÎ+¥‘ÌÃU¼ìRÜØÓ„!êØÊ4¯Ëµi8' lªæØ›nëm…Un/UVÛ‹p½Z©r'ѶY·¢m×vP²v}¤fËÙhx5œ_û×þjïù]kAÍ®^FQʵ({¥Fè®FiÒµ‘§2’·ë½tp9bŽk5õ±`Ö§ÚÚ¾}h× O·‚²×Ú‹vYy{™ÍÚuG{¡:§e1º7³•ìZ.‚8‘kcjÆT—2猚 Ýk°¬"Z.6],£„:"Äöȳð›,ž@·‰¡¦f{dÑm¨Õ´ê5=8^H5Žw£œŽ ùèL¯êË1ÆæzÖ›Ö…ÂÔ¼¶«GÚÛ¼®ú5€x/ÐÁqrlàî3{úâü|2©]ÓÉx ðétüyj*œz~õ8™çÏœÍRÔ×xA¹­“¢Ïhÿ`8Ü(ÿY×?/7êhôÌ1r¸Q¡ÓèùÓ¥Yâ'z:‘þîö~Q9¶ã õVRRÆ‘„ñl¦^’ó¾×uǶ+1©×|Wd©DE\Z¿YE endstream endobj 182 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Contents 183 0 R >> endobj 184 0 obj 1127 endobj 186 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 644.764 234.0 653.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 109 0 R /H /I >> endobj 188 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 632.764 180.0 641.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 120 0 R /H /I >> endobj 189 0 obj << /Type /Action /S /GoTo /D [172 0 R /XYZ 72.0 720.0 null] >> endobj 190 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 620.764 174.0 629.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 189 0 R /H /I >> endobj 191 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 608.764 234.0 617.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 90 0 R /H /I >> endobj 192 0 obj << /Type /Action /S /GoTo /D [148 0 R /XYZ 72.0 720.0 null] >> endobj 193 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 596.764 198.0 605.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 192 0 R /H /I >> endobj 194 0 obj << /Type /Action /S /GoTo /D [182 0 R /XYZ 72.0 720.0 null] >> endobj 195 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 584.764 156.0 593.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 194 0 R /H /I >> endobj 196 0 obj << /Length 197 0 R /Filter /FlateDecode >> stream xœÅVKOÛ@¾ûWÌYöáÇúØ"¨Z!ªˆH‡½ Ž ¶)ðï;;~ÄÞT¹ÐäàÑxç›oæ›äÕa@ñ;3 ämœ×ÆÇ à üÆåùÀ\Â=Ø@c{šS=ƒï,|Ô‡Ðx‚{'s(üpñe Þº· ¾sæ½üæ ýòüÖÎ÷…sqí£°Xu-ò\"dˆ‚$‚{¶ØÀÃÉåïÛÛ«ËÅé#,~9W‹A‚ñÿPÇ|Àµ x@öÞF‹Ú‡žȼJ›æ7ϵ6krõÓJŠvœhŸÒPÜ/Mn×5è!r 'w­R~qËF*šÜöb\9šÍŸ+8މj­(Ï2UIžµ®*ïÌ'ÝÚ±ªÔR•£|ÑQ²JtÜz–Ÿ­Y·íâií1ãœé J¹à#ޙߡŒÊÌ€ðPÔ´$ôGRVeWuZhž÷‹“¬w¦è˜¬3•¦:®iô{‹†9UåEœdkÀömÛfmÃÉ ±~J%«YMÛZ;ó% M ÷'ˆÀ‹*ÔFWº8UB¬Ë¨H–(’Zæ4Ù¡â¬ãH‚ À)VGiè…^x§5|K˼½ Ý b'|—õÏÃvÃ}¶Ô¦±Žg»‘*'/‚þ±àqR6ø6L)Å,ô? ¥Çbž5³Vï3+:ãÇ¢¯’¬ë®—-]Y©ê­¯Ö6Ð>KÌgÄcøc°°F¸Í+mmÃJzDRŽX»ù[¼M¾O¨gîõ&b_ò<µf é¡PPY|èÓ¸æo@ ý‰èzÖ³X¯Ô[ZÙo²dÄ ‘ç†S žõç;nPÅúm£3\ef77h#¹xàá^Àxአ´Á O®ÔàP8l7cì‚…G˜Y®œ’ðòæn~cÏìc°‹Ç]RýQé¬4kšôFoîü~ï[ endstream endobj 187 0 obj [ 186 0 R 188 0 R 190 0 R 191 0 R 193 0 R 195 0 R ] endobj 185 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 187 0 R /Contents 196 0 R >> endobj 197 0 obj 706 endobj 199 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 604.028 180.0 613.028 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 120 0 R /H /I >> endobj 201 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 592.028 162.0 601.028 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 79 0 R /H /I >> endobj 202 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 580.028 156.0 589.028 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 194 0 R /H /I >> endobj 203 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 568.028 198.0 577.028 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 192 0 R /H /I >> endobj 204 0 obj << /Length 205 0 R /Filter /FlateDecode >> stream xœÅRMOÂ@½ï¯˜£Xgw»_G„jâChâx¨P•Ц5úó²[°b‚ía&3;oÞÌ›W&éïUÆz ³{­c¬eê6 ".5¬ ö5,«W Gn=2á9ÏpÇr†pͦ÷”œRÁ;Ã}¸Mñ„ý« ž¼?»LØÅ•<~­HnDä½·WÒWŸ„dÓ³Áíh’xØö“þeOÎï!¹aqÒšI ù3[HW+-ßS{S­BŒ"¨J-k!jPƒÈÛI ¿8a“R[è“6ïÖØ*Šp×ÒVšN)O¼²ÛF.ÜÖn<¿?î|QÌÖyžÍÊÆ;ÚŠCD±‡£ ·NQÂë̲—r±ÎSb»(ßÒÊ/è7‹&®Fp4† £užñmEwk繦oE]7É2è/‹õn‚ÖJj…Uýi)mP"w$èoˆÒ‹X”iùVtFâXÀÇE>ïÍÓ2}H‹¬ûË-ëèJ5bäÜVÉ2ûQ{‰’ke½”;ÓsÌ>lìe€ endstream endobj 200 0 obj [ 199 0 R 201 0 R 202 0 R 203 0 R ] endobj 198 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 200 0 R /Contents 204 0 R >> endobj 205 0 obj 418 endobj 207 0 obj << /Type /Action /S /GoTo /D [100 0 R /XYZ 72.0 720.0 null] >> endobj 208 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 626.028 258.0 635.028 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 207 0 R /H /I >> endobj 210 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 508.556 162.0 517.556 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 79 0 R /H /I >> endobj 211 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 496.556 198.0 505.556 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 192 0 R /H /I >> endobj 212 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 484.556 234.0 493.556 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 109 0 R /H /I >> endobj 213 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 472.556 180.0 481.556 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 120 0 R /H /I >> endobj 214 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 460.556 156.0 469.556 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 194 0 R /H /I >> endobj 215 0 obj << /Length 216 0 R /Filter /FlateDecode >> stream xœÅUMo£0½ó+æØðú°}$ÚìJ+m¥(H=T=PbZVÒ@µÛ¿†Ih›=dÉÁc›yóæ=ã<; (þÜfšC²už»5’ƒº%?æîú؇¼ykð>ÂÁ¾„ÁÜ:…Cá»sw› ˜ðÛ¡‡pmòÚYê7;ôâõ)<:‹ÈùòÍF!J‰„G´Oñ‘("¸nÑ†Q¸×K÷&ü¹¼¾‡è‡³Œ&ÝÆÿC7« tTrI|n³…]à ÔlåÝhQmhÉÙq–8Ñ1¥©Å->﮸BÔÄU®f­¼°dG.6µßšAêèªÂ£É&=µÎÊ®'ÛÒ:ÛX¦©IêÊ6wB OЄª.ñ¦, é3æ ’ø˜£%ëò¶–ÙÀâõMÌ¡¬¤ñl?m/ú =úØ6q?Ä•q‹xkÜt_nÝjg’‘W©Âq=d‰·Ë?‰ÙÕYYĨxV¿ÄMü®@ÌÃUH­=¡,Æm–çp ®/‰‚«*{lÀÞæq1Äf¿/÷Ã4K‡¸~2ä|ø…Ú ó]\U¨ä€YÍ$öÄ‘ösŽÆ Š´Uœè¡—v¶s®$æ+Ê„æ'òÇ\÷èNmÆ}Žè&CÆ£Ír,ÂënÔLÏi”\N-Ù‰9~p@¬…Lòõs{ÀOg¦ðÒ×OŠ`Ýd „yUž>ÌœR¢=ïœÓœ”E.Ÿ¼iDÆÏEL³bhr—{ÿÈt¤`5‹.‚sÑ7Yõ‘ž:´ªãú¥úüÍÀ•O$´ÒÒïï½Ú¼Sâßeˆ¥¥<º*Ûš+ç/ý±V endstream endobj 209 0 obj [ 208 0 R 210 0 R 211 0 R 212 0 R 213 0 R 214 0 R ] endobj 206 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 209 0 R /Contents 215 0 R >> endobj 216 0 obj 617 endobj 218 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 171.404 162.0 180.404 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 79 0 R /H /I >> endobj 220 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 159.404 198.0 168.404 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 192 0 R /H /I >> endobj 221 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 147.404 234.0 156.404 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 109 0 R /H /I >> endobj 222 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 135.404 180.0 144.404 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 120 0 R /H /I >> endobj 223 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 123.404 156.0 132.404 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 194 0 R /H /I >> endobj 224 0 obj << /Length 225 0 R /Filter /FlateDecode >> stream xœÅWKoÛF¾ëW ÜC Úî›K£  ÔŠ HãXhPÄ9ÐâÊa-‘²HÁ6Šþ÷ΊO‘m÷àÚ.—ûÍ|ó^ÝŽPü»‡çs˜¯F·ÅƒÐÅ–ÒÀ$á VP¬,ݩƂ—+|ä‡pñ¾Œâ…³Ñ×oø1Š€»m‹Û/Fç ýî }qýM‚ñÿ…Áù~<î‘Vlvh‘ïáN.È}Zn+ž¹Ô|™“ËŸIÑšíwJA÷å”S¸½~~§€Q˜-ê¤õîÃ}÷Ça¶‚¯Ç‚½ú³÷£é¬ÊvY'ŠNwe RǨJ)Û³iY¯°)7éc°²¹Q=>¸O¨Vî¼É§“Ùäíäb:žýùi 9´0Á Ó¨WhÝ…^rîµrg6ƒì»…ìam!Y@aWAŠoWÙyFJî^wÉõ)ŠÓ¹¸3ÛM4‡wÛxžEI\b»KûD1ãû+ÜuñgÁ} ô{”2*‰äÒYT±ûkÙmd÷`iÚØYÛö“æ=’KÈ¢E„é&eèÒçL÷hùõ ÔŒ“K0"ºK•ØÉæz»²q–B‡ðG°ÜÚô0iç=…uÄDCD镃IʨîMÚ™òØSiãÒh—Nõ÷zo¾LRŽËO¤GГħ˜±Êšú¢å(uNàÆ>Ü%›Ò‡ÕU²„ÐÆIÅטÖ7qr×”®‚ùÍØÆ!yÜéœ2â+F©¤¢³Mç›hÝÌðÞÊæÛ›n?Ûl»‰Ó½ŠH1®‰ñ°º<ìK]aÇ dœEÒô‘yŠéŠ!4ýyz¬ÖË:Åúê“M<ϵœª-Ï“8Æ/ãh G™E1AfÙa²#ÀíËWp²W¢p²NÒìzcÓ[üØMî›–&¬¤~ùíÃÅù‡ñ§ß/fgŸ§¸<©—ã²Báoi„ÏOùé?oº‚¦¶ ûÌ^‡vl—Y•ɯû λFµ›–ƒÙ‚4ÛÛP°„fÄÃnlcE/B ÓÅ=Ÿ%ª0’hœ 5òcÛ'ä‡d¨’á0J%¸ÓfC¸zÒ(ÑJeTøTh¤Æð0VΜéýÜîJ1ÀÑeÛÀ­Í•h®ÂÆQËø-10V1pœF×NXõÄõÚn6ØÍª×hQ¯]QW/yK¬ß×AŠ}¯!3=<Ü¸ð‰ Ø Nò® ¶n<ÄŠ]œ÷à›\7xgÉlÓÎݸhóµ­M'¸â¨Þªv[ƒ“=`7ÿ¥¯[ÄæÆP¦(.ˆÂ¶Í•(¯ÖÂd™&Õ³¾á¡b% ^fv?™vW¼Nk£`ˆØ»­]­÷Êê$*ú\‰‹(®<(WóÿÈ´áÁô tœÏ”Féc®À™ðL¡idÛ&ËG.ÞšãÝÈÍ*#ÊŽ’ *-ñN#uè¹öU®»PÀ ª&­;<¯‘¥šuÁ»58Æ5CÇ(üÔUlï3§ØóHÃWç£.M­À endstream endobj 219 0 obj [ 218 0 R 220 0 R 221 0 R 222 0 R 223 0 R ] endobj 217 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 219 0 R /Contents 224 0 R >> endobj 225 0 obj 1125 endobj 227 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 508.028 234.0 517.028 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 109 0 R /H /I >> endobj 229 0 obj << /Type /Action /S /GoTo /D [97 0 R /XYZ 72.0 720.0 null] >> endobj 230 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 390.556 198.0 399.556 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 229 0 R /H /I >> endobj 231 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 378.556 258.0 387.556 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 207 0 R /H /I >> endobj 232 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 366.556 180.0 375.556 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 120 0 R /H /I >> endobj 233 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 354.556 162.0 363.556 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 79 0 R /H /I >> endobj 234 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 342.556 156.0 351.556 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 194 0 R /H /I >> endobj 235 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 330.556 234.0 339.556 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 109 0 R /H /I >> endobj 236 0 obj << /Length 237 0 R /Filter /FlateDecode >> stream xœÅV[oÛ6~ׯ º—¤˜h^EiØ 8S´È²e6P m‹N´éâHòÜ`Øß¡$[².n™ X‡Ïw¾s#ùhQDàg›—òZÆÖc=G‘bˆ;õ”t˜I£Z–(2«ZÛIðªð€Þ[‰EÐëÃ'ø  [‹táJå¹uÛ²o¾g·Oнu±°&WQ‚«&DÜÅ„HB(QÈÅœyæah£gWoo.íËébz1ÏÎ?¡Å;k¶8ð†Sö?xs{À2ª˜Â<—Ú¼šƒ™ È|ŠêÔï µ+rÕ{”i8‘6¥Ã?«ññì*3Ø=È*wFSùÌ!ëeÑØÞ;ãu®©Pi\qœÊ—g«0 ìÀ/ü;?×èE “b’è­ÎÃxb/>žWî¶aÁÜ!ð8´ÂùéúîÇ××óÛkûçßáÿ‡ò_ûèoኙG_Ë^õÑ8ë õXM ¯#¿Ðtœ“ãœ~ýe¾xóÛÌkÄvÜc—ìrˆt¾Än»Ýâuœ¯p »DQFCd·Oöæíu¡Ût×úË—Cø^7¤ÿQ0(éFU‹&WÐ)°‰¸ð‰T'$X¹œ¡ê²›‡F³ÕJ/‹|§ßë=cN*L¨XÁjÍ›4Ñø+LºKêzž¢^¥8-­é]<íÛ·éž²¦)U ·éíïË4IJÐ}:òÖÖP¢ŒSdpr0 '‡pÝ nöy©×E˜&>4xXl|#s–\A|xñ>Œ"tŽlA1EgyxoÀöc?ideiÖ ÓU#OkÝŒ–QþÙåaky’6rìˇ0¹ofö•Ú¶iܵ>¬ÒM|ߦ4ƒ] ½#˜`åHB…#BR2_‡‘:Ç´[.ç­e›¡‰úÀ.©D¬Îø_…¢X ¨NÎØ7mš‚J¬˜ã¹ž’»¡ÐG÷H!†Û9!žR•ÊZn¼Ó Dæ>O8‘ºÁmZbÔ %î1uô§~Ú¦Y€üì~à éžK/xÔs¡iÍu‹°ƒ‹Àxç+çˆé|OÁéi{3“Æè€vy£5Í™QÓ°·™ÖŸ äpÈáVÜZÿ`ÇJJ endstream endobj 228 0 obj [ 227 0 R 230 0 R 231 0 R 232 0 R 233 0 R 234 0 R 235 0 R ] endobj 226 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 228 0 R /Contents 236 0 R >> endobj 237 0 obj 972 endobj 239 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 573.292 234.0 582.292 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 109 0 R /H /I >> endobj 241 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 561.292 162.0 570.292 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 79 0 R /H /I >> endobj 242 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 549.292 180.0 558.292 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 120 0 R /H /I >> endobj 243 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 537.292 234.0 546.292 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 90 0 R /H /I >> endobj 244 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 525.292 198.0 534.292 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 192 0 R /H /I >> endobj 245 0 obj << /Length 246 0 R /Filter /FlateDecode >> stream xœÅSMOã0½ûWÌq©f<ù°}ìJ€Äa¥ªA{@BëìFjSP²Zöß3Ž]Ú*‡’<gÞ›yoò( ¿hK°X‹Ç˜S  ’<¦²T*)ƒ5Ä8ƒ•ÿj/ mÄGøˆƒ?ðK4áJÜÞñå þ <„ë‹çb¶Çïoðäü¿ÅBœ_f Šj'Qf¥RÈO®ÀÈ„¬Š5Ü~›ÓâfþýŠkqQ ÆH}Á³Al¥&- î«“ãLòW«¨}<jCsám w=á~KCoOJ>n«N8#ÍÀΔF­<±d¯\ôÜ/ÃpëìªáTƒ™zguœ)Œ4­*·èÜîÿ‡ÙÞ"5X‰yÎx&ÖýÜ4Nn+Æùr-3®±Zź‹§…{èêMSò(u÷·ôqûµUÒ 1´ÍŽ¢VäK™›báÜ9˜®ÚÍ‹‰; ™G%¹$4^È^D{Ø ¾ú½›¦éÕ›,Ë®¼/[×¾¹ =5ŸDEÌñXÄeÝ~ªéXг9©«‰{ªÛ®=E7é±èUÝìÔÝÃý`ωͷÙüDm·¦sï$"ú­çœ‰gòDƒt endstream endobj 240 0 obj [ 239 0 R 241 0 R 242 0 R 243 0 R 244 0 R ] endobj 238 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 240 0 R /Contents 245 0 R >> endobj 246 0 obj 447 endobj 248 0 obj << /Length 249 0 R /Filter /FlateDecode >> stream xœÅTMs›0½ëWì1™‰U,>r#‰ÓN'Ó©kfzÈä ÛŠ­‰ä´þ÷F˜]û åÁÛ}»oa‹< ú?ª0öa‘¡mƒyú@ƒbxcì3È ‰lê§œÀ?Fú0é` ¿QŽ|EÏ/úæˆ&üAä4ݺKÑ—GôÕŽˆìûŒB#ˆ0õãúçCšÁóÕý¯I’NFIšÜ%³Éõ ¤ßÑ$íôC=ÿ?ô3íhО†~ˆOœ>°©Á4bÕ·6 Íi²šÐˆ3ç (b5WR×ä‹ö7¤ÁQÇ×ñxÐÊ ¬çb]»mFK×®Fz9½NOgæ'ÓÒB‰ÊtufãhŒIèLQÃHײ‚ké­‚«×]¾P²È[ ãû6–ùGñ&ÚKµ¶qñ.J®d¾j‘j_)‘õ3W¸…Òõ®º±„"³ù–\ñ9¯Ä`:WW)¶;Yv„™ ¸}3ï¤o¾Ìd.+Uë6 3Òj!UØx.lÌ?¸ÜðùƤ“©¹XìÊRäÊ?“ô¶—‰r‰Ò­.3q3õ6ÛWÛ£Ž/ÞD¾´@3›v%â3+ГÑ’æ3¸I9îK×únß‹J­tY­í(騥øLïfÇQÀÂ~òE)¸Ëù $JÂOèø³ Dìl±Ñq ‡Ç@ÏA»ÇÛ6ƒ‡8ðôËL¯O¾šMŸ†ëE5W¿íL£ú…Å_%òJ//v>lSô·[È endstream endobj 247 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Contents 248 0 R >> endobj 249 0 obj 568 endobj 251 0 obj << /Length 252 0 R /Filter /FlateDecode >> stream xœÅUÁn›@½ósL¤˜. ,lnN㶪¢¶®‘¢(Êam66ŠÖiý÷¼˜crtíÃÞÌ{3ƒ½µ øUGÀ),Rk[c\VC>dz©)Ô±ëê©V@ú! Vðhe¯Öó ÞŒ áENÓÈ3kÚª_Ý!¯O`iÝEÖ§/>8¢WÓ"Êlæxœó €Ðv)¯>¢ž¯î'³è÷ϧÑý8ßg“눾[“¨cÈuè04íhÀ¡4°OF}`»CD'ªn­ë)ԧΪC-NŸƒ¢ˆÑDÚ’ºS¾hñá."vجÇGyá–õ¦XÕnÌ tœjHq:ž“ jOÚÒ\ÉR»:Ó/—Û„1ÌÖŒh•”p #Ü*¸zÝe •äY¤bßÄIöž¿ÉæR­Lœod!T’-¤Ü—J¦ýÌ¥Ý@ÑjWÞBžš|±Pb.J9˜®­«Û]Rt„é´}ûΉo§I–”ªÒ­ û¤#Ô@*7ñ\šX¼‹d-æë”´2Õ Ò‹]QÈLà×8úf›Ë±j“võ$•7YoÓ}¹]·Ô‰Å›ÌbÔ½iV‚ŸY æž´æôПÁMrÈ,]é»Ýä¥ZbYÔv”tTƒR¨»p2?è'‹|ÏQî@¶?òú§¥$®E¾·p¸ ž×gO4.YÃ(þÕà»L˜Ó'~˜M†ëñŠ‹/»?QýÂò¯’Y‰»k·~צÖ?AªÈ~ endstream endobj 250 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Contents 251 0 R >> endobj 252 0 obj 574 endobj 255 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 149.025 210.0 158.025 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 254 0 R /H /I >> endobj 258 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 137.025 216.0 146.025 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 257 0 R /H /I >> endobj 260 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 125.025 204.0 134.025 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 259 0 R /H /I >> endobj 261 0 obj << /Length 262 0 R /Filter /FlateDecode >> stream xœÅW[oÛ6~÷¯ ú°5ÅÌ‘”HQ6À]ÓaCP °±=4}P$:*KŽD'ñ¿ß¡®´L+ÉKæEò;÷󑺟QDàonAÈP¼Ý·s y¢âQ3޶¨s”™]Ö€u#x4›`°AÿÎòAξ}‡Å<ÎÈX\ ^ή-ýf…¼¹~Û²ÿÅ‚ëã,,À£ÜÔh¯™ƒ™FYÊÚ°µÏFj3lŒkžg"ƒMÄ”ÖÜ·SNÐÝìÓjöëŽ(A«õP´3X²ÐüZmÑ·÷¾¼øŽVÏ.W'©|ãdÑèîÓ!«’B|ª3´>5.}¶ªqÊ_"b"¸Ù/ÀÕ_ËÕüóbµø´X^.QƒíÔó°ôŒbébo Æ €®ÒJ£$ÒÑmT© m#oÒüéBÕ~·ËR• ¸Èsë´ÈQµS1Šò¤Ç }Ø)Üy8<ô)&!¢ÑùeŸ×²:Ìù`Šs*Ã0 m0—‡\GO0t(£„cæq&hëbýEEúŽÄbÞÇbGáÞÙ–ŒŒ¡KÇʹ åYW˜p¡ÑO?ÔaB'äÙê\š›TÕèNû•ªÚgúùt™Ú !>_£åÝ~«r]Õ%óO”í»¸º¬7éã¾CŸ°É€´u¢ãÚM×iÙÕç6#˜úP²^8B· cè]ÀXÆQ/Æš2­×ÖFUþbM¦Xaë5²ÆPE™ØË«MZÙ:Õ:‚ôÙSº°_6¶þ“#ë½X[/5?¡p9$Ç.× çG1û0oF)æhÓ ‚FÄqÍ9#} Z ÓÂlîy¬ogü|ý2/Ä>¾¼¥ÇϪŠËtg׋“Ã~mCY[wuÖ-ÑAé}™Côö Œ«ž`ÊXšæ5éö%R*­¶]Ñ ßNv¾ä˜æ$.{^V¿>à&„¼$„P € ¥ìrrùmwÙÐö.Òö˜ÀB@ß²ŽèoFdŒ~¾yÿ.+â(Û•~‡Þåêþ'À-Ýãæ}:¶Ž|6=ò¹JóX ì>¢\AÞ€öK%5ÍX*)½?ÀMzAú¸'•¼MßR)´Èª¢¿Ò7jc¶ ظ¹V×Wê^ Hbïèë ëµêIÁù©`$ìµ’èØ²8> endobj 262 0 obj 1213 endobj 254 0 obj << /Type /Action /S /GoTo /D [263 0 R /XYZ 72.0 720.0 null] >> endobj 264 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 97.487 216.0 106.487 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 257 0 R /H /I >> endobj 266 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 85.487 204.0 94.487 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 259 0 R /H /I >> endobj 267 0 obj << /Type /Action /S /GoTo /D [253 0 R /XYZ 72.0 720.0 null] >> endobj 268 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 73.487 204.0 82.487 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 267 0 R /H /I >> endobj 269 0 obj << /Length 270 0 R /Filter /FlateDecode >> stream xœÅWmoÛ6þî_qȇ%)j…¤Þ l˜›ºÃ†nCcoEÑômQ±0YrD¹®ÿýŽz±i‰v Èb I=wÏÝ‘ÉÇ‚¿¡zø!ƒÅjðØôQðØ^Óåz@‹¹°‚æÝ…T}¥½°ö õGø²„ƒl@à—Áç/8AÀv@ºæ*ðtðAó¯FÈ‹ûר”ý/ >WÁg¾Õ©M…¶ë>ì© ©¡´I[ó¬­Ö¯5¹úy’9p"æ¤4t_Î9‡Á›Ùàæ ”À,>LZ߯+`¡úc0[Áç+Ǿþ³ß“Y¯”/œ²^•ï}0H«BèQLUeý&¦:¤?øJÔAràÀB‹x®ú>¨·w“ñl2|;žßŒ§¨Á{u<‹¸èÙ&n|Ϙ߸ç°(/pˆxÉç\îÉú²µHHíÕèw›lQ&yÖbNçÅ -—aèÓ&/Ó]Vòo-048 mË'>Ú™RAjªÃc¢‡8mZh¾ã:ŽÁEže¢ i(×bq’³ `øá±;ã‘ù¤j£–»µ8éÏ6å~ü äf±R~¿”1‹+€³¼‚‹‡ÍJd¥žEð7O7Bž&ÔÔ£NnÇΦ«7Ï©=†>‰“×ç“™†XÄö5CÆšIô°c¸ÆA\#.ìíh]Ê¢ÖlXŠâµÖ™XÂÒš\{Ç ±Í‹Hž-©û1ߤ¥ÞUæzc©ûÿªª¤µóXk¼ŠÄ°§s@:1W‡GY{u6åŒP+¤zí:óΘì>j óî¯at'ŒV;ù˜Þ_wòˆ…=öˆZ;3|‡IøOÌæ.“T@Yì’ìPmx5ùSkÏö¹Þ(¦ãa7C© ñû§é‡÷£>Þ!¬‡¯èðÍÑ$æÈ6A• ­’lÔnмÅWQ/árÏû²ÜÒnÁD“Ëq“‘©Å#‘ šÆ"ÏËŸ5Ó÷WUqVuCqÁ§ÉôþúÒàŒu˰DµÉ‹MQìæbwkð£’JTJGpûs:ßÞN¦ÓáäîîÏ»/Kn¯@ß_ŸŽZŒÚ„2¿9¦%‘€Ic²O‹=zs‰mÙ>E5`­Ô6IS˜‹VW!¯•,Æ 5"†Û˜êQù}‚ˆ¸6µ* q<ÚŠÈBTšËñüž”›êqž¯ëZëá¾à5§©qVm¥èÔ‡+ÑÔúª0͹Ðå²È·úÇI|4ª{tʨ»š4hßäBjÍ,/µOÓ|«Š­Á¼ŽoNâmM=8ñõ0úËõüNêöUÖTÖÔò“O)eˆ‡Â@JÝæJ1Æ©Ì÷ÁÃ= }{O±´ºV±ÞnA °ì£;e$dYä»Îµ¡sÃT¦™ó\Óë"Ÿwï#ö÷\Ãi"ç3©V¿´žN endstream endobj 265 0 obj [ 264 0 R 266 0 R 268 0 R ] endobj 263 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 265 0 R /Contents 269 0 R >> endobj 270 0 obj 1291 endobj 257 0 obj << /Type /Action /S /GoTo /D [271 0 R /XYZ 72.0 720.0 null] >> endobj 272 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 97.502 210.0 106.502 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 254 0 R /H /I >> endobj 274 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 85.502 204.0 94.502 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 259 0 R /H /I >> endobj 275 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 73.502 204.0 82.502 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 267 0 R /H /I >> endobj 276 0 obj << /Length 277 0 R /Filter /FlateDecode >> stream xœÅW[o£8~ϯ8êÃn;j\cc.‘v¥L'3šÕh»m¢­Ú>0 Z)Móï÷æ iç¥ÓHÅØ>ç|ç;ãç‘ãüaÚ ÜõèYÍi`2à†šh:aÖ ÆÂ|WkÀª>ÊM8XÁ÷Q4¢ðetÿˆ‹PØhW]!<ݶìç+ôÝí·pý·‡Q0™I:±)¤y9‡3¥¢|)T´©g©µ–àÊçQP´ÁD‡IQpßÏ8…§ÑÇÅèê³ÂÂo’Öä8C,fç k¸?×ÅÅ#,þͽP¾3e½(æ¶kg:FÕ¢”j>‘5•O¥K:kY:5Àn³ 5D¾ß*>Íæ‹»›ÆŸ¦‹éÇé|¥t-£ N˜‰¦ufö¥3»Æ)ðdš%ñ><'s–NZã5ðê¡6Ey£”ÿ¼Ü,ˆ£Jæ85†M„fÙ¶©)jæû(s^*A{À˜õI­a– ëøhã©®÷D ÒÚ;4A{ÛÝ8ŠdáÐ8ÝH÷(8¦÷eá—åþ„=f}”'ãl¿‘G­q1àØo¿Cºu]™¦¯s¯1N ŠyiX¼Ÿ&OÛµŒ2Œ{äÁßN¸•éqè M·ˆÈ3ÇÆI®zY® JO¡‘‡\>ð×i§Ò0 S#ŒsÛæ‚Ÿ pDOv ¸( 쵞ÖT®±õªPÊä²5IZ¯NkŒé°‹¯½¼XiÛ¦ôm˜µ§²¸ý²jÛÿ/Rë=ö[/<9îÕúlñŽÏ…ÅñkNRΨ 6Å´ÒM»NÞ ’Ý—šÂ2ŽCéDà‡Î¯>¯/¦aåm†ëªGMcÿ;%x 9¥u¨wNZ‘¿ Ã}Õ ¥G^/*Æ¡\PÊ ¥ý“LÝ$Ø´“x°ç ›à™‡°¸j…EZøª•µd¢Cäé>Íäº*éÁòTëáÈŠ¦!+Ò¾ù·•ŽlžPòÆ,5X¶eQ½š½8ëMØ´ž¡S€3ƒhØú,SuÊõNøõáü,Œ]'\Åivg‘Üá;\õx¸€É£0ÙàÞ§D¦ÏáÃE§vr»ÜêØÅ–»Øg°ŸƒÏÔ{øvY]öfI'ø¾ B Y²¢'À®ãeÐdXö*CgØUÇÙ€z»KÀ6ÍUúò×Í|ñån6¿ý6é+ÑñK°«¤@Ù(Q„‚ï jo^o¼å¤›ÈuŒ ²Þ0»»»¹›@³á¬pã ¼X¦ÅÈ— ðHgÝp¬°OÄ®»M’º3ˆðn$îñx󂢞s&pý O¯¯góù¸@÷8 IïF ^/+Ý„QNñ€W=~xf¾Çëñ.æ°yÍ ­6m5Ç a©˜Åã'ñºhB>2¬úAùLž&o¨ŸŸÌ2Ð;^•¿+‹v‰›Ù¶8ÿO#xÛÒuªYAÓOAF,8—•¶j¢ð@—²e«$ÞÕ{¿™¯·´¾Šwåmµšg牤†NÆ»®†zcq®w(f/O 览0Œ‡} X7èÕ`e¤o‰’-7)~¨ê’0—¦a×·³ær„€ M#ù}oHÅí¨×Ã)X„\ôÜD:™ì|Çwn}¹fülýAÍ›$^¾A1Ý?¨8Djk½iKqþûMQ:] endstream endobj 273 0 obj [ 272 0 R 274 0 R 275 0 R ] endobj 271 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 273 0 R /Contents 276 0 R >> endobj 277 0 obj 1256 endobj 259 0 obj << /Type /Action /S /GoTo /D [278 0 R /XYZ 72.0 720.0 null] >> endobj 279 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 203.612 210.0 212.612 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 254 0 R /H /I >> endobj 281 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 191.612 216.0 200.612 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 257 0 R /H /I >> endobj 282 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 179.612 204.0 188.612 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 267 0 R /H /I >> endobj 283 0 obj << /Length 284 0 R /Filter /FlateDecode >> stream xœÅW[oÛ6~ׯ8ÈÖ5Ç«.6ÀYÓaCÑ-‹±=4}Pd:&KŽ$'ñ¿ß¡®´$Ûí²¨ÈC~çÆs>ÒŠ3óñÑÚyld <ÂmDÊ& W°†f¬ 1»¬oGø©7áàþvR‡Â/Îç/¸¸Š€g‡ÕUàçÚ²oVè«Û·=Œÿ/\Ç=28› -jJjEf)iÒÖ|k­õ°v®þtŠö>Ñé¤4q ÷ÎåÂùáƒFa±ê‹Ö(!>Ì?‹5|>—ÞÅXüæ\-FGùÊ)¢±Ýƒ®ã©ú”R¶Su²^SÒ§p­ë &r }à¡®2ûýðÇŸ¿_^ÍÞÏóËùÍÔØÁD@„o¶‹`Œ½åÜä1”º( Xe9è—¸(uiÈVÂ2,û°è|÷&|—ŒÐ€¢6·Ööa›Feœ¥-æpšÜ€(†^y¬IÓÍ.-×L ñG]X8d“gwz¶ï§•'>F@«µ 01a!ÊÒTWÍŠŽzÇù¾ûGïŽX䮃Úhfån£Úr*¸‚bEº(NçŸqŽÕ.ñ°æ+ø<¿ß®uŠÅ¦Kø+L¶º8ì<ž“.Q )ü£éU=›DϡǃÁÇ«8 íršvÃõŠ&s8íÄ;‡ \Tètz,‘ÑhM/uþÖÆDkZc,ˆç,_ÚË‹‡¸°mêU¸MJ[TföäÁ¶ÿdNÉšcãö“7K=qÆìÓAÌ•ÅÙ^ÖÞM9§| bPw“É£æp—e‰SX%á=_Wp¤ÅQ†Æ\!'T-šFF<| &¥ÝQW$X@œî‹‹Rãšœî+.( %z‚ÕÞë"Êã]Ǔ׀R„{’RNÛêÊàŸ竆Y;AÍÛÝ2òw·R•H=î9½•T%RÃndUz-ˆÓIu£}u^úiÓËNr·ë†‡KJøxDøºF–®šDÍiù‚xÜ üÀkXðê%\o’žù¦."d]BÑõ•l®ÝÁ]ßßžŸ%Y&YQžÁYªŸñÿ%Òkû¹½€w{ñÁ» î½Ïuñ˜Ü^ ×X|`ù~1±OÊÁ>8áq"]A÷šë8^j¸Z­Žwµ±¸Ä“.¦½yÁ}ÊR}ÚžäŠ0쪘héªIB|Åå¶"þ£¦%>l¤ZÐñ†OLÕÎ|ß°Ÿnõõ¢u¸»Óý´|ȳgk9^ÙkÖFû¨%]Ù·;2]ô³4+ûI®#?YØp¹ŽSìÊ<,³|–è'X‹[´œ–{÷Þ^Ì.Ä\Ħ»;zÀ!ÕØ€xkä:\V4f™4®tñ ü7–“~@a^ªyùÝh ó¤Èºç{ÿzF·UÄ÷}󄮞ϣ®¢à±÷K BïËáënð³ÀhF¿Qó™3Ïv§UãcùU'˜äNoa)>ñ£A¹.q=†Ü¥XÛFåqR^4J^ ƒÃÏá©«Æc0à]vDáŽ@Š—¡çÔeèŸ?Þ\> endobj 284 0 obj 1187 endobj 286 0 obj << /Length 287 0 R /Filter /FlateDecode >> stream xœÅXKÛ6¾ûW=$Y Vù–¸@ lm›"M¬Ñâd›^«ÑÑäìúßw(J¶,Q²}I½‘”¾™o†3Ãá~›„áoj¾¢h™L¾Õkù1Y/ ‰÷¨@ ªÇÅæ«Ö€6#xØ`°AŸ&é£ß'Ÿ¿ÀËÂxšà®¸ ü0ùØÒoÞி̀ú¿0øxº >õ½ÎÞThf×`Å 2¯âÚmõÓJµCKÎ>Iá#'ìvJM÷Ç)Çèqòf6ùù7F³õ1h}+^@•ùQ4KÐçW\Ý|A³?'÷³ÞVþ`—õvÑè>ÔaWŒ19±©ÚY¿¶Éšô!L´5Êá ª<,…ù>°€OïfLßÞÍîÞÜ=Ü# =cÀ>æ‚ô¡sJý.€Ðý³^îJB´ÈV{”­Ñ2[iô•XûæQ¸ˆ5¼Ü¥+Tf°Vlõ2ZGz…Va.ÂB£lñ¯^–^c¥ï°’+ Š¥UüW¸Ì³0ìM©ä½Š­í¼ üŒJI,«ÊÈùXm€øS&v0#9ã±€Õ¶Ñ]%~5 #~ò,5ÇÒëfí N² SÕ•A€S!ZÏt'C8ÍÈ6)õÄ›Õhs z¸EÔóVßP¯PÕÑôÁ‘}¿^ÁáÄp¤À„ËúF÷ õp7%¹§8 Pçúг}.–cðêê:ÜZSé1ß\y©p€WQqV}‚ºŸêK¸ k…O<Ì0­ÿ»ÊÅU³2êfUåäâ|¹›{ÐëÜ܃_ãæøj7÷$\àf á × ·ù )ŽKÝÜ€¢rW]ØG[Âþ2)¡šföb÷¡Wy¼¿Âã}ðµïKðZÿºþ8ùwÊÕE endstream endobj 285 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Contents 286 0 R >> endobj 287 0 obj 1573 endobj 289 0 obj << /Type /Action /S /GoTo /D [285 0 R /XYZ 72.0 720.0 null] >> endobj 290 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 85.504 198.0 94.504 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 289 0 R /H /I >> endobj 292 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 73.504 195.53 82.504 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 139 0 R /H /I >> endobj 293 0 obj << /Length 294 0 R /Filter /FlateDecode >> stream xœÅWÛnÛF}×W R °h³7rw6€l+½ÀubXm¢<ÐÒÊfA‘¶HÕ6Šþ{gIвÈ•¾¸" ./gÎÜvfø0`@ñº“2fËÁC}â ÂúV“„°„z@âÞz±à›žª—pqŸé€ÂOƒ/_ñá(´-®_®^ð»'ôÕù_j ÿ_4¸Ú‚⊴bS¢EuïT‚Ü£¤v[}®¤VËJ¹ê¼W)ºÕ‰úR«ûzän§“Á»0 “Å6i•À;Dsã~&Kør°ã¯0ùu0žtBùÊ.ëDÑq7Æ êUM)e;6•‘UµM•I—ÑÒVFy| 5pCh¸÷uøüËäçáùøÃè÷‹Éð|4Ž®ÇpìU¢L3bBäSRvEM9Wm€é44ã';[¶¹ŽšÕM6n.²E³œeóíëqq×\¼ÛE´NŠá<*¢›(·o_[§óæªÈ<|ù½Å‹ØÎ[† ë$CõCŒ®}½! ‡+ÃA¨¡hsX~‹f«lØXtt€DF±šìú9-¢§ Ðx˜Ó„IÆÃ:¿¡üµ,ÑÒó¦óà°í¸#¥‡c£’{º«g¡°+Ýc }Â÷+›=l‚úØ\þìeÂkÑï¹Ð‡ÃÄdH´’UèÑêv½´i‘C„¹öG”¬m¾_i6ňԸ-¸~uö1s¦v`£¢Yÿea#²›?í¬ ýüFM9Úf‚®ÏüÜÈ.âüÊ]éàý”˜„1…{‚×>ßõ·—´ :·…]-ãÔÎáæŠ;[‡ °Nز¢Äémy?‰0uìÓ=>Ïã,…8íK$ŒiÀ°HÊ<¬½ÞŠöaÉáŒâR¶2êÜæ³U|_ â½•=4­„ødW‹lµì1U ‚0T·\ Tªš¼—™ Jh€ö xà›F´Ÿ^é>ʡ۾%FcwFñR×­jü-ï“íVö`!\è¤+%uÑî’wÛŠ(KÈKÖŸï~8»¸¾º~‹’$7…Õ°°Sž•!}x·Cö†`éfM©<`X¬ÓY©t3`!¶:WgBæ‘Ò_!µêÂ2z†<¾u´«U¶BE}ÔÛËœ8¸ƒ3ƒp)¾qiVàÐrhˆØŸ&!¶…;HU×ÖÂ(ɳæ3kû•ƒ)rAÜ\ŒŸ:ågN§¦âLÄÎ[U^vlm}¼9¹"Ø‘ÛñEWî¾B] wÇ¿¤#Þ¶ endstream endobj 291 0 obj [ 290 0 R 292 0 R ] endobj 288 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 291 0 R /Contents 293 0 R >> endobj 294 0 obj 1174 endobj 296 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 678.764 162.0 687.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 79 0 R /H /I >> endobj 298 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 666.764 180.0 675.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 120 0 R /H /I >> endobj 299 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 654.764 222.0 663.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 144 0 R /H /I >> endobj 300 0 obj << /Type /Action /S /GoTo /D [288 0 R /XYZ 72.0 720.0 null] >> endobj 301 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 642.764 246.0 651.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 300 0 R /H /I >> endobj 302 0 obj << /Length 303 0 R /Filter /FlateDecode >> stream xœÅTMoÂ0 ½çWø¸Ú9I“4G¶±/¡IˆJÐÍ6¤ÒµûùKI-´BìÀÚƒ-'~~öK²"Ðþ^e”f0_’U£ pY‡„øLÀj_@Zíj8lëYã6Yç¦$#÷döb@›°&¸·Ižq£~µ‚g¯ðN®#ru'€"Do»qéKªµ5‡ÐçLWƒh ³‹écôàÝ¢Áõ`2¼|è‰ £V7œ²èfÜâ`ULù{:o²¹‹Ùˆª–ÒZ‚Ú:Tç:rÎö’Â'lRjK|Öâýê*n#~ØRU`¯”gÙŠUíßf,u«jˆˆ´ÕÓFYU÷äZšƒ´ÈÛá!pô•»ó\½?$<8øó<Ë̼윓 Ø©€É¢8‚)‚¿czŸyžš¤ZÊS¡×‹òÃKÌ[ü•–^—ñk\˜ü1}û‚†Z+Z ôœ—¦p,GjopˆÌbiÑäЪÝqÀ)“¹°( †m’> endobj 303 0 obj 423 endobj 305 0 obj << /Length 306 0 R /Filter /FlateDecode >> stream xœÅSKoÂ0 ¾çWø¸ò I{,öšTÄqèFH<„Ú‰ýü9$Œ>Ô+K¶ì|¶?͉p`øÖèXÀçžœ|Œƒ •… xŸŠöàývöVÅW»„Îæä@<“Å“+`8Ö,wOIZéo3ìîý|‘!½qœYßVÄåÃ#9DTŠØf‹‡ù«y †£q2›˜`˜˜dLGK0oddj¬$ÿÀ*­Í€Êj¡iCï ZºF\!›Úy)¼uUë†s¶s(v›‰UGªK}׿Ý*k‰ÕÔ E§”w^YKEÛû ŽŽªÚ”×8]”Õž“£ô~,ó±êãæúȘ2¥°Räçm¹ Vù:ûÞ•Á*+³¬È¯ÚE÷Û%`[@WŒjabA·/Lñ6øi2M'ý„°X¤¢(íÆùO™Šíñ@+J¦äÙañ endstream endobj 304 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Contents 305 0 R >> endobj 306 0 obj 353 endobj 308 0 obj << /Type /Action /S /GoTo /D [17 0 R /XYZ 72.0 720.0 null] >> endobj 309 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 680.124 149.98 689.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 308 0 R /H /I >> endobj 311 0 obj << /Type /Annot /Subtype /Link /Rect [ 529.438 680.124 539.998 689.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 308 0 R /H /I >> endobj 313 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 668.124 180.461 677.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 312 0 R /H /I >> endobj 314 0 obj << /Type /Annot /Subtype /Link /Rect [ 534.926 668.124 539.926 677.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 312 0 R /H /I >> endobj 316 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 656.124 176.22 665.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 315 0 R /H /I >> endobj 317 0 obj << /Type /Annot /Subtype /Link /Rect [ 534.996 656.124 539.996 665.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 315 0 R /H /I >> endobj 319 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 644.124 174.0 653.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 318 0 R /H /I >> endobj 320 0 obj << /Type /Annot /Subtype /Link /Rect [ 534.997 644.124 539.997 653.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 318 0 R /H /I >> endobj 322 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 632.124 195.66 641.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 321 0 R /H /I >> endobj 323 0 obj << /Type /Annot /Subtype /Link /Rect [ 534.996 632.124 539.996 641.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 321 0 R /H /I >> endobj 325 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 620.124 193.56 629.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 324 0 R /H /I >> endobj 326 0 obj << /Type /Annot /Subtype /Link /Rect [ 534.998 620.124 539.998 629.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 324 0 R /H /I >> endobj 328 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 608.124 190.77 617.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 327 0 R /H /I >> endobj 329 0 obj << /Type /Annot /Subtype /Link /Rect [ 534.996 608.124 539.996 617.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 327 0 R /H /I >> endobj 331 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 596.124 189.11 605.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 330 0 R /H /I >> endobj 332 0 obj << /Type /Annot /Subtype /Link /Rect [ 534.996 596.124 539.996 605.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 330 0 R /H /I >> endobj 333 0 obj << /Type /Action /S /GoTo /D [20 0 R /XYZ 72.0 720.0 null] >> endobj 334 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 584.124 336.718 593.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 333 0 R /H /I >> endobj 335 0 obj << /Type /Annot /Subtype /Link /Rect [ 534.76 584.124 539.76 593.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 333 0 R /H /I >> endobj 336 0 obj << /Type /Action /S /GoTo /D [20 0 R /XYZ 72.0 514.852 null] >> endobj 337 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 572.124 297.796 581.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 336 0 R /H /I >> endobj 338 0 obj << /Type /Annot /Subtype /Link /Rect [ 534.839 572.124 539.839 581.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 336 0 R /H /I >> endobj 339 0 obj << /Type /Action /S /GoTo /D [20 0 R /XYZ 72.0 299.872 null] >> endobj 340 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 560.124 189.0 569.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 339 0 R /H /I >> endobj 341 0 obj << /Type /Annot /Subtype /Link /Rect [ 534.996 560.124 539.996 569.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 339 0 R /H /I >> endobj 342 0 obj << /Type /Action /S /GoTo /D [20 0 R /XYZ 72.0 264.073 null] >> endobj 343 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 548.124 264.725 557.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 342 0 R /H /I >> endobj 344 0 obj << /Type /Annot /Subtype /Link /Rect [ 534.76 548.124 539.76 557.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 342 0 R /H /I >> endobj 345 0 obj << /Type /Action /S /GoTo /D [20 0 R /XYZ 72.0 162.589 null] >> endobj 346 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 536.124 264.725 545.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 345 0 R /H /I >> endobj 347 0 obj << /Type /Annot /Subtype /Link /Rect [ 534.76 536.124 539.76 545.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 345 0 R /H /I >> endobj 348 0 obj << /Type /Action /S /GoTo /D [23 0 R /XYZ 72.0 572.619 null] >> endobj 349 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 524.124 232.16 533.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 348 0 R /H /I >> endobj 350 0 obj << /Type /Annot /Subtype /Link /Rect [ 534.837 524.124 539.837 533.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 348 0 R /H /I >> endobj 351 0 obj << /Type /Action /S /GoTo /D [23 0 R /XYZ 72.0 439.062 null] >> endobj 352 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 512.124 230.513 521.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 351 0 R /H /I >> endobj 353 0 obj << /Type /Annot /Subtype /Link /Rect [ 534.838 512.124 539.838 521.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 351 0 R /H /I >> endobj 354 0 obj << /Type /Action /S /GoTo /D [23 0 R /XYZ 72.0 293.505 null] >> endobj 355 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 500.124 310.048 509.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 354 0 R /H /I >> endobj 356 0 obj << /Type /Annot /Subtype /Link /Rect [ 534.601 500.124 539.601 509.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 354 0 R /H /I >> endobj 357 0 obj << /Type /Action /S /GoTo /D [23 0 R /XYZ 72.0 147.948 null] >> endobj 358 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 488.124 266.931 497.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 357 0 R /H /I >> endobj 359 0 obj << /Type /Annot /Subtype /Link /Rect [ 534.761 488.124 539.761 497.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 357 0 R /H /I >> endobj 360 0 obj << /Type /Action /S /GoTo /D [29 0 R /XYZ 72.0 720.0 null] >> endobj 361 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 476.124 222.61 485.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 360 0 R /H /I >> endobj 362 0 obj << /Type /Annot /Subtype /Link /Rect [ 534.857 476.124 539.857 485.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 360 0 R /H /I >> endobj 363 0 obj << /Type /Action /S /GoTo /D [29 0 R /XYZ 72.0 665.661 null] >> endobj 364 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 464.124 193.44 473.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 363 0 R /H /I >> endobj 365 0 obj << /Type /Annot /Subtype /Link /Rect [ 534.997 464.124 539.997 473.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 363 0 R /H /I >> endobj 366 0 obj << /Type /Action /S /GoTo /D [29 0 R /XYZ 72.0 324.527 null] >> endobj 367 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 452.124 259.509 461.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 366 0 R /H /I >> endobj 368 0 obj << /Type /Annot /Subtype /Link /Rect [ 534.773 452.124 539.773 461.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 366 0 R /H /I >> endobj 370 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 440.124 206.947 449.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 369 0 R /H /I >> endobj 371 0 obj << /Type /Annot /Subtype /Link /Rect [ 534.921 440.124 539.921 449.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 369 0 R /H /I >> endobj 373 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 428.124 208.592 437.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 372 0 R /H /I >> endobj 374 0 obj << /Type /Annot /Subtype /Link /Rect [ 529.941 428.124 539.941 437.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 372 0 R /H /I >> endobj 375 0 obj << /Type /Action /S /GoTo /D [57 0 R /XYZ 72.0 409.841 null] >> endobj 376 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 416.124 209.16 425.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 375 0 R /H /I >> endobj 377 0 obj << /Type /Annot /Subtype /Link /Rect [ 529.941 416.124 539.941 425.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 375 0 R /H /I >> endobj 378 0 obj << /Type /Action /S /GoTo /D [63 0 R /XYZ 72.0 636.0 null] >> endobj 379 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 404.124 212.468 413.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 378 0 R /H /I >> endobj 380 0 obj << /Type /Annot /Subtype /Link /Rect [ 529.939 404.124 539.939 413.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 378 0 R /H /I >> endobj 381 0 obj << /Type /Action /S /GoTo /D [63 0 R /XYZ 72.0 485.117 null] >> endobj 382 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 392.124 189.56 401.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 381 0 R /H /I >> endobj 383 0 obj << /Type /Annot /Subtype /Link /Rect [ 529.997 392.124 539.997 401.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 381 0 R /H /I >> endobj 384 0 obj << /Type /Action /S /GoTo /D [66 0 R /XYZ 72.0 720.0 null] >> endobj 385 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 380.124 246.86 389.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 384 0 R /H /I >> endobj 386 0 obj << /Type /Annot /Subtype /Link /Rect [ 529.835 380.124 539.835 389.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 384 0 R /H /I >> endobj 387 0 obj << /Type /Action /S /GoTo /D [69 0 R /XYZ 72.0 720.0 null] >> endobj 388 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 368.124 197.33 377.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 387 0 R /H /I >> endobj 389 0 obj << /Type /Annot /Subtype /Link /Rect [ 529.997 368.124 539.997 377.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 387 0 R /H /I >> endobj 390 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 356.124 250.66 365.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 90 0 R /H /I >> endobj 391 0 obj << /Type /Annot /Subtype /Link /Rect [ 529.997 356.124 539.997 365.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 90 0 R /H /I >> endobj 392 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 344.124 325.65 353.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 113 0 R /H /I >> endobj 393 0 obj << /Type /Annot /Subtype /Link /Rect [ 529.996 344.124 539.996 353.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 113 0 R /H /I >> endobj 394 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 332.124 256.21 341.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 139 0 R /H /I >> endobj 395 0 obj << /Type /Annot /Subtype /Link /Rect [ 529.999 332.124 539.999 341.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 139 0 R /H /I >> endobj 396 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 320.124 284.54 329.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 87 0 R /H /I >> endobj 397 0 obj << /Type /Annot /Subtype /Link /Rect [ 529.998 320.124 539.998 329.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 87 0 R /H /I >> endobj 398 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 308.124 303.97 317.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 166 0 R /H /I >> endobj 399 0 obj << /Type /Annot /Subtype /Link /Rect [ 529.997 308.124 539.997 317.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 166 0 R /H /I >> endobj 400 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 296.124 191.22 305.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 79 0 R /H /I >> endobj 401 0 obj << /Type /Annot /Subtype /Link /Rect [ 529.997 296.124 539.997 305.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 79 0 R /H /I >> endobj 402 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 284.124 266.77 293.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 109 0 R /H /I >> endobj 403 0 obj << /Type /Annot /Subtype /Link /Rect [ 529.996 284.124 539.996 293.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 109 0 R /H /I >> endobj 404 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 272.124 230.1 281.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 229 0 R /H /I >> endobj 405 0 obj << /Type /Annot /Subtype /Link /Rect [ 529.997 272.124 539.997 281.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 229 0 R /H /I >> endobj 406 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 260.124 289.0 269.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 207 0 R /H /I >> endobj 407 0 obj << /Type /Annot /Subtype /Link /Rect [ 529.997 260.124 539.997 269.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 207 0 R /H /I >> endobj 408 0 obj << /Type /Action /S /GoTo /D [217 0 R /XYZ 72.0 720.0 null] >> endobj 409 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 248.124 225.66 257.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 408 0 R /H /I >> endobj 410 0 obj << /Type /Annot /Subtype /Link /Rect [ 529.998 248.124 539.998 257.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 408 0 R /H /I >> endobj 411 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 236.124 207.33 245.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 120 0 R /H /I >> endobj 412 0 obj << /Type /Annot /Subtype /Link /Rect [ 529.996 236.124 539.996 245.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 120 0 R /H /I >> endobj 413 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 224.124 250.1 233.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 144 0 R /H /I >> endobj 414 0 obj << /Type /Annot /Subtype /Link /Rect [ 529.997 224.124 539.997 233.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 144 0 R /H /I >> endobj 415 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 212.124 223.99 221.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 192 0 R /H /I >> endobj 416 0 obj << /Type /Annot /Subtype /Link /Rect [ 529.997 212.124 539.997 221.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 192 0 R /H /I >> endobj 417 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 200.124 281.19 209.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 155 0 R /H /I >> endobj 418 0 obj << /Type /Annot /Subtype /Link /Rect [ 529.997 200.124 539.997 209.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 155 0 R /H /I >> endobj 419 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 188.124 204.0 197.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 189 0 R /H /I >> endobj 420 0 obj << /Type /Annot /Subtype /Link /Rect [ 529.997 188.124 539.997 197.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 189 0 R /H /I >> endobj 421 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 176.124 181.78 185.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 194 0 R /H /I >> endobj 422 0 obj << /Type /Annot /Subtype /Link /Rect [ 529.997 176.124 539.997 185.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 194 0 R /H /I >> endobj 423 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 164.124 239.55 173.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 254 0 R /H /I >> endobj 424 0 obj << /Type /Annot /Subtype /Link /Rect [ 529.998 164.124 539.998 173.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 254 0 R /H /I >> endobj 425 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 152.124 246.77 161.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 257 0 R /H /I >> endobj 426 0 obj << /Type /Annot /Subtype /Link /Rect [ 529.996 152.124 539.996 161.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 257 0 R /H /I >> endobj 427 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 140.124 232.89 149.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 259 0 R /H /I >> endobj 428 0 obj << /Type /Annot /Subtype /Link /Rect [ 529.998 140.124 539.998 149.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 259 0 R /H /I >> endobj 429 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 128.124 227.33 137.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 267 0 R /H /I >> endobj 430 0 obj << /Type /Annot /Subtype /Link /Rect [ 529.996 128.124 539.996 137.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 267 0 R /H /I >> endobj 431 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 116.124 226.76 125.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 289 0 R /H /I >> endobj 432 0 obj << /Type /Annot /Subtype /Link /Rect [ 529.996 116.124 539.996 125.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 289 0 R /H /I >> endobj 433 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 104.124 275.64 113.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 300 0 R /H /I >> endobj 434 0 obj << /Type /Annot /Subtype /Link /Rect [ 529.999 104.124 539.999 113.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 300 0 R /H /I >> endobj 436 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 92.124 242.997 101.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 435 0 R /H /I >> endobj 437 0 obj << /Type /Annot /Subtype /Link /Rect [ 529.785 92.124 539.785 101.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 435 0 R /H /I >> endobj 439 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 80.124 292.87 89.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 438 0 R /H /I >> endobj 440 0 obj << /Type /Annot /Subtype /Link /Rect [ 529.996 80.124 539.996 89.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 438 0 R /H /I >> endobj 441 0 obj << /Length 442 0 R /Filter /FlateDecode >> stream xœÅÝK—×uàù¹>†²×bVDì}^CJ$»Ð‹Ö‹ð*»Z„ËìE‘2U]ß¾cßfÞ ”¿‰Ûˆ ÿçf?ycç‰ÿþ‹ýÕvþÿõ?c¯þø§_üû»·¿Ç«èïþUë¯ö|8Ú«?½z÷ÏíÕWUýäŽÿéüŸÇèü‡{õ_~ñõ/¶Wÿ×/þÛÿ8ÿ㯶sÁÿþÅöüån‹?ûÅïòñë¿lÿáÿ§ŸAìÇÿ/ŸÁïŸ*Œc<<³¹­ŽÇwþ›ÇªÿôÕ»_¶wÿûøªÿøøÉ=þïÏ~RÛûÏi»þEy÷éþÇ}ðíÕÿüůÞüâ?}Ò^íÛ«7ÿúþ7툇Û¶í3Îÿô0Uÿw¼zó§Wÿí—_~ùåßýWoþï_|üæõ?øïγ>ö_~Zçç~úÎúy<ùÙå¬Ïs¼ûY=þ¤Þ|þ/_½}õÍ¿¾úõ7_ÿöëï¿{ü)^üÚœ«c<Œ­Ÿ/{ÌÇÕ¿ûöí¿~þÇ·kÞÿ*އU=Î?íwK^ýÝ™Ôç÷ê—Ï–Íý¡·ã\—q¿ìáyœˆ×&qHÜ%^ïÛAu£zJ½‹â¾ cý¶úÈýÉýÊý(Ëýü‹äâÐ]‡ÄMâ qî§Äâ¶Iw‰E°‹`Á.‚C‡œ"8EpŠàÁ%‚K;;;;‡†††¦¦¦¦6l"ØÞ½¡™ÛÅûÓ»ºïT'ÕCê±QTwª—Ôó ºQM–‹,Y.±ßCmíü5Ì9^RÕê%uT7ª§Ôm§:©Rw²ìdÙɲ“å ËA–ƒ,'YN²œd¹Èr‘å"Ë%–Ç&–Ç&–Ç&–Ç.–Ç.–Ç.–Ç!–Ç!–Ç!–ÇA–A–A–A–I–I–I–,Y6²ldÙɲ“e'ËA–ƒ,YN²œd9Ér’å"ËE–K,cËØÄ26±Œ],cËØÅ2v±ŒC,ãË8È2È2È2È2É2É2É2ɲ‘e#ËF–,;Yv²d9Èrå ËI–“,'Y.²\d¹Ä27±ÌM,sËÜÄ2w±Ì],sË<Ä2±Ìƒ,iî“4÷Išû$Í}’æ>IsŸ¤¹OÒÜ'iî“ç{ûˆ†“Í<ßã¯ó²àúcìÏêq¼:¿JIsŸ¤¹OÒÜ'iî“4÷Išû$Í}’æ>IsŸ¤¹OÒÜç6ËÝ×¶mGÊôô6Í]g{5t½æŽxÖüç/¿ûþ›oÿÏÝPö"}ü,æC»˜á¶‡>s­Ñúýº»iDíry]»Ü¡Nª‡ÔµËê ºS½¤®]îP“ee’e’e’e#ËF–,Yv²ìdÙÉrå ËA–“,'YN²œd¹Èr‘åËÛQP‹åí0ƒ—×»XÞŽ3€Z,o¼¼>Äòv¤Ôdddd™d™d™d™dÙȲ‘e#ËN–,;Y²d9Èrå$ËI–“,Y.²\by;Ýj±¼nµXÞN7€Z,o§¼¼>ÄòvºÔddddd™d™d™dÙȲ‘e#ËN–,;Yv²d9Èrå$ËI–“,Y.²\d¹ÄòvºÔb™4÷Išû$Í}’æ>IsŸ¤¹OÒÜ'iî“4÷Išû$Í}’æ>IsŸ¤¹OÒÜ'iîó8Ã=¯¥÷«AëÏOOg¸cÛê|´»uCÜó]êÓæwß¾ýöí¿ÿðåw_~ÿö»«9d¯ó~{¿_ùøYí÷Ý:ƒº¯µzÏûU÷SÀíá¼Bض<ÆKê ºS½¤>ß…HݨžRŸïB¤Nª‡Ô,;Yv²ìd9Èrå ËI–“,'Y.²\d¹Èr‰e µXÖùPïbYçH-–u>€ÔbYçHM–A–A–A–I–I–I–,Y¶~ûÊ=×¶¿¤^RŸïT¤nTO©ÇNuR=¤žÕA5YN²\d¹Èr‰e µXÖùPïbYçH-–u>Ô‡XÖùR“eeee’e’e’e’e#ËF–,;Yv²ìd9Èrå ËA–“,'YN²\d¹Èr‰e µXÖùR‹e µXÖùPbYçHM–A–A–A–A–I–I–I–,YÖx©Å²îƒ—Z,ë>x¨±¬ûà¥&Ë Ë Ë Ë Ë$Ë$Ë$ËF–,Yv²ìdÙɲ“å ËA–ƒ,'YN²œd¹Èr‘å"Ë%–u¼ÔbY÷ÁC½‹eìbY÷ÁC}ˆeÝ/µXÖ}ðPYYY&Y&Y&Y6²ldÙȲ‘e'ËN–,Y²d9Ér’å$ËI–‹,Y.±¬ûà¥˺ê],ë>x©Å²îƒ‡úË<Ä2iî“4÷Išû$Í}’æ>IsŸ¤¹OÒÜ'iî“4÷©™åùNlÍ1–L ßí¡\³Í¼_÷nlùŸ>é¯öíÕ›}2Àܷ燠þã'Ÿ¼þqE{¾¢öpŽwFÞ¯½}Šç¡‹ƒNÏ?Y+GÌ‹…÷ÓÌfù<ó±mí%ñùgâ”x@|þ€8$î/ˆÛ!q“X»vì"8DpˆàÁ!‚S§N\"¸Dp` 9!ÁqB ‚5à„k¼ùòøÁnB,‚!‚!‚!‚!‚)‚)‚)‚M›Öó-ϯÞså}³<,ï–/ÊÇay³|R>wËÓrS]¦ºLu™ê"ÕpRNª5â”|'ÕrRNª5検TkÐI¹©†©†©†©¦©¦©¦©6Sm¦ÚLµ™j7ÕnªÝT‡©S¦:Mušê4ÕiªËT—©.R­ (å¤Z3PÉwR­)(å¤ZsPÉR̓Tó0Õ0Õ0Õ0Õ4Õ4Õ4Õ4ÕfªÍTk(:×YäÕ¸òçGŽ?ÝËy¿îb3gmÔ|ýÃGíùxá|»´ïÛù}¿XðøÙìq1Ýæq¾u u·ð~¢–wËåuVºäÍòIy—.yZ>(o¦ÚLµ™j3ÕnªÝT»©S¦:Lušê4ÕiªÓT—©.S]¤ZGkRNªu¸¦ä;©Öñš”“j°)ùAªuÄ&妦¦¦š¦š¦š¦š¦ÚLµ™j3ÕnªÝT»©S¦:Lu˜ê4ÕiªÓT—©.S]¤ZgoRNªuú&å¤ZçoRNªu§ä©Öœ”›j˜j˜j˜j˜jšjšjšj3ÕfªÍT»©vSí¦ÚMu˜ê0ÕaªÓT§©NS]¦ºLu™ê"Õ:“rR­ó9%ßIµN褜TÓfKi³¥´ÙRÚl)m¶”6[J›-¥Í–ÒfKi³¥´ÙRÚléq¬z¬¹®êŸŸc>™ªÞ­»šªFêÙÖŠÞ£Ï~øóŸ¿ùöû·_ÔG©/¯~ùëoþô§o¾~ÿãO¿üîÏïôúOþêíŸÞ~ýýçßùÍ×"ckžŸÉÅ{ÿ*WW$?p¿îòŠDò°¼[¾(¯+É›å“òº"‘<-'ÕÛ‰ä¤z»"‘œToW$’“êíŠòƒToW$’›j˜j˜j˜j˜jšjšjšj3ÕfªÍT»©vSí¦ÚMu˜ê0ÕaªÓT§©NS]¦ºLu™ê"ÕÛ‰ä¤z»"|'ÕÛ‰ä¤z»"‘œToW$’›j˜j˜j˜jšjšjšj3ÕfªçI[Ƕ×õËËßÇ×É8¯A¶5ÆÅºãâŠ$Û_»"©ã!^ýò³ßúþýä8_®®ˆÚÑ.^ûý«Ü­[û6Ï«§±_¬»{g{þ¶¤¼Y>)?[Rž–ÊÏß–”‡åÝrSí¦ÚMµ›ê0ÕaªÃT§©NS¦:Mu™ê2ÕEªuÂ4å¤ZgLK¾“j2M9©Ö9Ó’¤Z'MSnªaªaªaªiªiªiªiªÍT›©6Sí¦ÚMµ›ê0ÕaªÃT‡©NS¦:Mu™ê2ÕEªu5å¤Z‡PSNªu 5å¤ZQK~jEM¹©†©†©†©†©¦©¦©¦©6Sm¦Z׸õ8›¹]]‡þìµb]äΘk®ãjÝó‹ÜqÜž{ö4zýõwßþÕWW—°û>.<8?s3ÃyQÿx4õýÂç?ëÛSø$ï–¯3?ÏØyA^†”¼Y>)¯gCJž–Êëñ’‡åÝrSí¦ÚMµ›ê0ÕaªÃT§©NS¦:Mu™ê2ÕEªu3å¤Z73H¾“jÝÌ@9©ÖÍ ’¤ZóUÊM5L5L5L5M5M5M5Mµ™j3ÕfªÝT»©vS¦:Lu˜ê0ÕiªÓT§©.S]¦ºHµ¶QNªµuˆrR­­C”“jm’ü ÕÚ:D¹©†©†©†©†©¦©¦©¦©6Sm¦ÚLµ›j7ÕnªÝT‡©S¦:Mušê4ÕeªËT—©.R­­C”“jm’|'ÕÚ:D9©æAªyj¤š6[J›-¥Í–ÒfKi³¥´ÙRÚl)m¶”6[º=쯟ïÈz[4È|r7Ãݺ«½C}=‹>þú»¾}[¢N0|u{àû}ùÝûþê›Ï¿xûÅňcíñ<™»¿ønYØÛvüíü էӎ䦦¦¦š¦š¦š¦š¦ÚLµ™j3ÕnªÝT»©S¦:Lu˜ê4ÕiªÓT—©.S]¤útÚñ‚œTŸN;^“êÓiÇ rR}:íøÛùAªO§/ÈM5L5L5L5L5M5M5Mµ™j3Õ'ÓŽ— žN;îÖ]M;Öó“c>üâ6ëØëáŽ?~€‹‡¨ïç{¨1ο%Î ý‹WùëS?á[žk{´‹µ?ùðþüû{>åèçoáú9F¿úôï>÷Ÿ,<Ûýü¨ÙŽ‹…wÓ”Þ-_”Ãòfù¤¼~§Hž–Ê×f¹©.S]¤Z#5ÊIµFj’ï¤Z#5ÊIµFj”“jÔ(7Õ0Õ0Õ0Õ4Õ4Õ4ÕfªÍT[©Æ»»¿_/Êëk¥äÍòIùØ-OËås³<,7ÕiªËT—©.R­‘å¤Z#5ÉwR­‘å¤Z#5ÉR­‘妦¦¦š¦š¦š¦š¦ÚLµ™j3ÕnªÝT»©S¦:Lu˜ê4ÕiªÓT—©.S]¤Z#5ÊIµFj”“jÔ('Õ©I~jÔ(7Õ0Õ0Õ0Õ0Õ4Õ4Õ4ÕfªÍTúà˜=A5¶­õ«k–¸©Ý®ê¯GjýU=[û/ÿ|5Ý:¿jµ=¶ói]¼Ò_–ÞMŸŽ‡m¼{ Îý²ûaU³|R~^ÌPž–ÊÏ‹ÊÃònù¢|™ê2ÕEªuå¤ZçI¾“jD9©Ö9@’¤ZçQnªaªaªaªiªiªiªiªÍT›©6Sí¦ÚMµ›ê0ÕaªÃT‡©NS¦:Mu™ê2ÕEªuå¤ZçQNªuå¤ZçI~jD¹©†©†©†©†©¦©¦©¦©6Sm¦ÚLµ›j7ÕnªÝT‡©S¦:Mušê4ÕeªËT—©.R­s€('Õ:HòTë ÊIµÎ¢œTë ÊM5L5L5L5M5M5Mµ™j3Õfª5 sÛÛž0czwû¶ãbÕÕ l~²Ð»AØù–½ý­e9Ûv»]îþE~ýég¿ÿôÇÅ÷{ËΫ¼\¹VÛ‹Åï?| ßÞÿèó¯ò™Õ‰Eïô§o¾øá«·wW¶çoƜۖ{û«æîªrˆšï_ñ/ÖÝ_„¦åƒòów%åay?ócÍyÌå‹òów#åÍòIùØ-OËås³<,7ÕiªËT—©.R­í”“jmß|'ÕÚ¾A9©Öö ÉR­í”›j˜j˜j˜jšjšjšjšj3ÕfªÍT»©vSí¦:Lu˜ê0ÕaªÓT§©NS]¦ºLu‘jmß œTkûå¤ZÛ7('ÕÚ¾!ùAªµ}ƒrS S S S SMSMSMSm¦ÚLµ®â,æåµÇÏ^oÕEkßömýêÃ\]µÏ‰ùÃ_ßî¸:_éÕ/¿ûÝ÷ïôÝ_~ÿöýÿû/¿ùs=gìó¯þûß={åýü»iŶÖWãýkÜ­;Z_+{\¬»{‹[ïY%OËåõžUò°¼[¾(¯÷¬’7ËM5L5L5L5M5M5M5Mµ™j3ÕfªÝT»©vS¦:Lu˜ê0ÕiªÓT§©.S]¦ºHµ¾KO9©Öwé)'Õú.=å¤Zߥ—ü Õú.=妦¦¦¦š¦š¦š¦ÚLµ™j3ÕnªÝT»©vS¦:Lu˜ê4ÕiªÓT—©.S]¦ºHµ¾KO9©Öwé%ßIµ¾KO9©Öwé)'Õú.=妦¦¦š¦š¦š¦ÚLµ™êm„‘kíI€w‡º¬ÙãêÃ<aä|<#àIt<Ü^þvƒË¯¿ùÓŸ¾ùú³ßúþ_½ùáûo¾ýòó¯žÏêéEûöîñw/ú~ýݺ|Øúù—M‹~±îù/L=HòÚÍ&yXÞ-_”×n6É›å“òÚÍ&¹©NS]¦ºLu™ê"Õ:ö…rR­c_$ßIµŽ}¡œTëØÊIµŽ}¡ÜTÃTÃTÃTÓTÓTÓT›©6Sm¦ÚLµ›j7ÕnªÃT‡©S¦:Mušê4ÕeªËT©Ö¾!ÊIµö I¾“jí¢œTkßä©Ö¾!ÊM5L5L5L5M5M5M5Mµ™j3ÕfªÝT»©vS¦:Lu˜ê0ÕiªÓT§©.S]¦ºHµö QNªµoˆrR­}C”“jí’ü ÕÚ7D¹©†©†©†©†©¦©¦©¦©6SµÙR ÝÎ?Qïîuyùëv³Ë_f{wëÚ³|‡[>‰^ýý·ß|ñÃkGÐóÃù[¹@ÞÎ µ‹•OîÞæýh­Þã´±ÖìýbáÝ £Þã@^ïq$OËåõGò°¼[¾(¯÷8’›j3ÕnªÝT»©S¦:Lu˜ê4ÕiªÓT—©.S]¤zl¤zl¤zl¤zl¤zì¤zì¤zì¤z¤z¤z¦¦¦¦¦š¦š¦š¦ÚLµ™j}ÿ¬Ímuõ6ä~F¹Y–wËåõý3É›å“òúþ™äi¹©.S]¦ºLu‘jl¤©ÆFª±“jì¤;©ÆAªqj¤‡©†©†©†©¦©¦©¦©6Sm¦ÚLµ™j7ÕnªÝT‡©S¦:Mušê4ÕiªËT—©.RÍTs#ÕÜH5wRÍTs'ÕÜI5R̓Tó0Õ0Õ0Õ0Õ4Õ4Õ4Õ4ÕfªÍTk—â˜kIƒÉ˜ž‹¶mW ¯¦ýùB}þýçõæ|X¯~ùß|ñö«/¿þŸïÿÍÿþòñÈžÇ=¾âÕùAçõÐ8¶mÛ«ò7Î:ßv·mmÛyer±øù‡ÿÉÀd{˜ë¼fk«î§+!q—x½<®}k7‰'ÄõêåqJ< >@°vªA ‚µKíåqˆ`ˆ`ˆ`Š`Š`Š`Á&‚­Ï¿D·ãeù¢¼¾Ù$y³|R>vËÓòAùÜ,ËMušê2Õeª‹TkOå¤Z{Ò$ßIµö¤QNªµ'MòƒTkO妦¦¦š¦š¦š¦š¦ÚLµ™j3ÕnªÝT»©S¦:Lu˜ê4ÕiªÓT—©.S]¤Z{Ò('ÕÚ“F9©Öž4ÊIµö¤I~jíI£ÜTÃTÃTÃTÃTÓTÓTÓT›©6S­ËL1ÜnñsæjÄ2îOþêóï¾{<áy<ì¯~ù‡·_}^ûÓ¾{>G8ß*¬ÛÖ¸x™Ÿ¼ÂÝÂz€Ùܶãbáݼâ¼r¤<-”Ÿ×”‡åÝòEùù›ƒòf¹©S¦:Lušê4ÕiªÓT—©.S]¤ZgËQNªu¶œä;©ÖÙr”“j-'ùAªu¶å¦¦¦¦š¦š¦š¦š¦ÚLµ™j3ÕnªÝT»©S¦:Lu˜ê4ÕiªÓT—©.S]¤ZgËQNªu¶å¤ZgËQNªu¶œä©ÖÙr”›j˜j˜j˜j˜jšjšjšj3ÕfªÍT»©vSí¦ÚMu˜ê0ÕaªÓT§©NS]¦ºLu™ê"Õ:[ŽrR­³å$ßIµÎ–£œTël9ÊIµÎ–£ÜTÃTÃTm¶”6[J›-¥Í–ÒfKi³¥ÛHñÇ'¦Á´î¶këØÖ\k],œ#ÅùüºßþËÿóöß?~Œ¬±å¯¿}ûùÕ=¯õµíkµ#/^æ'/p7ÅÛöÜÏŸ\Ž‹…÷C¿°¼[¾(?/ )o–OÊÏ‹BÊÓòAù0ÕaªÃT‡©NS¦:Mu™ê2ÕEªu#(å¤Z7‚RNªu#(å¤Z7‚J~jÝJ¹©†©†©†©†©¦©¦©¦©6Sm¦ÚJu[k?ö—ä}³<,ï–/ÊÇay³|R>wËÓrS]¦ºLu™ê"Õº”rR­A%ßIµn¥œTëFPÊIµn¥ÜTÃTÃTÃTÓTÓTÓT›©6Sm¦ÚLµ›j7ÕnªÃT‡©S¦:Mušê4ÕeªËT©Ö ”“jÝ*ùNªu#(å¤Z7‚J~jÝJ¹©†©†©†©¦©¦©¦©¦©Öãˆj 6Eµ<¯V]V¬v5ÐÛ·û±_Ý?ò´úä˯¿xwwf}”ñêÝ ð~'á Ò·m‹Þ/^æ'ë/Æ~cçÊ ¯Æ~”wËåí°¼Y>)ï»åiù |˜ê0ÕaªÃT§©NS¦ºLu™ê"ÕûQNª5ö£œTkìG9©ÖØOòƒTkìG¹©†©†©†©†©¦©¦©¦©6Sm¦ÚLµ›j7ÕnªÝT‡©S¦:Mušê4ÕeªËT—©.R­±å¤Zc?ÉwR­±å¤Zc?ÊIµÆ~”›j˜j˜j˜jšjšjšj3ÕfªÍT›©vSí¦ÚMu˜ê0ÕaªÓT§©NS¦ºLu™ê"ÕÜHµÆ~”“jý('ÕûQNª5ö£œTkì'y˜j˜j˜ªÍ–ÒfKi³¥´ÙÒãØïüCr^³Ð@íÉØï~á¾_Œýöç¹}ôö«·ßÿeîígç~ç/qö¹mG\½ÎOÖß-̇m‹íÌçÅÂûÉÜ ¼Î^•<,ï–/ÊëìUÉ›å“ò:{UrS¦:Mušê4ÕiªËT—©.R­{|)'ÕºÇWòTë_ÊIµîñ•ü պǗrS S S SMSMSMSMSm¦ÚLµžë³km—_zïgg»åiù ¼žë#yXÞ-_”×s}$o–›ê2Õeª‹Të_ÊIµîñ¥œTë_ÊIµîñ•ü պǗrS S S S SMSMSMSm¦ÚLµ™j7ÕnªÝT»©S¦:Lušê4ÕiªËT—©.S]¤Z÷øRNªu¯ä;©Ö=¾”“jÝãK9©Ö=¾”›j˜j˜j˜jšjšjšj3ÕóËAn矩}Ѐì6Ç‹ùøÜû…{\ÌñŽ»§ |óõ¿úịÛtënõ³\£õ‹u?>âþ‘¹õLÛ}dmô»Xw7—¨Ö R×íj£ž¼Æ‹ò°¼[¾(¯ÛÕ$o–OÊëv5ÉÓòAy7ÕnªÝT»©S¦:Lušê4ÕiªËT—©.S]¤ZÏO¡œTë*’ï¤ZÏQ¡œTëY*”“j=O…rS S S SMSMSMSm¦ÚLµnW;¿Æïû/Êåu»šäÍòIùØ-OËåu»šäa¹©NS]¦ºLu‘j}KrR­g¬H¾“j]FPNªõŒÉR­‚rS S S SMSMSMSMSm¦ÚLµ™j7ÕnªÝT‡©S¦:Lušê4ÕiªËT—©.R­g¬PNªõŒÊIµž±B9©Ö3V$?H5RÍÃTÃTÃTÃTÃTÓTÓTÓT›©Ö®Çyœ}§±ämZúãƒiïÞMKsÞ¾(?­^?ÜžÊÒnÇ~óõ×oÿX¾ÿwŸýÅû¼þúËï¿üü«/¿»<±ž—X·C×Q÷èý«\ÌxŽ}®•{^¬»šñPž–Ê×fyXÞ-_’׌‡òf9©ÖŒ‡rR­ä©ÖŒ‡rR­äaªaªaªiªiªiªÍT›©6Sm¦ÚMµ›j7ÕaªÃT‡©NS¦:Mušê2Õeª‹TkÆC9©ÖŒGòTkÆC9©ÖŒGòƒTë妦¦¦š¦š¦š¦š¦ÚLµ™j3ÕnªÝT»©S¦:Lu˜ê4ÕiªÓT—©.S]¤Z3ÊIµf<”“jÍx('ÕšñH~jÍx(7Õ0Õ0Õ0Õ0Õ4Õ4Õ4Õfªµ!nômýj󳳑ñÌó+ÕÚ³_¬ÛóY_âòù©w}øæÃ_}øÙÇÏÇçˆmÛö«wé͇y±n>¬}¬µŽq±ðn,q¾¡<-”ŸoA(Ë»å‹òó-åÍrSí¦ÚMµ›ê0ÕaªÃT‡©NS¦:Mu™ê2ÕEªuôå¤ZGïQNªuôå¤ZGïI~j½G¹©†©†©†©†©¦©¦©¦©6Sm¦ÚLµ›j7ÕnªÝT‡©S¦:Mušê4ÕeªËT—©.R­£÷('Õ:zOòTëè=ÊIµŽÞ£œTëè=ÊM5L5L5L5M5M5Mµ™j3ÕfªÍT»©vSí¦:Lu˜ê0ÕiªÓT§©NS]¦ºLu‘j½G9©ÖÑ{’ï¤ZGïQNªuôžä©ÖÑ{”›ªÍ–ÒfKi³¥´ÙRÚl)m¶”6[z¼cw®ÕÛ¤aàÓMhw ÷v1¡ìÏèûû_ÿö7¿ùø×o>xýÉÿÓëÏÞ|ö÷wC•ùÐÿò¬»¨Ïï|¯zqën€ÓãÝÅw뮦+”OÊëÉÓò!yMW(Ë»å‹òTkºB9©Öt…rR­éŠäaªaªaªaªiªiªiªÍT›©6Sí¦ÚMµ›j7ÕaªÃT‡©NS¦:Mu™ê2Õeª‹TkºB9©ÖtEòTkºB9©Öt…rR­é 妦¦¦š¦š¦š¦ÚLµ™j3ÕfªÝT»©vS¦:Lu˜ê4ÕiªÓT§©.S]¦ºHµ¦+”“jMW$ßIµ¦+”“jMW$?Hµ¦+”›j˜j˜j˜jšjšjšjšêyuÐÖ±æØhzñt¸r·nïÕñüÔ´¿ÿèWüî·¿ýôƒøðŸ>øäüÁ»iËëßþænÎRw½ô\çòuñRõ‰ö¼8¸­î~«m{d\¬»¿üY”דy$o–OÊëÉ<’§åƒòz2äa¹©NS]¦ºLu‘êí¡!’“jÝý"ùNª·ƒ%'ÕºûEòƒTo·-KnªaªaªaªiªiªiªiªÍT›©6Sí¦ÚMµ›ê0ÕaªÃT‡©NS¦:Mu™ê2ÕEªu÷ å¤Zw¿PNªu÷ å¤Zw¿H~jÝýB¹©†©†©†©†©¦©¦©¦©6S=/fÛßÝýòò«ŠÇËŸ¾mÇÕuÍ>.®~æóSPþþ£?ùð?}óÁwÁÜ}gùv@HZ2ö‹õ·[sæÕÃÜæ8¯éÚ¶íÇÕÇ}þkP'…P–wË—äuRåÍòIù¾[ž–“jB9©ÖI!”›j˜j˜j˜jšjšjšj3ÕfªÍT›©vSí¦ÚMu˜ê0ÕaªÓT§©NS¦ºLu™ê"Õš•PNª5+‘|'Õš•PNª5+‘ü Õš•PnªaªaªaªiªiªiªiªÍT›©6Sí¦ÚMµ›ê0ÕaªÃT‡©NS¦:Mu™ê2ÕEª5+¡œTkVB9©Ö¬„rR­Y‰ä©Ö¬„rS S S S SMSMSMSm¦Úò¡ï¹íçß­2Žxœ•̵ηŠëöy1,YÏϹ–|ðæŸw71©Ý×-ê{ÄǺx‘úÇ|÷ß$>ÿôÌ£¯Õf»Xw)>)?ÿôPž–ÊÏ?=”‡åÝòEùù§‡rSMSm¦ÚLµ™j7ÕnªÝT»©S¦:Lušê4ÕiªËT—©.S]¤ZÛ°)'ÕÚ†-ùNªµ ›rR­mØ”“jmæÜTÃTÃTÃTÓTÓTÓT›©6Sm¦ÚLµ›j7ÕnªÃT‡©S¦:Mušê4ÕeªËT©Ö6lÊIµ¶aK¾“jmæœTk¶ä©Ö6lÊM5L5L5L5M5M5M5Mõ¼:ûv^&·” ×wÛ°ÏeójݱÝ_[ßöì<½¶~ý›×o^øéëÿúñGO¯¯ï7aשc{Ü¿Òíó<î/¯ëqë\ud^¬º¿*œ”×ã:%OËåõ¸NÉÃònù¢¼×)¹©vS¦:Lu˜ê4ÕiªÓT§©.S]¦ºHõö¸NÉIõö¸NÈwR½=®SrR½=®òƒToë”ÜTÃTÃTÃTÓTÓTÓTÓT›©6Sm¦ÚMµ›j7ÕaªÃT‡©S¦:Mušê2Õeª‹To딜To딜To딜Toë„ü ÕÛã:%7Õ0Õ0Õ0Õ0Õ4Õ4Õ4Õfªu9Ϋ³¹õ—_œ=¹“÷~Õ±_\BÏï÷}wßî³t¯ÇS?^-Þ-z|~èvõàÍÛãü™Ÿ—‚ ŸÿÄ÷ÛòrÔ2F{I~r@ž–ÊoCÈÃònù¢¼–7ËMµ›j7ÕnªÃT‡©S¦:Mušê4ÕeªËT©Ö9†”“jcH9©ÖNÊIõqÍËóƒT7Ð@nªaªaªaªaªiªiªiªÍT›©Þ6Ьm?ß}¼$¿m <,ï–/ÊÇay³|R~Û@yZnªËT—©.S]¤ú¸rR}Ü@óò|'ÕÇ 4“êãÈIõq 䦦¦¦š¦š¦š¦ÚLµ™j3ÕfªÝT»©vS¦:Lu˜ê4ÕiªÓT§©.S]¦ºHõq ä¤ú¸æåùNªh 'ÕÇ 4/ÏR̓T7м<S S SMSMSMSMS=¯bÎmÛrѨñéøónáq\Œ?ãùïÆŸ?Ù>óÙŤ¡F³[ãân7ÏäÕmëûëõ°Œ~\}àû«üÝò´|P^ß_—<,ï–/Êëûë’7ËM5L5L5L5M5M5M5Mµ™j3Õúþú>·}Ï«?ã÷Wù»åiù ¼¾¿.yXÞ-_”×÷×%o–›ê2Õeª‹Tc#ÕØH56RTc'ÕØI5vRƒTã Õ8L5L5L5L5L5M5M5Mµ™j3ÕfªÝT»©vSí¦:Lu˜ê0ÕiªÓT§©.S]¦ºLu‘jn¤š©æFª¹“j;©æAªyj¤š‡©†©†©†©¦©¦©¦©6S­ó0òÌ·£É%ýOϽ_v\<–òvdê“ê/wéüæÃøøùÈ .C¶:6t¿Xy{¢Ã¸:5´Îcy~f«]¬{þ³¯ 1”Êë<&ÉÃònù¢¼Îc’¼Y>)_¦ºLu‘jmˆ¡œTkC å¤z;ZFrR­ 1’¤Zb(7Õ0Õ0Õ0Õ0Õ4Õ4Õ4ÕfªÍT[©¶Ú‹{õuá~~´Y–wËåã°¼Y>)Ÿ»åi¹©.S]¦ºLu‘jmˆ¡œTkCŒä;©Ö†ÊIµ6ÄPNªµ!†rS S S SMSMSMSm¦ÚLµ™j3ÕnªÝT»©S¦:Lušê4ÕiªÓT—©.S]¤Zb('ÕÚ#ùNªµ!†rR­ 1’¤Zb(7Õ0Õ0Õ0Õ4Õ4Õ4Õ4Õº:¨›ïÎ÷2zºænÝqñh›ZòWÆS|ò‡ßþßýîã_ß]ôŽ‹µ·ÛÇÃ~ŠÌù.ç[ÎÖźû«Ø°¼[¾(?ßåPÞ,Ÿ”Ÿïr(OËåÍT›©6Sm¦ÚMµ›j7ÕaªÃT‡©NS¦:Mušê2Õeª‹TëÀÊIµÌ‘|'Õ:0‡rR­s$?HµÌ¡ÜTÃTÃTÃTÓTÓTÓTÓT›©6Sm¦ÚMµ›j7ÕaªÃT‡©S¦:Mušê2Õeª‹TëÀÊIµÌ¡œTëÀÊIµÌ‘ü Õ:0‡rS S S S SMSMSMSm¦Zæýñé¯p%úôùnݱ.®‘ûóƒuž´úlÁ~^åô¾ï½_,½]¼_œšS³ž~².=ÿÉïµßê ºS½¤®½†P7ª§ÔµÑꤚ,Y.²\d¹Ä²ß+µXÖÃ{¡ÞŲÝ+µXÖ˜Kj±¬!—Ôdddd™d™d™dÙȲ‘e#ËF–,;Yv²d9Èrå$ËI–“,'Y.²\d¹Äòvø3Ôby;úùåõ.–·ƒŸ¡ËÛ±Ï/¯±¼ú 5YYYY&Y&Y&Y&Y6²ldÙȲ“e'ËN–ƒ,Y²d9Ér’å$ËE–‹,—XÞÎv†Z,o';C-–·s¡ËÛ©Î/¯±¼é 5YYYYY&Y&Y&Y6²¬ÍÛX«Õ=?ðä£×ŸýÌaÎç[Dæ<ãbÝí„•ó=îÇRu(Ù<ÞýdîÞMêP2ÉÓòAyJ&yXÞ-_”סd’7ËMu˜ê0ÕaªÓT§©NS¦ºLu™ê"Õ:nˆrR­ã†$ßIµŽ¢œTë¸!ÉR­ã†(7Õ0Õ0Õ0Õ4Õ4Õ4Õ4ÕfªÍT›©vSí¦ÚMu˜ê0ÕaªÃT§©NS¦ºLu™ê"Õ:nˆrR­ã†('Õ:nˆrR­ã†$?HµŽ¢ÜTÃTÃTÃTÃTÓTÓTÓT›©6Sm¦ÚMµ›j7ÕnªÃT‡©S¦:Mušê2ÕeªËT©ÖqC”“j7$ùNªuÜå¤ZÇ QNªuÜ妦¦j³¥´ÙRÚl)m¶”6[ª™`ž¿ø+öNó·'ç Ý­‹«Ž×óS‰ÞO?øÝoûéÇÝ `~ræÐÝêÛ¼r{è÷£Á:¡Ò>.–ÝOJ’ê!uŒuPÝ©^P×*©ÕSê],k•ÔbY;¨¤ËÚA%5YYYY&Y&Y&Y6²ldYG l}ÛÏ? /Êåu‚äÍòIy yZ>(¯#$ËMušê2Õeª‹TkCå¤Z[ª$ßIµ6UQNªµ­JòƒTkc妦¦¦š¦š¦š¦š¦ÚLµ™j3ÕnªÝT»©S¦:Lu˜ê4ÕiªÓT—©.S]¤Z;®('ÕÚsE9©Ö®+ÊIµö]I~jí¼¢ÜTÃTÃTÃTÃTÓTÓTÓT›©Ö¬µo[äÕDäggOo¼[y?o9/YžUŸ¼þÍûgI=œ?µ¶mk¹.–>n»¶œ_ßržé‘q±înq~}“üüúFyZ>(?¿¾Q–wËåç×7ÊMušê2Õeª‹TëøhÊIµŽ¦œTëøhÊIµŽ–ü Õ:>šrS S S S SMSMSMSm¦ÚLµ™j7ÕnªÝT»©S¦:Lušê4ÕiªËT—©.S]¤ZÇGSNªu|´ä;©ÖñÑ”“jM9©ÖñÑ”›j˜j˜j˜jšjšjšj3ÕfªÍT›©vSí¦ÚMu˜ê0ÕaªÓT§©NS¦ºLu™ê"Õ:>šrR­ã£%ßIµŽ¦œTëøhÉR­ã£)7Õ0Õ0Õ0Õ4Õ4Õ4Õ4ÕÛˆû¶mÊéÉôë~]\<ݬíÏÐzý›×o^øéëÿúñ픬ºßkvd^¼Êíø®uñ¶Çkñ¹m½­‹u××âOÊo×â§åƒòÛµ8äay·|Qž¦š¦š¦ÚLµ™j3ÕnªÝT»©vS¦:Lu˜ê4ÕiªÓT—©.S]¦ºHõñZrR}¼y¾“êãµ8ä¤úx-9©>^‹CnªaªaªaªiªiªiªÍT›©6Sm¦ÚMµ›j7ÕaªÃT‡©NS¦:Mušê2Õeª‹T¯Å!'ÕÇkñ—ç;©>^‹CNª×â/ÏR}¼‡ÜTÃTÃTÃTÓTÓTÓTÓTëAãµã£í!×¹O¯ÅïÖÅÅ£œÚñüÔ ?|üsÇ]Õw!õ«Ç‹×í ½½»X¿[øüç\‡I^7,Hž–ÊëžÉÃònù¢¼îZÜT»©S¦:Lušê4ÕiªÓT—©.S]¤Z‡QNªuhä;©Ö¡A”“j$ùAªuh妦¦¦š¦š¦š¦š¦ÚLµ™j3ÕnªÝT»©S¦:Lu˜ê4ÕiªÓT—©.S]¤Z‡QNªuhå¤Z‡QNªuhä©Ö¡A”›j˜j˜j˜j˜jšjšjšj3ÕfªÍT»©vSí¦ÚMu˜ê0ÕaªÓT§©NS]¦ºLu™ê"Õ:4ˆrR­Cƒ$ßIµ ¢œTëÐ ÊIµ ¢ÜTÃTm¶”6[J›-¥Í–ÒfKi³¥Û¡Aql[ŸWùÏëžÎïÆÅ#îZ>?[è³7¾ùÇÏžO ηXc¬µæ˜knŸR=^ë~‚X“öc;?«~õÁî¦5i—|Q^“vÉ›åóÌ÷mkG{I^“vÉÓòAyMÚ%Ë»å‹òvXÞ,7ÕnªÝT»©S¦:Lu˜ê4ÕiªÓT—©.S]¤z»£RrR½ÝQ)9©ÞvqJNª·]œ¤zÛÅ)¹©†©†©†©†©¦©¦©¦©6Sm¦Z»8Ïßôó|/ô’¼vqJ–wËåã°¼Y>)¯]œ’§å¦ºLu™ê2ÕEª·]œ’“êm'ä;©ÞvqJNª·]œ’“êm§ä¦¦¦¦š¦š¦š¦ÚLµ™j3ÕfªÝT»©vS¦:Lu˜ê4ÕiªÓT§©.S]¦ºHõ¶‹SrR½íâ„|'ÕÜI5wRÍTó ÕÅÞ-Ì‹Ç:¶öüر_ÿáãß|ü³GŠÕFŒ¶mÛùíbñínÏ|8îG²c;?µcÛ2Öź«©åÝòEù<,o–OÊ×nyZ>$¯©å¤ZS!ÊIµ¦B”“jM…$?Hµ¦B”›j˜j˜j˜j˜jšjšjšj3ÕfªÍT»©vSí¦ÚMu˜ê0ÕaªÓT§©NS]¦ºLu™ê"Õš QNª5’|'Õš QNª5¢œTk*D¹©†©†©†©¦©¦©¦©6Sm¦ÚLµ™j7ÕnªÝT‡©S¦:Mušê4ÕiªËT—©.R­©å¤ZS!ÉwR­©å¤ZS!ÉR­©å¦¦¦¦š¦š¦š¦š¦ZûµÛY¬Ñeòòn(´f«}wë2.†Býùi\}üÙ›?üöŸv*tþ ;ÆvþTŽq±úö¹íãb*4öÙ×êÙ/ÖÝJvËÓòAùùΛò°¼[¾$¯gRÞ,'Õz å¤Z”ü Õz$ å¤Z”(Ÿ›åa¹©NS]¦ºLu‘j=rR­§J¾“j=rR­§J~j=rS S S SMSMSMSMSm¦ÚLµ™j7ÕnªÝT‡©S¦:Lušê4ÕiªËT—©.R­§RNªõt@ÊIµžH9©ÖÓ%?HµžH¹©†©†©†©†©¦©¦©¦©6S­¹ÍXuBú.³‘ǹMß¶ãê£äÕñèãùÁm¿ûÃoõW¶òl³¶$­š?Ý­½}b—ç³õÚž”kµëîFç—ÉÏ/)”‡åÝòEùù%…òfù¤üü]E¹©.R­B”“jm¢œTk£å¤Z…$?Hµ6 QnªaªaªaªaªiªiªiªÍT›©¶R­gt¬«¿èïGB›åay·|Q>Ë›å“ò¹[ž–›ê2ÕeªËT©ÖF!ÊIµ6 I¾“jm¢œTk£å¤Z…(7Õ0Õ0Õ0Õ4Õ4Õ4ÕfªÍT›©6Sí¦ÚMµ›ê0ÕaªÃT§©NS¦:Mu™ê2ÕEªµQˆrR­B’ï¤Z…('ÕÚ($ùAªµQˆrS S S SMSMSMSMS­Óùµx®&c§û„îÖåÕ3æóÓ¾>}ýÙ›¿Ì›îÎójçïŸØ¶mŸq±öö™Í‡¼8µù0÷8/w¢_¬»8í–§åƒò±Y–wËåó°¼YnªËT—©.R­qå¤Zã,ÊIµÆY”“j³$?HµÆY”›j˜j˜j˜j˜jšjšjšj3ÕfªÍT»©vSí¦ÚMu˜ê0ÕaªÓT§©NS]¦ºLu™ê"ÕgQNª5Î’|'ÕgQNª5΢œTkœE¹©†©†©†©¦©¦©¦©6Sm¦ÚLµ™j7ÕnªÝT‡©S¦:Mušê4ÕiªËT—©.R­qå¤Zã,ÉwR­qå¤Zã,ÉR­q妦¦¦š¦š¦š¦š¦Zã¬}?‹ÜejôdÿÔݲœ÷㬾=?1鿼~óŸvûÔùy3^Ùö‹¥ï>¯~9Í:òñóº_v5Ì’:©Rê ºS½¤žÕj²\d¹Èr‰eͯ¤Ëš^I-–5»’Z,krõ!–5·’š,ƒ,ƒ,ƒ,ƒ,“,“,“,Y6²ldÙɲ“e'ËN–ƒ,Y²œd9Ér’å"ËE–‹,—XÖtJj±¬ÙÔ»XÖdJj±¬¹”ÔbYS)©É2È2È2È2É2É2ɲ‘e#ËF–,;Yv²ìd9Èrå ËI–“,'YN²\d¹Èr‰e Ÿ¤Ë=A½‹e ž¤Ë;A}ˆe ¤&Ë Ë Ë Ë$Ë$Ë$Ë$ËÛ¬iÛ¶5†Ìt~:kº_–@ìûóƒ˜gMòá?~úæçfNu%ÞãÝ-{÷/QŸ_}“öîó»¤ÜÆZGkë®.Ê%¯“”%o–OÊë$eÉÓòAy¤,yXnªaªiªiªiªÍT›©Öß6·mÌý%y¤,yXÞ-_”×IÊ’7Ë'åu’²äi¹©.S]¦ºLu‘êí$eÉIõv’2ä;©ÞNR–œTo')KNª·“”%7Õ0Õ0Õ0Õ4Õ4Õ4ÕfªÍT›©6Sí¦ÚMµ›ê0ÕaªÃT§©NS¦:Mu™ê2ÕEª·“”%'ÕÛIÊï¤z;IYrR½¤ ùAª·“”%7Õ0Õ0Õ0Õ4Õ4Õ4Õ4Õóê Ïíñ$e¸Š~¼ÊŸçUźº€oϯ•óU?žÜóúõÃíŒ:ªùÍ¿½}ÿƒÏþÏŸþ囯¾üãOþÍï?ýéþúûÏÿßgâñ±Z}­ÜŽ‹ö~õݺ|ˆ¾¶-âbÙó_°½nt}y]÷¹BTwª—Ôu+Ôê õQ7¸B-–Ç&–Ç.–Ç.–Ç.–Ç.–Ç!–Ç!–ÇA–A–A–A–I–I–I–I–,Y¶²œkÎ-_’÷Ýò´|P^'¥I–wËåuRšäÍrS]¦ºLu‘jl¤©ÆFª±‘jì¤;©ÆNªqj¤‡©†©†©†©†©¦©¦©¦©6Sm¦ÚLµ›j7ÕnªÝT‡©S¦:Mušê4ÕeªËT—©.RÍTs#ÕÜH5wRÍTs'Õûçß¼ùðŸî./·‡zöÌjûÕ«ÔçX·ùßïñ¨Óùõ¼Xw;(¯ÓÃ%Ë»å‹ò:=\òfù¤¼N—ÜT[©Žµ¶Ëß‚÷Wœ›åay·|Q>Ë›å“òz2äi¹©.S]¦ºLu‘jíd œTk'ƒä;©ÖNÊIµv2PNªµ“rS S S SMSMSMSm¦ÚLµ™j3ÕnªÝT»©S¦:Lušê4ÕiªÓT—©.S]¤Z;('ÕÚÉ ùNªµ“rR­ ’¤Z;(7Õ0Õ0Õ0Õ4Õ4Õ4Õ4Õ:ƒâüËfëmɵâ“ûî–µ|Ì?~ó‹ßŸÿÿÿŸíus endstream endobj 310 0 obj [ 309 0 R 311 0 R 313 0 R 314 0 R 316 0 R 317 0 R 319 0 R 320 0 R 322 0 R 323 0 R 325 0 R 326 0 R 328 0 R 329 0 R 331 0 R 332 0 R 334 0 R 335 0 R 337 0 R 338 0 R 340 0 R 341 0 R 343 0 R 344 0 R 346 0 R 347 0 R 349 0 R 350 0 R 352 0 R 353 0 R 355 0 R 356 0 R 358 0 R 359 0 R 361 0 R 362 0 R 364 0 R 365 0 R 367 0 R 368 0 R 370 0 R 371 0 R 373 0 R 374 0 R 376 0 R 377 0 R 379 0 R 380 0 R 382 0 R 383 0 R 385 0 R 386 0 R 388 0 R 389 0 R 390 0 R 391 0 R 392 0 R 393 0 R 394 0 R 395 0 R 396 0 R 397 0 R 398 0 R 399 0 R 400 0 R 401 0 R 402 0 R 403 0 R 404 0 R 405 0 R 406 0 R 407 0 R 409 0 R 410 0 R 411 0 R 412 0 R 413 0 R 414 0 R 415 0 R 416 0 R 417 0 R 418 0 R 419 0 R 420 0 R 421 0 R 422 0 R 423 0 R 424 0 R 425 0 R 426 0 R 427 0 R 428 0 R 429 0 R 430 0 R 431 0 R 432 0 R 433 0 R 434 0 R 436 0 R 437 0 R 439 0 R 440 0 R ] endobj 307 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 310 0 R /Contents 441 0 R >> endobj 442 0 obj 15855 endobj 444 0 obj << /Length 445 0 R /Filter /FlateDecode >> stream xœÅTKo›@¾ï¯˜crØí²Ëóè8NÕ ¥rŒÔFQk1ˆZÿûYÀ€C.Íc™™o¾í‘Àñ¥­p<aNŽÏG€´;—eƒ0™° ‡N· ÿƊè5ú'Tð“„ÃWòòЇp øMø<ÝGðŽlGõÛ~õúÞÈ]@¾‹#ØŸ Šõž5¬Ïm’Û6f¹×>&\D㸌Ø”0ÌËP¸Ê™ 7Qš$qUvR•ù`¬Ë> endobj 445 0 obj 497 endobj 447 0 obj << /Length 448 0 R /Filter /FlateDecode >> stream xœÅTKo£0¾ûW̱=˜Ì+9f[Z©ªZ%XjWUV0M¤Š¡êî¿ï°¦5åšÁŒg<ïÏ>2^Þ‘d)`[²c/ó!Ľ(ŠA„žˆ „žà@»†ŒøâˆØMÄìà‰U á–½¼’2$ƒ†cw3¶Äï4xöøoì§d?n"ðdáZ$/" XxXvYÂËÅ&Íäã&åÙúžoÒÕ5¿|yçlá…)& GÆé†g¿äê™gr%SkšÊ“f¾øÍXŸä@€H¨ #˜Ðz•‘Ä:êT‡~‚=µ^-k“³t6)t9á0¥S„œ5ø<8’€$Þâd®±˜å™[6™bû»˜x\L8øÕ=AÛ–ó¯êú„ná‡K¸ù„š‹|_Ú4NP˜ºt««º,ëŠÂ8Ѿr|»S­[}¥²œœR:^ý0ð“I.F7mm4oŽn´ÊµáÍŸªU¿yÓªVÏÖb<ïtî ¶\ûJçN J5º¨á“[¡T[SƒQíN â+PP¼WÛv_WÞXkö ïò9£ endstream endobj 446 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Contents 447 0 R >> endobj 448 0 obj 424 endobj 450 0 obj << /Type /Annot /Subtype /Link /Rect [ 344.596 496.501 491.836 505.501 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 438 0 R /H /I >> endobj 453 0 obj << /Type /Annot /Subtype /Link /Rect [ 512.757 496.501 539.997 505.501 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 452 0 R /H /I >> endobj 454 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 484.501 252.0 493.501 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 452 0 R /H /I >> endobj 455 0 obj << /URI (http://www.lispworks.com/documentation/lw51/CLHS/Body/f_load.htm) /S /URI >> endobj 456 0 obj << /Type /Annot /Subtype /Link /Rect [ 222.766 438.89 239.986 447.89 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 455 0 R /H /I >> endobj 457 0 obj << /Type /Annot /Subtype /Link /Rect [ 245.819 438.89 536.669 447.89 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 455 0 R /H /I >> endobj 458 0 obj << /URI (http://www.lispworks.com/documentation/lw51/CLHS/Body/f_cmp_fi.htm) /S /URI >> endobj 459 0 obj << /Type /Annot /Subtype /Link /Rect [ 137.15 426.89 186.03 435.89 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 458 0 R /H /I >> endobj 460 0 obj << /Type /Annot /Subtype /Link /Rect [ 192.07 426.89 494.03 435.89 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 458 0 R /H /I >> endobj 461 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 73.489 264.0 82.489 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 438 0 R /H /I >> endobj 462 0 obj << /Length 463 0 R /Filter /FlateDecode >> stream xœÅX[oÛ6~÷¯ °—¶€i^E©Å¤«»uh3´vwAŠDÇZdÉ‘d¸þ÷;$%K–uíC?ˆ‡â¹}ç£n,×íËr«£#Q_vÝSC%”­¹=¡¦y÷9<…¡KÀ°%øÇQÑUŸOqìÓÀžà[WÕöùl¶ßïqš”Û}^Ü—8Ê7³8ì…bÓn–î%ýüö×Åìef«OÆB¼®6}ø<=´y\h»@; ½Cu³cô 5Ob.%ÓëÎøÀê­¹}M´ú À`GÌ\ç«!º3ìaÅ V^0Àö­ØE›í§U2„ccfž¡Ç ±Ø»Ã€ý¨W%Øáê„Ù¢ «ó(pÂzܦ=3Èö¡ghŸ¤)ºÕu32íkUACÝy¤ËÒTÛÙ÷øÁ9L„ÃÅSO¬óÏáf›Ž,\ ì>¡„Õ}ô Tbƒ-p'€i¶ÊÃÊRå[ÓQCk2N#S¸!t÷ª'ˆzt›¹ïcÉ!¥©¨'t -dº…¦Þiô|shÖ×Oæ]BÎÙ£lx>:+Ê¢¬/ ã&/ÌçÄé¹/šöZ:4, TýÐÌþ'€œÈä^_fg( ¶é RAZûͰºHbæ«•ŽªÑˆ €^x "^3¾ƒqeš¾±ü˜œö’üáúúÊ^©°¸ù²Q’w`þ•~íÎ…µ2èö0f“„ ð…möÿ89KœñB¹§š¤ôÖÝÕh‘T;Û.F‘ÃÜ| J~•r:™Š0*êŠ[h.Ò2?~²·_ÌpăhJÍg³ýd>+ ø°‚¡¦ûõ?>ûÚÿ ˜ß¿…Êx` endstream endobj 451 0 obj [ 450 0 R 453 0 R 454 0 R 456 0 R 457 0 R 459 0 R 460 0 R 461 0 R ] endobj 449 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 451 0 R /Contents 462 0 R >> endobj 463 0 obj 1442 endobj 435 0 obj << /Type /Action /S /GoTo /D [464 0 R /XYZ 72.0 720.0 null] >> endobj 465 0 obj << /Type /Action /S /GoTo /D [449 0 R /XYZ 72.0 720.0 null] >> endobj 466 0 obj << /Type /Annot /Subtype /Link /Rect [ 138.0 596.841 312.0 605.841 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 465 0 R /H /I >> endobj 468 0 obj << /Length 469 0 R /Filter /FlateDecode >> stream xœÅTMoÛ0 ½ûWðجJrüµã†uÀÐK;=8¶ÜhsìÄR–æßŠìH‰Ûk—E‰TöŠßÐ,iΡÚûÑÇ å%£+N€-a £CknyŸ,\ì%46ð+è ?‚ç<¬bÀ1 ·pçàU°ôò›úéù}ãÿ…Áòº )OÉMoÎÑ‘õ¡Ç™£v”m\-ª5-9»~HŠ:Nô}QFºŸ—œÂkðµc`ŠÆ m¡‡d<7ÅžïâèþŠŸÁ÷bÖÊO–lÖE“ûRL|A²3÷«šHÆLAIœž¥”Ò$±Õ«ÓvÝ·²‚Õò 7.ßlÉÉ­B‹ „eâ±Ìb|{ÂÀ)b®iF(ÃŒ‡w ÷¦1YÀÝnèÿÊZ(ç)©&†žÇÐô.·m”Ý«óh¬ì²©úNéáPiÙwÎÛ7Î6µ_6âm7¥ð²Ïdz[©´·­E+·R‹Ú¹Ö'«ˆ¯\BoÊWûC9œišÆ`ÐPV„VĹŠw{©œ­Cg Ø}ß4ðÉÙµhÊC«¯rø@J\dšT5ȵðî´l¥–¾«é·]¹nÇvXOÙyÜj©Â¹<)Gyrœ3ÁFžÃtrTjQÖb€QƒmÒ».c”ò§Úk(™&55§þ¤â›ÈSÇ1v(Þ‡Ü}ߥáXv¤†¾›òÛQGÆ)ÉM³³lExÖC„j߆–z¨®ÞÙìÕð} J}VC÷;ÀáeµƒØ?Q*ì‡&Þ¿Õ2øˆ;¾Ç endstream endobj 467 0 obj [ 466 0 R ] endobj 464 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 467 0 R /Contents 468 0 R >> endobj 469 0 obj 606 endobj 438 0 obj << /Type /Action /S /GoTo /D [470 0 R /XYZ 72.0 720.0 null] >> endobj 472 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 496.506 306.0 505.506 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 471 0 R /H /I >> endobj 474 0 obj << /Type /Annot /Subtype /Link /Rect [ 450.0 262.964 522.0 271.964 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 452 0 R /H /I >> endobj 475 0 obj << /Type /Annot /Subtype /Link /Rect [ 138.0 250.964 216.0 259.964 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 452 0 R /H /I >> endobj 476 0 obj << /Type /Annot /Subtype /Link /Rect [ 154.94 229.354 328.94 238.354 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 465 0 R /H /I >> endobj 477 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 73.486 270.0 82.486 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 452 0 R /H /I >> endobj 478 0 obj << /Length 479 0 R /Filter /FlateDecode >> stream xœÅËrÛ6ð®¯À1™1YHðÐÎ8šiÇqkKÓ´“æIÅ1EÊ$[ß 0E©öÅ•Ú]bß,õ0‰†o ÒŒ åvò`iJ ŠKb ŠhHÚ" 3TèS@z~Ì!6èˤœ`ôiòõ<\! <×1Ï&7ž~ý¿¹~ß‚8"ÿ‹7ϳ’4ä¦ãŽ (F~TذÙ_#Õ€Æ8ó{Ò(ìlÂãA±æ¾rŒî&æ“~a(Âh¾vE›Æ@ 9Éô‡ ù}}ÇèûohþÛd:?Jå‡ì(‹Z÷Á0²Ê1ÆÑ3ŸºÌ¦Ö'ãÒµØJãÔH (G$ qÂôyn¦×—®¦Áìæ*¸^~œÞ³¿¯ç—!#åÀeY'ÀÇ :GRþ!$0|Ž}*ª…(Š=’¥X5­¨%ZÔby/ª¥XÉ5ûR‰§°÷(ñˆF!Î0HNŒäÏbYW=ÃéÈ%YÈ"žeid#7ëTõŒÙˆ¦³R²bj½è>Ç99i¼ š‡"0®§ÏŒªùñ'ôßEqÒ”aœD†í²¾k·²T å ý)ŠV6çj#b)d,…HÛ ×U)Ãhæ`q¬sÚ$|”ͲÎw*¯Ê³Õ¨k„PŒYÆy[— z‚8 #ô®*¬6Ò!P¯±ÅrÀMh=\*•—w'DVBùÛåÆçÊaùú…2óƸhäC ‰ê?PWy£+duq® ‰ñªe£ªz¤°‚ΓÁ'P[ÇÒÐc^}Gæ ‰;‘—/(B!š=¦¶ö¦Ob»+Î×Iã¤z&¤üUõc0œàöÞfùJ¢éz-—ê¬Ê˜°Ä0ˆµ.Ï$ô‡Î]^*Y—¢°3™2P• Ç*´ª–F“Ócn…}®Vù:—FàJ®E[˜Q¦´ŒÑg–% ŠÓn'å3#싨K¨Úž)º£™2r=WÓØÆýç+茓È’GPúyu1rr¨åZ;áÐÊÁ÷Rîüƒ0®Z­ü¸‘…Ú;kÄ ®A ¾ž>Qè˜ía!eé°>!Ž2ßäûR”>«ƒwuµi„(Rœ "QÈ­PùRs¦}£Øúaç‡=ØxϪ­ÜTŽÐ÷¸£È'StfXù•ƒO&Ÿdpí%Pz##œ/ƒ§,ã0¦ónM`ºÎlÁt°½{Ô(´OìHî N€6¼ZdØ“~¯/zP~—‡“]–{ÉNMÀ=`Ó£&ÏØxÕ¬ëªñ› §µITÊt­.«Vß^&Qš´kãy‡ÕmYÚýG£6ò´–…=þ뺇öU{$ß pÊU½?¡æä"Ãuì5¥ÛdFüO†Sjdu¥#¼H p òŒT¾…›úDåvúÇÕðš×º9‡Å:}<âýÒ ÑI÷à®É¨¾dµê#VÝÁù·±u%ç„"È6,ùHÝu¢òï/Y£X”„,ÎàµkÔe·AA-öç¶(F1ìûð†’púªÅ%`yFÍ;¡Ý—²{M€Åk–«¶kæ³+Ë`Fp-f¯Rž°šasëÒxY4Õá_÷Š’XoKT¿‰woáG‰ÆˆÃþìÿ¡à×ðHb»ÿô÷_Ž5€ç endstream endobj 473 0 obj [ 472 0 R 474 0 R 475 0 R 476 0 R 477 0 R ] endobj 470 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 473 0 R /Contents 478 0 R >> endobj 479 0 obj 1440 endobj 482 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 709.5 312.0 718.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 481 0 R /H /I >> endobj 485 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 697.5 318.0 706.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 484 0 R /H /I >> endobj 486 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 685.5 306.0 694.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 471 0 R /H /I >> endobj 487 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 673.5 294.0 682.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 465 0 R /H /I >> endobj 488 0 obj << /Length 489 0 R /Filter /FlateDecode >> stream xœÅTM›0½ûWÌq÷µM ø˜Ý¦•ª(R6HÛjµLƒÄ‡¬Úüûk ’UÓC müÞ›yƒ÷„Å×jOr3²o×x·].°™ÍdÐÆÒæ«“€wæ# vðLrBá+yyÅÍ(øEèîýð†¬Oø›zs~ ?ÉC@>}À(ñ±DŽ-\AñqÁ·.›‡CÁËÝb5X.¬Ízi=-æŸOÖæÇ*˜¿…àYƒ¼ÆÿC^ëôÖãž=rüý´cÖpÅ5[ikF;Tqf¼(Š5ÑSIC³oJ~ÙgÏÁÛ,ÄE+o\²‰‹C g¾é­>=9NNº7-B•¦Kçj›j«Ú§V©U¤K«:äµú}6u$bü_™¢¤ºŽŠÏ®¥*uUå «ªU­/™ï¢8ÁDþ¢t=&¶þy>^$líqÛkúÎcŽÁ^µ® Æ™FE¹Ò³©ë"’/͉`§¡:dÛ"MBÀûŒH*h‹Áö‘ŽÕ[ZÛ¶{›19\"âE9žoS†Yq¼ ¦gáÃÞ¾‹’8ÖeÕÏã²ÈúÉc‘eEÞèîV’¼ëªûI'câo~H1“R4?òDÇÇN»ö:.¦&åGy%Ç”°ºIŽ…îæê¸¥ú(SaYô³RÕ;]†„BÊw !V!ñ[ÖI‘Û'-¶&‡ç¿Þ endstream endobj 483 0 obj [ 482 0 R 485 0 R 486 0 R 487 0 R ] endobj 480 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 483 0 R /Contents 488 0 R >> endobj 489 0 obj 545 endobj 452 0 obj << /Type /Action /S /GoTo /D [490 0 R /XYZ 72.0 720.0 null] >> endobj 491 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 494.556 306.0 503.556 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 471 0 R /H /I >> endobj 493 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 208.876 264.0 217.876 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 438 0 R /H /I >> endobj 494 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 196.876 312.0 205.876 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 481 0 R /H /I >> endobj 495 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 184.876 318.0 193.876 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 484 0 R /H /I >> endobj 496 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 172.876 306.0 181.876 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 471 0 R /H /I >> endobj 497 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 160.876 294.0 169.876 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 465 0 R /H /I >> endobj 498 0 obj << /Length 499 0 R /Filter /FlateDecode >> stream xœÅWKÛ6¾ëWÌ1j–/‘Ô¡œÄ Z$ llô4Ú¦w…ê‘•d$ûï;4i[¶eﺇ­÷ ’â|ß¼Gû0 ø7òqX”ÉCLFÓÛ£O“ñ»É§Ñô¯›ÙøO0;aN9aEvŠò7çúø>»pÞõÜÅ#,óÖÎ íÃÚ6æ]üã:hœ]ºÚǪ³ßÉÖ"=`‘d„f¡U€þhM½8ï9•‘”™,Ó,znº¡Ú fLŒ¦ÄŽ`˜LÁŒÍïÈp#nF3GíC1 ¶ÚáÞkbH~úž6‰ ßRJ¥‰n7wëÒU] ¶ZÂï¶X»öRv°ÔTè,“""ÜÔ•#Ï 6Šd> Z°˜W®]4ù×.¯«‹ùÈáZRÊidœ­›ª…×0!xU¯VûMwïöÌØý&æËnœÛÛ»®Ë«»3P'·;Ûõ_¯÷}IÛíwù9õŽ1ó¶8oÝÃ#ƒ°;u•O‘å—rsq䝯µ]Ý dÖhcÅYçûL;EƒoyQìŠ2ïÀÞÙ¼zFð”>”¦hòÝ–_‹Ë鯵"”!X¦õUé&¨$R Êx”›æK“ÕÊ-º‹Œ‚¢¥Bƒã˜:,·¼ê\SÙ"¶)ÐÕ[_,ÉQ¥z´”¢}¬—ù*wqéVv]„VÖyˆç¦3°hÊbé7F¹%Ì/&© Ò (ºå*WJÁH&°OëTm#·p›ºEgLónmýú¢Weªg:3šªëÈ$JÓÌìæ×Ô9m½Ìû¹ˆDØÛˆâÒÇÍ`<© †ˆƒŠê\ß=šüžÇÖ•E½ð£lt5—ÿ•ê‰q2À%Ôµ\Ïj,LÒ\Ë´ÊÑ”gxԤDR•.ù6 »ËHÑŒ(,7Ê¥Œã+·},çu‘/À˜Ø°}o;–ⶸw9®†À±´Áß~@ijúhº!ÇÿNeýœ`د3À l MÛ;Y5uÙÛ¾­Ë²®â€ŒgyÕÛlgXÜž8SÔ? T6 Ói8`£ÐûúöíCwçz~bû¯mo]î¿ÿ‚!ÅWc±K7تmVëjáéåÛmò/„Å{0 endstream endobj 492 0 obj [ 491 0 R 493 0 R 494 0 R 495 0 R 496 0 R 497 0 R ] endobj 490 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 492 0 R /Contents 498 0 R >> endobj 499 0 obj 1033 endobj 481 0 obj << /Type /Action /S /GoTo /D [500 0 R /XYZ 72.0 720.0 null] >> endobj 501 0 obj << /Type /Annot /Subtype /Link /Rect [ 434.767 514.401 539.999 523.401 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 471 0 R /H /I >> endobj 503 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 502.401 210.0 511.401 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 471 0 R /H /I >> endobj 504 0 obj << /Type /Annot /Subtype /Link /Rect [ 450.0 205.112 522.0 214.112 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 452 0 R /H /I >> endobj 505 0 obj << /Type /Annot /Subtype /Link /Rect [ 138.0 193.112 216.0 202.112 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 452 0 R /H /I >> endobj 506 0 obj << /Type /Annot /Subtype /Link /Rect [ 154.94 172.681 328.94 181.681 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 465 0 R /H /I >> endobj 507 0 obj << /Length 508 0 R /Filter /FlateDecode >> stream xœÅËrÛ6ð®¯ÀL/ÉLˆ‚ A€‡vÆqÔŒ;ŠGjÓL’LA')óÇß4EÉî%MÚö}Ñw3øïéS”ìfwöÌGœ¢ ²G,B~ˆ)C;da†2M5hÁ!`‹>ÎòAogŸ¿Âå`¸Ÿ‘±¸–y9»è×7ä§ëZøô±àúñ+pÊñèmZîÀœÁ‰¤¯26ûk¤Ðg~EœMd:(ÖÜŸ§œ ÛÙëÕì×?ò Zm\ÒòN° ±þGÑj‡>¿`üåW´ús6_<åOÙÁ+jݽ3`:¼ª „ø|j_–[ŸŒK—r§ŒS1¢1&ÓôÂ0,®ÎÏ‹OÞüòìõbî-¯Þ‡ùÙ›ùoùéruö2Òz4Œq)$ò¥}¡”0`;d@‹"‘Yö€T.o2…ª»F– Ý”2ù¦jT*¹V%ªòZþÀc|±ÐÇ$& 82‚ßɤ,:†ãŒbÌ|ÇÜ·\¶ª:ÆxB“O £„…–µÿF~‹p‚23ÞzÆ[¯ºË<ã¢W ôºØñhJÝo¿£§=óû>¶Àò•·ÍNåu…d¾FˬQÕ©\ñY€E1 "f³«È~†jA0÷Cx‹ 4ŒoT•”é¾N‹üdv’‡4‘Âj\5e^¡—ÈãôµEîàz«yë›5=nbëðû´ÞMí’­ÌoÓüöˆð1UËzxÝ$Û!§H=hQÌ£ÒŸÆÞŽù&Þ;ô0èb‡JUÕEé2Ë ƒì³SŸ~^ëÙÑòƒ)ntŸfTªª!«Ój‹tô’¦,!Ùlí¢Vò3r‡†>¤{ÀlîÌÈÝ>;ª¢B($» ¶þ/òZåkµ†rÝ÷E]ôàêÁ¦¤yÊÚ¤™#ße'ÅÚ]ÜoÓ6 z©•S¼ud¶½õ†Ø6×_w‰f…öyj5º4=}›72s¢Å{ªÑ˜ãPÀ@Cö1„~Á_žìT_^Žˆ„fqDä-õÐbŒÑùÕ›9úkyqù-?½{}µ¸8GºÆíPÒ$"ƒàùêCvÂûq*dÚy6ϧs>°m„”øÄ–Ô2…Ôšo6*©O¦}H8&LÏSÞ½bnRÈ>kµ‘Mf¦¨.M5œ á#aQ„Âö#BåžöQ–9¤[Ç-ÐL šÏcÁ»Â;_À;5:Ž0¸Iý‡¼ºÿ Šdv™¶%Ô¡…ƒ¿)µB 9´Ø8ø~« å€Ö4uƒ¸¦nð­è“™ŽÙƒ;¸Q*w˜)Š5v'«m:`Od>duð¾,nÆ-YG1 G‘ÈÔNÖi¢9©ÀzÓÆÁÖƒ8?,a5¸+vj[Ü»ƒuZµ–»õ£VeÞ®`N~áà£Ocظ"ØcF'8ºø g±œO0;õràͦ©›r๬kµÛ×Õ´áv¡m"ð<©vádûºg™ÃÖ…ƒó¢ÞBuxž}sZ=T`•Ã5Í·Êái=€烌3Ã3']Žl'Ä[¹ß›µ’7C T©Ž(Í'B"Ä($Æ’WšÍ‡á mv'ƒä…ƒmz HÛ‘jaé@;T-Ö­L–¥r0ÔK¢*3£í‘ŠË 9¸k§³…“b·-ÞcU²ª\À޲ؠ7Ø•'j•2ŠL„´]L™Î3›0-lÇH‡…öƶäîÀ ІgJ‹ÄÝÑUùªÕwÕS¶¯ÜIvjÚ¶ìû0jð1‰W驲,Ê ¿}Ý­ñ9³ßnæ¡8Ó¹š ,\¥y(ÞîXãy‹•Mžwû5sÛ5ë-Ã~±é ‡¢9ï8åuùpDÍñ%š‹ ¬)íПðŸ†#ú‰/·©¥9 'x‘Dà¼3ªÓL:¨”ó÷ <¡–?±ˆ„ýÓÅR)tÔ=˜5q¨‡¬V}Àª â‰Ð 7(‹N Ez3†©'³vœÔé÷ç,ûŒSL‚€Pk¿QÛ¥ÒèæáÔâÃbhû~LÅú4`ðÀÇt,üuŸ‰j?Lay^¦uÓóÉ­+ õºÆœðÝퟒ®gÿ¤ƒíÓ endstream endobj 502 0 obj [ 501 0 R 503 0 R 504 0 R 505 0 R 506 0 R ] endobj 500 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 502 0 R /Contents 507 0 R >> endobj 508 0 obj 1590 endobj 510 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 678.764 264.0 687.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 438 0 R /H /I >> endobj 512 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 666.764 270.0 675.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 452 0 R /H /I >> endobj 513 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 654.764 318.0 663.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 484 0 R /H /I >> endobj 514 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 642.764 306.0 651.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 471 0 R /H /I >> endobj 515 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 630.764 294.0 639.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 465 0 R /H /I >> endobj 516 0 obj << /Length 517 0 R /Filter /FlateDecode >> stream xœÅUM›0½ó+æØ=àÚæÃæ˜MÓJJ• R»ZíÁILƒÄ‡¬Úüû1äƒm¹¤‰"6óÞ›7ÙY (~íf‡ufíÚ=‚ƒã·[žÜ%܃ ÚØƒï:xábnÂ` ß­Ü¢ðÅzyÅà PLøeÑ>Ü!yi-Îø›zw~ ?­ÇÈúøÙF!ŠO1I¤ëAà0ÄáAóáeðò!ü6„á³=›OÙ½\„öÃ+D_OÙŽO¨O)eŽN{éO³É§Ù“½|žG“&q]˜á0þÌX\hÀ\Þ˜àÏ%ŽÙÃÔ¥mÛÕ šÐˆ3ëMQô¤‰žKºœ»’ßáà‘]õäÍVÞÙ²«.6ÜÇbP:vU6ÃyQÓ¡³¢­É”´Ô&iU ;áºJ„yepƒ¾Iôê¹Ñ¹Z¥Ú®v©]jµÑ¥]íóZý4\>–a“Tã(> endobj 517 0 obj 583 endobj 484 0 obj << /Type /Action /S /GoTo /D [518 0 R /XYZ 72.0 720.0 null] >> endobj 519 0 obj << /Type /Annot /Subtype /Link /Rect [ 434.885 505.501 539.999 514.501 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 471 0 R /H /I >> endobj 521 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 493.501 210.0 502.501 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 471 0 R /H /I >> endobj 522 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 121.5 264.0 130.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 438 0 R /H /I >> endobj 523 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 109.5 270.0 118.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 452 0 R /H /I >> endobj 524 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 97.5 312.0 106.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 481 0 R /H /I >> endobj 525 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 85.5 306.0 94.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 471 0 R /H /I >> endobj 526 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 73.5 294.0 82.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 465 0 R /H /I >> endobj 527 0 obj << /Length 528 0 R /Filter /FlateDecode >> stream xœÅWIs£8¾ûW¼ª¹th$8ÌT9‰§+SŽSi{–T§Ë65:€+ßO Ûãí’‰h{û÷–¼ôPü9æ#Ѫ÷bÏH®o„Ì#\À ìZ@b^5|³ÂOýKø§—ö(|î}ý†—3 HðÚ£mvñ¸÷Øonè‡Ëojà2þ¿hðø> ’KÒŠMEíÖgxR32W‰u›ýÖ\ëe­\ý=¨ÝéD»bÕý8á½ëIï×?0 “ù´ÒÅ¢x`þ8LVðõ“®¾ÁäÏÞ`²ÊvÙ^ì­1¨:FUQJÙ;›ªÈJkSmÒ(\éÚ¨x x@¨/Ì{U núÃá“s{7î_Îøqè|ôo_œñÓhÒÿjv[&\pÂ\ÃÁ öÙ=s.Û>x¨»ç‹}fQ˜$o0‹‹pšh(^Öa®aš‡Ñº„\‡3Cñ––á²1Mv˜æ1BŠœýšó}åنఠý€¦‚@2ëÂq%jCtHbÔ'Ô3nçÒZQýµ W^Çˤ6×±æ:ÅKâÔ6:ECðÎ{ŠwÉûíw8ms=âK‰¨éúùb½ÒiY@˜Îàï0Yëâ\˜“ŒRÁ-‡Q–jr†h%‰r¥¾d5á­.¢<þ^ÆYz Œ—c<#|Êæóݦ\êÝ¡»ÛXÜl÷µswû׸\fërw-Ãt§‹ÌÛôE–Íëu´lR† έˆº˜J¡k);ÌmÓu@ÐõÁB8`%Ûçë¢Ìò´œ–ÆËÜkmñçT– s»¨á5NÌUE#¬ãb Æ{Ñ:Ïm6{¡â|xL‰1Æ>·•zð#\}OŽc•KI<åc– ¹»´ÔéLÏŒKw‰ÂÈdÍT76ëâÝÃ8mlÂÆz'M²y–7vQ6Ó‡˜¼.ã#U–ͧ¶ì5”³°ñd ÁÍ"8™2ÈV˜æ½}TÐòÝ6Œš‹$›†I+~]•ÑE98‚`ä”Û¬Œ¿çÓµïùª]C OWàÙñÖ“ÞBàæáv£‡ ü5¾}†ñÓýõÃðîLá°ÍÎ<ë`‹eðl$;â‚vn¶Ò®ÛªÛ©§É3µÁg°Žcè`>×Qy4™<×'Jˆ@IaSü>›ÅóX fz®“º;›„?'«±ýc§5u‹Zeú•ˆÐéÛQ]J¨™ ¤5!ìë¦ÿR‰m‰tÕ‚Íã¸\‡f}ÔÂsMÄù€^(q€ížõ½ÖÐOŠl;tîf>#H)3ôUß^jQPXq›³«N­‰Ùû”^ÂþÄxÒÁŸñKøoJÁÅfpï1'Òí ”úŸÙs¥˜–pŽ%æ÷–‰ endstream endobj 520 0 obj [ 519 0 R 521 0 R 522 0 R 523 0 R 524 0 R 525 0 R 526 0 R ] endobj 518 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 520 0 R /Contents 527 0 R >> endobj 528 0 obj 1054 endobj 471 0 obj << /Type /Action /S /GoTo /D [529 0 R /XYZ 72.0 720.0 null] >> endobj 530 0 obj << /Type /Annot /Subtype /Link /Rect [ 253.798 494.931 400.103 503.931 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 438 0 R /H /I >> endobj 532 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 482.931 270.0 491.931 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 452 0 R /H /I >> endobj 533 0 obj << /Type /Annot /Subtype /Link /Rect [ 137.064 418.345 331.688 427.345 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 481 0 R /H /I >> endobj 534 0 obj << /Type /Annot /Subtype /Link /Rect [ 351.376 418.345 540.0 427.345 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 484 0 R /H /I >> endobj 535 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 406.345 138.0 415.345 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 484 0 R /H /I >> endobj 536 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 174.076 264.0 183.076 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 438 0 R /H /I >> endobj 537 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 162.076 270.0 171.076 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 452 0 R /H /I >> endobj 538 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 150.076 312.0 159.076 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 481 0 R /H /I >> endobj 539 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 138.076 318.0 147.076 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 484 0 R /H /I >> endobj 540 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 126.076 294.0 135.076 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 465 0 R /H /I >> endobj 541 0 obj << /Length 542 0 R /Filter /FlateDecode >> stream xœÅW[£6~çWøqV*®oØæ¡•²Ú´RÕÝj’¨m÷$Î* »›ßcl! “ôašyàØpîß¹ÌS@¿Ð>TÌÐf<ù;ŠC\ú«H"*0‹Ðy:B™ýªG°–‚‡ûˆôGý|ü/·ˆÃ×€ Å5ÌËྦྷ߾!¯®¿o§ì±àþ< Š)<ÈMÃÍÝÜ8AöUæÃæŸNª#qîù¬QädŠ7÷õ”ô9x» ¾ÿ)B” ÕîZÅákÛC«=úx'é›OhõK0_]¤ò•Cv‘E«»sL‡¬jB=ó©É¬ò>9—>${㜉ЈŘÈÈ~¯Ãb¾\ý¶˜‡Ëû_ÃÅ|ön¾—}XÍþ —«ÙjŽÞ#hÑèΉí„1ãX‚QŒ³K±3¦† bŠ¡§haªº(Mï¦z:$gë2ÙücêÞMi’­)û<ǼN¾õ.ê¢wHëªwz,Í—´8T‹!^‚‚¯}€«:© nC¬FBqLbžIÇñ>Ù”EËð|*5Åh‰õš–-c<¢‰‚,)B¸j£Øünh1òeé‚VOYèbºˆ…‡ÃÜ)2¦í‡ÑËŽQ!1%"Ž#¨Á†oV~>ìM)Hò-ú=ɦš-UsÊAs$<Ì‹ü”„ Õ±ÆÒæB0ŸŒw¦Ú”écùd™0†!€Uâ}çÉ:344†b¾«LGCítt‡CwìPèŽé®#¦ƒ‚F#êl#x Z@˜¡HÍG˜ÆþËt?Îô”¼Î ‡ä”µ1ywØ$Yf¶ÝqïJºÒòŸ{áLò)¨3.lÓêF #rÀ…)º³PôdÉ-¿¦•i/¼®ª=»ä7¤Ë}Cv©oNÎÜß;af—²ú»qa—-ˆAýœ›ìyl¥òöm¯( ¦"ÌT±&¾$æß’ýc6],´ˆuÄ#ߌëÇ ‹ ,Ëš¦ <#œC¶‘„K…¥Ö®Þ/d……Ö1¼Ò,ŠA.T™fc. sXwŽ©s#A‘i!ÏzÇ4›ðj×á%.8¥S¾K9Âp^8Œy-¡÷´ö™O·Íw;³©'1Ã¥ÀDQB…oÚ óÅ”Ðô-àÓ¼6ežd-ˆûcõLˆŽ0´ À’ßÙÞÛt—'Å—²qªmÔ®pHØÕNqXÛ5pÖø­j}œòGp#Í@d;ÇV`ÂæP–ÐÊ&š4GJÛEÆd[Ó (¶LëCbéÉH‹˜b*•]lÕMó1²ÍWHè,=•õ,«Šn1>í¥ÍjaÁ„]N›ÅôÚ°Æ`~¶cOé`ó¶*„ºUÅ “`Dôu\×sFT)ú_UÝî–æ·êÚ¥ à Ÿ^ø7D2‚)g„Ƥ[Ðêé‰"”¡RËS5UÇýºÈÒ ²cõr¾A…¶5{ÖÝÿ¶Øj endstream endobj 531 0 obj [ 530 0 R 532 0 R 533 0 R 534 0 R 535 0 R 536 0 R 537 0 R 538 0 R 539 0 R 540 0 R ] endobj 529 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 531 0 R /Contents 541 0 R >> endobj 542 0 obj 1107 endobj 544 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 709.5 270.0 718.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 452 0 R /H /I >> endobj 546 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 697.5 312.0 706.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 481 0 R /H /I >> endobj 547 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 685.5 318.0 694.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 484 0 R /H /I >> endobj 548 0 obj << /Length 549 0 R /Filter /FlateDecode >> stream xœÅTYOÂ@~ß_1šØuž€Åh R£†ðP¡*IKk”ïÔ-Ѓ&ânÓÌdf¿¹wRÂá§Är,"’–2–i–"áSa@%o@ˆ·ªŒØrHÔ%dÞàÄ„Á5™ÍQ¹†€Ošæ~ÀS2©ø/4ìäþ¼’¾G.‡pÞ˾D’SS0<¶6•Â)Ž/‚ÙÙðfäjî¸×G2Œ´ó9x·¨I™‰H.-¬½s{Wî6}{½Gt½Z%$ÿP‰I-œKX´1#øëT*J”¡B–í+©²ªXœ¢A±}L¬R}> endobj 549 0 obj 426 endobj 551 0 obj << /Length 552 0 R /Filter /FlateDecode >> stream xœÅVmoâFþî_1¢R!Râî‹íõVM%rI®WQ¢šJ>ø`KÆÛÜåúë;ëµ0 —~IáƒÇë™yžyµŸ ÿú"$ƒéÊyªÎ(<¨Žü¨ç2VPÉ>$ZkG`µ„£„ÂþrR‡ÀGg4Á‡3 hðÕ!Mw¥ñÀ¹ßÁ×OÈ»ãï2à”ý/ î÷« ˜pµ)­¹9ÃãH?Jª´UWãÕˆ†œ¹%E^9{R*ºïN`á\ Ÿn} †óצOÜIýc0\Á¨øgþîÜ JùÎ);¨¢Æ~ ©cUCBÝ‹©¬¬¨b2!õ£•2AYrà…À¤K_ë‡Æ`pßcð¢H—‡Z…ËCý1c¢¡/NéÇušÙvZ@”‚Fû8]À<[¯ ßn6I¬f ž7™Êó•Ýš¿°ð÷¨K$A÷q»M§ZÕ6ÇS…Qùi Z¥jð--¢çÚPZÀ(á®$:½aMùkÄzÍü)1¤¢¡L¹ÕoMI4xPÏæ>ÊùQê4°b\þ Èêâ5ÕßOåÄåR©0^ºÙb»Ri‘c9gð%[•'¯“è3Wø”A,Üz”zÌbÒ…\°ž[údK0qFHÀøKÞÇ:0éÖš)m‡±ê›ªy_}¹oÈžÄÉðp8ñŒïk•O³x³Û±Ö)eÔ ôÒ7†ªØfigpRè ›J*ç׈íên¡R•EÎVuP\%KU‹;­Ž×“ î†#õßÂòde™§lÝ}x’[”½<-²(Í“Ýã´Xï$æ°Aç X“4Ó͘•¦ëtŠ>ÓÒï׸XB9ª$ òM4U0SI¼ŠË¦PÑtùßZ‚¸÷G¤z Ý;Œ’“ ¡Ž£ßêÿÙëµ,Ê8â6ßíùzmuî1‹óÛ»;›ï IÄøn}޲–Õ¹zkµÚ¨ß¶ù—MîÍݬ_¤IØ ÄÆÀ£ÍTk”XÐ=Þ$[enÜÁÂæÏZ"Y±ü&}5îèJcFÏ˸ϵ¹ ^Ø›â‡7ÇÇÚdÜ-ÊÖW#êâ·Òå*QøU0B¢!Ø~.wÊÿL&Ð^F_ô.KˆgFM Óuø‚¯ßð%£¶žìÒÁ—(A¯¿€oK†Ï½†µNÆà¦wóa:Wݸ}¸û®ºÃoÝÇOý0îà÷Ó5\âé ã3èö¯µ¾ûØíbY²ç{(|{ø¸~)¡2”¢Z_ƒx¦àf>ÇLß¼Sú®çëWQPYöשzàpQK_Ä«¿J4\ŽŸ¿B <ü„æ\†8&ˆå÷½ó/÷ñAD endstream endobj 550 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Contents 551 0 R >> endobj 552 0 obj 1048 endobj 554 0 obj << /Length 555 0 R /Filter /FlateDecode >> stream xœÅXÛnã6}÷W(ÐÝ Ë;¥´]ÀÙu)I»×Ý}m9q+KŽ%#I¿¾CKrd‘ºø%MDS:sfÎ 9¢ø?5í34[ Š9Š4C\SR!*0“h…бD‘yª2`å.ùC0¸G¿âAŸ¿ÂÍ9"xº¹x<¸©ð›;äÕù«pÊþn³ ™ÆµÜìÐ<Ÿƒ™Ü¹²×Üj>Ì˯N‘Ÿˆ[”ÂÝ×#'ènp>|!%h²x)ZÍa{Ì7 MVèó[¥O¾¢ÉσÑÄJå+KfeÑpïƒ×!«!„Ĵˬ.bÊCº Va”Cá!æc¢¤yÞËã›O§£?~¹Ç—×W(Çî”sÌ´yZ;°_Óu€h ÷Iœf›í,KQ#àFáÓz¦é2‰Ñb“¬Pº]¯£e8Gÿ„ÏÉfŽ‚ÍÝvÆYŠË¸´#.A1ñ 0©œébÏ20Zbš%T>–Ôó}M ÇÏq<•@ßAF‰ÄžÐÆXQIh÷WÓÂŽ'Ó‡è´ó·f]BßÉP:îÔa}ß ê€Ž“–/,D·\ ý„0åk-‹2z Vë(l>U›X<¹„…HDYXõÏgùçÍ"IÐÙËãÍ4Ø|9q¨ã«šE8Ø~óãûOæ+ÔøÏñ™¹^~]MN‡“Éíåù¯“º¸¾ÆçÃÛw¶9ÅH§ƒNýërJqv¼Sçÿ\‰ºbÕC»ÏŒ7ƒÿ¯Õ1 endstream endobj 553 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Contents 554 0 R >> endobj 555 0 obj 1244 endobj 557 0 obj << /Length 558 0 R /Filter /FlateDecode >> stream xœÅXmSã6þž_±Cg Ì\\I¶%›i™.´×¹#„^¯—ûà$ ¸Mìœíô ¿¾+¿Åزý@˲v÷Ù}V»r¾ö(üë«‹pÌ×½¯ùÁÀäù”ÍZ³a ù؆•ZU°b„—lîác/èø¹÷ù >\Ao=RW— {7ûê yuûU&eÿ ‚›§,&Œ7©´™ÍáL¦H=Zåa˯™Öl˜Ë®­ ÈÑ%‡ûzÆ ÜõÎ'½.m &Ë]Ò g ‡¹êÃ`²†ÏGÜ=þ“_{ƒIƒÊWYƒEe»t¡#«!„>ñ)eVä>e.]yk™9¥‰ås ÂmµÞÉÆ7ïûÃëÁèlònx™h)@q¹©ìZŽFtʘ¨ ˜]pqmçI ^häÃ&’qì‡,£p ÄÛÍfåË„yIáÒxÑÝv-ƒ$6 ï„Æ;‹Ä%hg/·Áˆ:Ź‹™íp¶ýQˆ.ù¿‹ÊÆ‹ã4W²Û,“²q^F‹ÛJÃÜ-´’K?Š“òîoUüw¶ƒgÂtðDJììtúBJ,TÞ!« BâýUõ$,‡3©É5“Õáºè/žø´í©˜Dríùjibð;O–0¸:ˆs×ÖYêrœ jUÉ£YðU3nœÎÛ+ Éñ͸‚ä­uðà­7+Ù~’Páq¹Á8JáÛNþöñôx‡±\©VÐ ­…Eà©,”Ÿi­ôÃIâÍVÏqa'^‚ýv¶Mð~æEÓcnÌ„nÝU„Ûõ‹,þ3=ÖÚDÚlžd%¼)cYÿ)Óc2»NFÀ·{IßÇB%R§Pu2°®i£ã´3rF õgznöØLéКtë„à!÷»Õ«õÍí`ô ƃ÷ƒ‹ \‡ÆùÙèÍøöÃô(»ùý¸ ?¨gðñ—Áh€(p œ¦îÁpôv0‚sT¡dÒõ§M6U„‚ÇzÚ²;Ê r€mÆppñâU}ëܲ™SÓšº•ŠõÇŸÆ'êzy{u¡~:è~¿†ñdt=OÓ5‡oÕ·±Ejº«¯e]õÃæª¿s|ûsò·ü±¿0X.q÷wÔo´©hrP²8Ë^…|FÅâ¸Ç±þ¸9ÎÏ©1lp³Ç.ƒ7‰'DaÓ†Áô7§›Þ¿p¦ñ– endstream endobj 556 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Contents 557 0 R >> endobj 558 0 obj 1393 endobj 560 0 obj << /Type /Action /S /GoTo /D [550 0 R /XYZ 72.0 720.0 null] >> endobj 561 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 202.652 138.0 211.652 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 560 0 R /H /I >> endobj 563 0 obj << /Type /Action /S /GoTo /D [553 0 R /XYZ 72.0 720.0 null] >> endobj 564 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 190.652 204.0 199.652 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 563 0 R /H /I >> endobj 565 0 obj << /Type /Action /S /GoTo /D [556 0 R /XYZ 72.0 720.0 null] >> endobj 566 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 178.652 198.0 187.652 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 565 0 R /H /I >> endobj 567 0 obj << /Length 568 0 R /Filter /FlateDecode >> stream xœÅW[oÛ6~ׯà[`æx‘H±Àd;t Ú%6º‡¦ŠM'Âtq,ÿýEJ²,Ú‰û%$R<ßùÎy ("ð;1©ZäÁ£Û£H2Ä…ÛŠ¢!fÊ‘{PfNí½°ö ö¼< ‚" èàë7ø¸D¾ä®ž×{úÍòêú÷pÊþ×Ã(H&ñAlin÷`Ç™O™s›{ZTûjÉÙçQR¤çDüNqt_O9A÷Áoóàç¢ÍW}ÒJ;8fÊü04ÏÑ×·’^|Có?ƒé|ÊWvÙ(ŠFwg P‡¨Æ„:°©‰¬t6Y“>%¹¶Fy|ƈ)LDdÎÇV`v}5ùü÷ôærþùYÉîT8::‡½J«u«w[A¢Þíº8‰‘¿‰Â¸šêÁ{l͸†ÄŽLç £º„¨­>8ßÖÎZ/Ò•)žQᜨ-±€€ ü»®›t½_CÞžÁ¦ ©¤V°-ë 4‘ð ½5¤ºEã¸nå<Ø­å,Y—ÅÒıG( ™0w‹ÖÜ~§s 8£Û4‘ò‚’9‘¾DBLbBi(=x6‘Ã(:%{W'‹ˆñð\ÝÐ ÇRhYê AùìåRÒtárS´a©=œ¸ø if67MìõòÇÁÒì3æHLŸ’|õmÃ×y™Š0´ì]ã¹tTô&KÿÕ·ã’糡$ô;3à®>þ5õ§êàø~‹?e#,)W±bNr–.5š®VzQW§j‰‹ðT±à®·}* ý_r£žI~]Sl´5}锯iÍ…«³†!Ç2ï„­àôi¡›f‘Àµ%­·‰y?im(¦"ðPœ§\1,#ÕÓû™Öè2«ÊîÆÖ_˜@QDŽá ·¦æÆ4Ê+‚bÌ—?H)ïíÏ ÑøÐ&úÉÔUÕuS0ÌÔ¶™?Ä}æb ÈP¨=ª¢.Ïê¾îFóË‹!5#Tˆ— -cbƒ15}ÓÌEáRèznºèw\Ko?›«X¿^la>u¶ë·’}8Û±ú•váº}û%ËÊïnÌØ­÷ež—Å€À¢Ì×àÝ»LŽûŒÎ¡•mGªÞù³RP†MhÎwRìŽ%`á¹hUÙþ7àãâlrÙ~ɘßÿVo§Ø endstream endobj 562 0 obj [ 561 0 R 564 0 R 566 0 R ] endobj 559 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 562 0 R /Contents 567 0 R >> endobj 568 0 obj 1106 endobj 570 0 obj << /Length 571 0 R /Filter /FlateDecode >> stream xœÅTËrÚ0Ýû+îfG’ßÛ–Òi‡ fºH²¶uŒ ² áï+[Â2l),|Ï‘îëÜkï= HÿŸÛG’È·ÞÞrAl©(ú$‚-X;‚²½50ÈÙÒsIøã ÁOïíC€´ÃÑC×á:çWo>Èßž ‡çV`ò_*˜_N!!‰5›Î;0œfL ö¨´²Ù§‰jLSœy~Yr5¡û¢Ør—ÁÚû¶ð^¦`‹•[Ú$ÐŒŸ’¬ýXlám”ãXüö~,nFù`Én¦Øæî› €„~ÚÕ~ÑFŸF1B$Å@°OÒ!Ǧ»i#rÅ+AK˜PEaÂV\ð–1]»0‘n–¤Y&DØÇaÔŠ„M˜놮¼¦“Éì}l¼_¦ñµÄa Iê£0ɲ8²Ÿ½ÎggÛ¡èëX—Lôö߸ž#ä‡0ÚÉêÀ V;†:såÚì9]§Ç Ï7ÖÍnWI5¦6Ì\2چ䅺 %›üòFµº[ÙJÎÔéþ½BdIkv5 ­a†®„¨–YÞœD~#.ò²)¸X÷ŒU²ú©ÇÎŽÈEÁ>™ `:2vÍö 9«ýž:/Žs8Khdª‘b}UÉíY4›aY5ªGy#%ª<Ý6‹¹ê¶h×”u’Çd¨”cœ – rpJ˺rÈîNá;ê—\.Šî•xr”]¦v• 2ʳAf·}ÜLÚÒ•t€}Ò­~óÄúNûú;sÙ~7J JI¾l”NÕ«‡ N;=ªÁgkîý\‘¼‰ endstream endobj 569 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Contents 570 0 R >> endobj 571 0 obj 598 endobj 573 0 obj << /Length 574 0 R /Filter /FlateDecode >> stream xœÅXMsÛ6½ëWìäÐÆ‹ðË3팜8·I¦N”f2–Yl)R&©Æî¯ï‚%š©ä’Ê vßîÛÅ.èû‘ ÿÆêD–ÛѽYs! À|³äùàr‡z°3ö Q»Zð¡7á`ŸFéˆÀ¯£Û9¾\A/#ÒVW Ý4ðÕòÝñ›0—þ/ÜéÔƒ¹ëˆ _+y½O—eœ¥µL?7~äxnEk¸ùð˜–⡌,`.ñG„0ƒÕ¯åeÈ»—•kãÊŸ6)êt×f -;\Ÿv÷§¸v,wÃoDˆ,+Y,óx×ä¶D=G?ü-Ðhdá«Î€^(Æ-6 0[ø–YZ”¹ˆÓ²è»k1oˆSÒÝ i!ªÄ@²Ñ?ÿ§sÙeÌñCLf¯–›äwû­DÇ@¤+øS${Y äxAKE:T+\F,"Ó%ÙÊ9¿ Ð@¢ãôîŠÇí"K ËáÃÍ»\òâ [D'>!^Ø“!v ;b“cqÉÉe _6ñr+¹ûé*3xa&ãzë‹aã(q—2 ‹Û{V¬æu'ÄEyR'dªâ1Þ›Æv¸ŽääQ!«¸é•BE¨ÿ s›¶w×ozñUièJœð”ã…È ñCÞŽì®vD'p™e‰©*KMˆáu2 .|õ"'PgŽR×¢wÚï²ï :§5 ¨P? £ÀÓB¯¾"³ª6î·uoE7±Àsažú|êñR$‰\™É@s`žCÔ•" l8ÃE©=7àúDêñV<šÑB¶Œ¯S×Ìt]Ñ•»Õ@Õ˜®«ñ +c¼Že^KÇéIÇYβ—Pf1þd=âxUoúÞº!`@ ÛxuÁ:ƒ1õåav[JØñå@pæ"Y!O'z8 áhCÜ0\‡U:̾l²B§2‘º¥%sùT¶ñ«b‰5S¤AѦ±_”˜@‹}Ù¾)º)±äuqåãN=TOÍPYÚ ÅÓ›]š•ãtŸTMn—Ç[‘?ŽÕhs)pÏ2KöÛ0éMr¸âmÇá\ßœ¿¡æãÕ¥+©Š]ÝŽ!—ªÿªÓ€‘V=YŸ”#@£I+BùkÚ…c!ÑçŽë»Ä%þ—ê\3Ïß>꣩ÆuŽçf!^›Á@¦z¾ÃBõõ ­ƒôU‚ÒpHGmLÑ2¦Û!0çY¯šÁ½9ƒ*R3¸NÓìÕ¥™ÔÕì‰ú#cefuUãb¿ÛeyYol²ómˆEÔa ?²˜oNÃÕƒØî9p—Å/3Å®R”3óEøä3n×Y6ï¦ &kKžü~œ¡¢Ûx5ÇóSÊ;™ÏÎ,J<:¨uld|·)ç°N2QZµ`PNjQ•aŽs¢(ŸYuþi]Ël[U¸9$Yz·Üˆ\)³ª Ûì>šÛ<Ò&s¦sg,T¹ïtfg6aW‘èJ#ï€1µmd~k£-Ô&r ‘B‡Zy±Oã{¼Š]4*¦Ý*¶ÀÚDè\ˆçu¥ë õ1ëù¤ëµe[Ð&§Y‹lÈ-Äv÷ù¤íê7óŠöawß§m÷ŸÒzÑìxˆüìã»ë›Wˆ‚œ#Ðìì<ûãýõÛÉûÏðûÕgýW{ð˜%É,Ûx›²aº«ÿÙÝŒþ“[Gì endstream endobj 572 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Contents 573 0 R >> endobj 574 0 obj 1451 endobj 576 0 obj << /Type /Action /S /GoTo /D [572 0 R /XYZ 72.0 720.0 null] >> endobj 577 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 73.504 192.0 82.504 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 576 0 R /H /I >> endobj 579 0 obj << /Length 580 0 R /Filter /FlateDecode >> stream xœÅXKsÛ6¾ëW쩵3Š™igœ‰ÓI'M›ZÓbh ²ÔJ¤BRýï» H‘&!Jé!•@ìî‡}ƒŸ& (þ§î¡ ‡ùvò©^c 9U/I,"\Â걄ÛÕðf„¿ +øs’N(ü4ùx‡/@‘àó„öÙUÄ7“ùî ýêò»ãÿ ‚Ï­ ¹&=ÛTÔ¯áŠgä^mjµÕOÏÕ=8ÿ< ж˜hX)5ܯ'œÂÃäÕlòý ŒÂlÙ:­¸BbnÜÃl /´º¼ƒÙÏ“ëÙÀ”_Ye+:هà t´jL)eÏÎTYV×gòGzŸl­?T@Q ܪ¤Û{‚׿ÿúÛtvõêÝ5xºÃnÆ8ÑÜ å|Hw˹îð1xg;H`‘”É}RXÀÇÆ’¬€¡†" åY¼Ù§ór¥ Íq½(C$‹Ñ¬ÖËÍSZ& ¡ cT!3®j÷€ê×;dv.ðhÓê<}•D¡íÐà@= LÒAÚ±ê;ÓAßümŸFq´^N™-¦iVNíãº(J­‚äKN&XHÇ7—£THÎ?Âi/`""q¬ŒótWùÃ~kÓ²€$]ÀÉfo‹ãWHC¢ý˜Gbh‹A„1E$³•GÙÊUíù (Ê|>|ÅÓö>Û@–Ã͇w`w¹- tu2Ž.f$¦rÌȰ>ÃdWmXf÷Ùy ŸWëù v™ì7¨®2ƒõdÚl}1ŽÓˆ0¦1zù)ï ¢Ò_Õj"ð‹MRÔÛr¿*#B’[x¹~H3|¢_Ú<ÇÇí…Ów üö’œö.xÏg^Ûbž¯wÝÄ̬R÷Ìî^—øžº¢\AéÌ*'hçód³±‹ÎÂH’ˆ8ᣢ& ÷„‡ª1ÚŽüežmσcPeRaxÆ,Àò¤KòˆŽÑw0x§lç÷ì¨5ëL.Ûyûvy¶qœÛöR»3¹$‡¬ôT”h¸¨|¼3w9§(=_ A©à" äü0â˜8•Àþ@*`Ô³.:“&ŽÚÔN€>ÈÖ\»è9*°_'…åБÛrŸ§Å9°„ÒD)í:?`úþí»ãxb9FÚ‘þyes›ÏìÝu†*!u5p(LÌÏùh ŸÖË‘âj$á‡ÎkÀä ò®ÑcŒÝÄgÖ32©`®Å•”FqÝ^?&Ûݦ­¸¡6LD í¹Z_·n·>=òbºƒË,»»½ªOȸG‹mÂ,°OÓŒÖ5=,&}­5õ%(:æCÑm&úϧ‹h_3(] بVýs_Ýc¶‹" ÎM,±ßõ ôzaáz¹ÄÞ +ƒfΙ‰£X5UÛ«}Ç)yçŠÜñÔÇ#B«[C¤¼N·7H‚F)f!ù^‹þJŒ»thÑôŒÕ¡õýÓØÁ%—D§ëFÚ°úœ!^âÅÓ±‰µi‚fn«æ#ÁËâºÜ'nm¶ÅÁthÉÞÁÊdê™ãÁÎLîL`àcGj$Þ¹†O]HÆhÁe¸ôÛ|‚«”ãWF,ͬ ®!¯ó«ŒÎòãRȨUu5ª{we:»â(fˆÆ\]ßkn¬…«M‘¾ó´ŸYÐ:JHâ>.Ì·þ;Ë Qˆ‰xöÉhŽ%¾´Ý¦úxäþÿÀ3ÍÐ endstream endobj 578 0 obj [ 577 0 R ] endobj 575 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 578 0 R /Contents 579 0 R >> endobj 580 0 obj 1350 endobj 582 0 obj << /Length 583 0 R /Filter /FlateDecode >> stream xœÅXÝoÛ6÷_qÈÃÆI” l@Š¥C‡¢@c{h‹€±hY-¹’¼4ÿýŽ"i©­$/ó #Å»ûÝ'Oùº @ðïR?DÊ`µ[|µ{Û­(,‚X:‚­>5 ˜£ða!±¿å‚Àñeîd,®c¾Y|è×oÈ×?DÀ)û_|ø> ‚‰`›Ž››=Ü1‚ô«­u›}©†4àÌó$(Òc"~§X¸?N9|ñz¹øùM”ÀrÝ'­à¸$,Õ?Ë|<ÉÅgXþ±¸^NBùƒ]6‰¢Ö}4¡cTBýΦ.²ÂÚdLz/wÊåñA˜KGú|bÞ½½Y^.¯^¿»¾Ãxk~ùjÕ¶íãQ¡< b‚¹'Üp_Õùa§Ê3¤Ìà/¹=8ú`ë(ÅXW:ÅD{<3ÉÄëṂ¦­‹2 '¥!Çž²¾ûî´²˜zy ªá•ÜnƒyÓ0ÎÓ”GÜ¿u¶«¾Èª»/jÕÂý¦Xm Sk‰qj ­à…]\º£/æÁ1)Á †Âõ}нЦLWÇ>`Ð×ÿé¬a˜5„G„ðØJùM5«ºØ[·ñEi€ÕsÛ\;º€ËTÀ¹tDÊÒˆÍR¢[Öj6c²â¦ÛëªÞ-JlÄÇÓE騙2Œñ^×ý†±í£áÇ[kŽß0Ñ·‹c8 *G=;%)œ/EácÑÊ#Äè°¦§OVeJA8ÁÂ=Âfk“$s¬½î»‡ž¶é7Ž®4Ë’åv»‘ƒ³U¹ˆ2÷Ãà-ú*ók=4ªœ”µê:SUôo×S·MÃÅS¬¡(!”ã ôÜÀ…l–ÙBÙ“¦ŽFW£N ì\£ŒWeÕ•—íÐõ:GZÿ·ÝÍÝŸŒÅ¾dÒDøtÌÛÊ¢YfÐÁp1Ю?íq‚ÃÀv&8{6 lçsÌ€ŽÖ÷ ´UBGï Ð=ÞW9åÅ!)IHhä^“»ý¶¿}c6â€âˆ(²Sáp‚Wep¶®Uvöébu³‘œ >Ÿµ{uÛ 9³¸+ò¢lq¥Uõ ô‹UµÛËò)™eµ~'o¿TE‰÷+Lâ§ Öõ²§‰ï>¿Íú{õãF^W‡½!÷uµ2T­îë¢Uf¡ 3”l±,îøbª3¤c'ëQTs­¶²iŒ€¢Ü(|\eê›!«½ªe[Õn5à‘;Ÿ66ŽˆÓ&wÕÞ1öme™d®ÜªÎ•™3ìÑ<¯U.ý†ñð„*tFž+‹¹ËáÒ­V²±¢»v/WVu³‘YuïSŽC~ô_Uþ‹Ýõ±LíU™õÁŽæbß’&õA{)ú´Eã é´=7¡µA­lÑôbåòÛ£LxSãñ2_”o¥8fØ«Ó|M™‚ëõcÞÌM`Ç8à(,8µ-æ}Uª'ô¦(ŽðEŒ`ÝLÛ)ëZÿ¬BXš8#§S;ipAðë1N\g\©®Î%~¾íAjzÖô8 ®¥60½ûïÇůK“B endstream endobj 581 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Contents 582 0 R >> endobj 583 0 obj 1315 endobj 585 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 97.514 192.0 106.514 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 576 0 R /H /I >> endobj 587 0 obj << /Type /Action /S /GoTo /D [575 0 R /XYZ 72.0 720.0 null] >> endobj 588 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 85.514 180.0 94.514 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 587 0 R /H /I >> endobj 589 0 obj << /Type /Action /S /GoTo /D [581 0 R /XYZ 72.0 720.0 null] >> endobj 590 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 73.514 186.0 82.514 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 589 0 R /H /I >> endobj 591 0 obj << /Length 592 0 R /Filter /FlateDecode >> stream xœÅXKoã6¾ûWðTlk–ñU 4[¤ l´²9È6»•¥¬%#ñ¿ïP¢¶hysI“ƒ†¿ysfèo#ŠüÝC†ÛÑ7ÿŽ"Å—þ•ˆF˜ ´Ež(q»:«)xT›€X£¿F鈠ßFðq‰^Fä”] žŽî;òÝòîò»pÊþ ˜Â'±)Ѽzo*FîSâÝæŸ׊¬”«žg•"­N$ì¯îû 'èit=ýøY JÐlÕ&­âðkfÜC³-zø ÉÕ#šý>º™õBùÎ.ëEÑÉnŒÕ!ªšBl*#«¼M•I_â­­Œ ø ÒˆL¤pûu˜M®ïnÆ7ßNgÓñ¨Â6Ê4ÖÜ Ö¼ýʘ:ð!šÙ¼ÈÑ*Û¡bm‘}Ýä…Me+£e\Äó8·‰Åµ*`FD11ËŠñç}º(6YZcÎ{L,¨6FQï±é!-â×hÂ(‘˜E Mqêí(ÿNL×Q`giʸ44?Ÿ:K™×º€&'ÊP’‘vbÞÓŸš Œþµ‡AŒ‡e/©Ý•Äd3$D‘ Î‚³r8 Zôó/hgó}R\ÎÊ& Ž&¢BOvOû­M!7ãt‰þŒ“½ÍÏ+îrB¬dÈM? ½“ú 38æÒ߇2YP J ¼ØmÒ§O(?lçY‚àÀLïïàÀ<ƒ9$:ÖN3L7F]X½fÒhq>»"•­ýr{w^˜¤AŒ3ò§8I†Mcš¨+yLˆp­ëÃ&m½ÉæÿØE^Ö›Å-í*†,ÊQ‘¡~1®·~¼ “DÕ!>Nɰj=Ð]gYbã6ÊçsìÁZD„pãO¯6_ì6ÏÝrìšR$ŒnzGUœ¯Á}p5Ú“.5=ÙVlÿ2×SqZS.Skh™Ñ~±€àÚe½*>Lc©¢5Z厳ØZø&ý5¤Æ‘€öÅ¥°º˜vœÊ!|­@•u~Ñ$_í¿¬¦ÞœŠ†.*ᮟƒ¿ò†<[ 4|6pÂ4©>«ÁŠÕ|ÚˆžÒ{£Y×^¬V[8;­ÆÅ:n7fiÒr)Ó³Ýè<´ IÛçv×n‹w¶¡ík¼Ý 7onW=WõÄÂJiB Y<ªˆ ‚CA‹ª*é'ƒä wò8Ámš° cÈ^Yqñ¤óH»rGòS»ô>ö«ÆÉõWïe¿œw¶Õ†#¥`àƒ¹²¯ë°Ã˜w ,#ëÝÐúWel/êÊa¼0‚BkÓâͺB±·ò7—º¶ÙqøÚ¦›Ž>Ä ¤®c©+.÷# `ßgoûœ´ãThÂænp·†H×W‹“É=¬²ìñëU@[`aœõ÷EPdŽ÷u§ø!“"a#¡A é/ŽÓÍÒ¢›Õ ¦†|¨Ç‚±0äÐz.ÊRûNá–­ƒ2ßÔ'¥087óÃ@A9fX*íý¾qY¼ˆÌÇðAqVqaˉ"†ë¦ØÇŽ4]H Ó.#Œþ&Û…XÂlWÈ{ÛZ4Iò¬¹¬·we$)ÅF—?>•—å^~¤1?º÷/v6.ì¸Ì°à/Ž-ãoe»ÜeϘºÊð6¦ äÅ4ïpuÿÿ*Öa endstream endobj 586 0 obj [ 585 0 R 588 0 R 590 0 R ] endobj 584 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 586 0 R /Contents 591 0 R >> endobj 592 0 obj 1262 endobj 594 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 474.556 180.0 483.556 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 587 0 R /H /I >> endobj 596 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 462.556 186.0 471.556 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 589 0 R /H /I >> endobj 597 0 obj << /Type /Action /S /GoTo /D [584 0 R /XYZ 72.0 720.0 null] >> endobj 598 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 450.556 204.0 459.556 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 597 0 R /H /I >> endobj 599 0 obj << /Length 600 0 R /Filter /FlateDecode >> stream xœÅVËnÛ8Ýë+î²SŒX>DQ\L·p(Ò20‹¢ Ŧ¡²äH ÿý\Šz9zLºÉÈ Q$ï¹syèÅŸo_Jsؽ‡vŽâ ÂvJ†ÀÂ%¡KÈì®Ñ€w#|¹M8¸‡¼Ü£ð§÷ý.î¢Á“G_Â5Æ7ÞõÈ¿]¡oîŸÂ÷)ö>|‘À(ć¡D%Ji­#AD×öááû»Ïo7ñÖ7Ÿ®¶¿ý€ø«·/’ŒÿÉ\_Ä€„*®È škáæpÆÙ¥¬e };T7tÁ¹÷bPtˆ‰ŽCºdøM/“«Îè‚T%©|ã’MX´¾ûdô¤S›•6•0t¹üñb—Íx§D„Ÿ¹mÐE[¢" Z:Ûto`{8˜]]uæÓa Ñ%‹´3Ü@ÜfÒ v¥Ij³‡4ï#@€LPØc(‘² Ú>A´¤2‹!0­˜“ÿΜQF$hź š¬1îÛóZæŒKQŽˆ]ÍÞïÍ!yÌj¿‹úý+ÜK{¼%¥A9”íóΜê´Èì–´~Lìx•[)°h16Xq`È)¼3eY”ý²Ò «ô]d˜g¿xè‡+|¡l2›¶œñ›'ǪÂ`Ùr.¼¨ûq2Ä]—i~÷ûð}>ÞYÿ9Jöæúj(Ãó©4U…¥$ýÜb•Š¡õùdWYÏ-üédš¾H¬N|މ %ÇR'Pš¬!v-‹EçT`ûÈ@ÏøX-;·WIJ-$ÓýÌsZÕÕ+N ÇbhMñĈVenŒMV½¼êfEID•¸yy£“ëw_'¿Ñ‘YŶ Aø« æç@«ETý*jè»âù§p°RE-‰â¡Ž´jå㯢6«ç\ ¼SfEZ)gßÛæô…X?³aHD¤0Ì€ìP^ê2Ió¥g‚#D¨µØ ÄD’ï_“œH‹¡è\^N^%»uåã> endobj 600 0 obj 916 endobj 602 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 709.5 186.0 718.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 589 0 R /H /I >> endobj 604 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 697.5 204.0 706.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 597 0 R /H /I >> endobj 605 0 obj << /Length 606 0 R /Filter /FlateDecode >> stream xœÅTMOÂ@½ï¯˜£ºîGw»=Š¢‰!*ÒÄá€R>"´@kÀï”-ÐJâÛÃNf÷½y3oÛáÀðu²Åó|.È*ÏqðH§”îR¡`y¬`ž*bába0…w¤?ÀÍ0l«ÒíÀ=Ò-ÔÏvØÅë3˜V@npÁø8"WSc||¤†J‘…8³`ý«û·—W'¸muÚמH;(µ"¹ø‡Vº% h§'> endobj 606 0 obj 434 endobj 608 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 678.764 192.0 687.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 576 0 R /H /I >> endobj 610 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 666.764 180.0 675.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 587 0 R /H /I >> endobj 611 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 654.764 204.0 663.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 597 0 R /H /I >> endobj 612 0 obj << /Length 613 0 R /Filter /FlateDecode >> stream xœÅTKoÂ0 ¾çWø¸š9iCÒ#HlÚ„&¡FÚq`=¤òl¥íçÏm´<6qaíÁ–¶¿¯éš @z£ÊèTÂtÎÖ!&@Kˆ;!¤: .Ì!ø òêTÑ[Œ?Dμ°Cx`£1%g€TðÅð®.ÎØ°Ñ¿ÊàÕû#¼³žew÷ ‚}ÛS”t¸1)=q †Ç²r‰3;‡ÑÍà1³‘íöýìv ö‰õmk—XÈØeØšôÔRó•ëêØÇ(âªTÖ£z×çíÙ¡p?6Gj |ÕæçµÕ1E¸iiªÓ³R^™²#«Þ»ehtRÕ ¢híT+«ÃN~¥Ì9èæÅr·Ø71#×þÆ×¸é!IxôÙO7nRº¨œ¼æî$Y„šÈKQg›åêwL•\ŠYÃEîû³(‹hÕÀýƒÂTp%èÖk(|^–®ðõ§þ„PÜ $¨TmKŽ7ZÙH]"j endstream endobj 609 0 obj [ 608 0 R 610 0 R 611 0 R ] endobj 607 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 609 0 R /Contents 612 0 R >> endobj 613 0 obj 356 endobj 615 0 obj << /Length 616 0 R /Filter /FlateDecode >> stream xœÅQÁNÃ0 ½û+|„Cƒ“´MrdRA „¨ ¤i'pX‡&ø}œ&lÍ ×®=øÉŽí÷üv ‘ø/B0Nás»”“hê:¥ªe)T…=&\á&¼õ‹8ÄG Þñ¶@x Ë_¸áèxÜÐÜA;Ú*4û~Â7Xx¸¸ªPú×É´V—Î9²h…V.| }Ë3¹¸kŠæé¦ó]ñp¾B Ïäh©N §Í8°¥FqdôЭcŽ3qP(m’)Æ©Fr1N’¢'SÊ=žuù´½FsFØÌV+'­œùd\ »÷b˜:»j‰HfšgMÒ%Ý|­?£ªŽPZÔNP]ó$»ïØ®Åè-ü© Ú endstream endobj 614 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Contents 615 0 R >> endobj 616 0 obj 278 endobj 618 0 obj << /Length 619 0 R /Filter /FlateDecode >> stream xœÅX[oÛ6~÷¯ ò0$EÍò"‰Rsº´èeŲ-ŠØh›¶5Ë’«KSï×ïPWÛ¢ää¥stDñ|ç~x˜oŠü õCx Í·ƒoåE‚!î”K¶ƒ¨…™¶¨¤mè]«(x›€X£/ƒp@ÐÛÁý>.†‡9…Ë™ï·òõòÓåjÀ)û_4¸=Ž‚`ŸÄ&çæÅ¬@úSPº­|¨Y(W<;•"NÄì”RÝŸ'œ Õàz)g˜[6|`eÓÅ«l«Â4A2\ Ï2ÈTÒ£0ØgÛØàX‹Úí|j5 êËx­fCÑ¥ë¢r‘P’Æ~¸zŽ’ýv(ŠÑÝíG¤~ìb•$à{ܯœp°€&Œ3³7Í ¶ØFMW‰fÿ¨yŠÖþ|j)³¼•FèYù2¬¶>;£œ'°pÀ Äj•ˆY­èô‹?ÏÝò-SñþÑÎaº9ã8%dT¤Í9BšéŒ<îa׆ãÄqù™J2KmñÐuJ6†v§:sæ6%”ÓòÄø]%óØï—›Ÿi²Õõ\»´µ8ht…‚=t)k*OÛêe.ƒ@-êמ¦Ì9æÂÊm«-­¿šlÑÃZËöÃǨá@P…݆9[2ÐîÍœµÔ¢Xª·ºhª(žŠ4QýMw £«ýª8+·g ´“S‚Ê ;V5ͱ‡‚c]uT¿vûÌõ0t_,« ÙWÍ„ö06’u®_ŽT,J5i sšw–ž*ß¶òÀ°ÙÁ¶d§æþÒWsßu öœ™\`˳<φA·eÛcZŒExB£ÃNÆP©Šq³9ÒÛ„8Ì´GpOèA0lµØA²ecQæ`AvS“†©Õm¤Oï>v‹n7c-w¶¯É²ŠšOYCûˆlVײ1@ÖT…Ãî±Íƒ8Q¡o¬ùþº‡”‘+û‹)¢ÓéäÊA9†¨gí£mΩ&—•ñϦ•ªG®4J§fƒ´ `]¼µ¼@w© üˆ$'~K"ˆRŠ£xu1¹2)æš\€U¤aÆq”&›=PiA#½S‡”€ŸüŸJúg ÔÔw 7%yÔ&§Ix ¥¿¤ëXý»sÐYIže:& /ôœ#ЯYìÎ(\ÄÑ.Ò²$ÏBrn†ü…0ÍCóò+Tá&z^Ñg¡-Û ý‡¿YC‘ÖÛ(žÉÒ³«Š>‹k 3îuû }U0åzï ê,¢þˆ ñs þÖêϬpÅN?'WÏ yj»†`fÞ9þÖÝÐtç¨è¼s˜õóLAB¸!;1pô<"Ê«à¿Pèf¹„BînÜ Ó±,Ì9ÞíØÕu%oŸ0)TSªÌ{î[úŒ´7 ¿ÉÂÐÐÃþ;y;øÿ£zþ endstream endobj 617 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Contents 618 0 R >> endobj 619 0 obj 1571 endobj 621 0 obj << /Type /Action /S /GoTo /D [617 0 R /XYZ 72.0 720.0 null] >> endobj 622 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 73.504 186.0 82.504 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 621 0 R /H /I >> endobj 624 0 obj << /Length 625 0 R /Filter /FlateDecode >> stream xœÅXÍrÛ6¾ë)öÔÆ™ @€3Óθ§ãNšÖµ&9Ø9Ðd©•H™¤bûí» J&!Jé!•\’ØÝo°»àÈÅÿØ^TÂaº=4Ï(QÜ<’10A¸„54´„•]µGpOáÅ-BbŸFو¯£›ÏørG´+®f¾]íé·oè7׿ büApõ2 Š+Ò‰M͹gøÄ ²¯VÛš«“êHÎ]‚¢;L4ì”î·SNá~ôËdôã; ŒÂd¾KZá¢yb&k¸y¥ÅÙg˜ü6º˜ôBù]Ö‹¢Õ݃Ð1ªšRÊ^ØTGV569“>¤k㌠ø@hà ¡±´ëµcxû׎?^^|ÇÖ.f4&n¡P}¶[ÎU— 1ÀÛ"ß”Â,­Ò»´4ðei‰ÇªX#4¡("v"Þm³iµÌ3ÏsØ-qB$ÓI¢Xã–ëç¬JŸìaÇb~sõeÞal+¶£¤–‘ ZÔ§šz&·‡“»MÌ¢°ÔéD5G’kcà|Uæí÷™ÝçŒNIb¿ L×îûH¯QÐ$zñ©gŠ ¾2{£KýÍÇþÿ—[¿© endstream endobj 623 0 obj [ 622 0 R ] endobj 620 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 623 0 R /Contents 624 0 R >> endobj 625 0 obj 1345 endobj 627 0 obj << /Length 628 0 R /Filter /FlateDecode >> stream xœÅX_OÜ8ßO1âáUÉÙNl'•î$NGOœªJ«ö¡T(ìz!×Ý’loãØÞ„ÄÉ ·VCãÌsÔ(ÒÚDüA±æ¾8›ÙóÙ¯9PóU[´2DN³DÿÌ7ðí0Gßaþ÷ìt>Hå‡lE½sMǬƄú̧&³Òúd\úœn”qʃ(–Dp½?6ŸÎ.æÇ_ÎN¿^€‘Ûí¦Dfg$‡r—ŒÉ¾€T½-ó RXgU Å –i^§•‚Ÿ™z¨g·ôØÑ€$µ £íã6_ÔY‘;™ñ‰$à4NImˆ.žò:}t‚‰ŒH"QV1¾ùõü#ÏNíÛqãO?:‘o;üòC=3MéYCcâ‘*rUŽzÀ¨Of„QápÙÇ^~ûJUm×õþÜÐ0 á„D±­’“òf»Qye’/áKºÞªjÜp+TàˆÂØœÁÀªöÈœ@U—Y~óF½¥Qˆ‡x(úùìÓ8˜ ^(Jø®×Á´k1 H(;rý”ø½ˆ´'­¸þW-jx¸Í·°T«óTA]À;»8v[ßMÇ ÚuêyÒ½¦ …NvÍÀ$ íãUÃBì6R£åOU-Êì®Û¼ÍcWOB±ð®'Áq"á0uDc”¥Ñ6KYݲTwè3+2OŸ|GçØ‹w›³ÜQçPàÕ®›„ÇØ½ÙÇ‹kJÞ`’o»°k,K½º"„@À8‰EÌ^r¥ODƒs XÕÒ£‡2!Ø}Bô1 =Ê&&‰§D[ìë§–¶i»PšåF¥yÇìú6íì-òuGUsEt^b¨–~Ðm¥ÊÎδTíBשZ-ãl5ŒÚ0[aÂÂcBC…^›·ˆM û3˜¶¤9E½ÛQ׌{ª–*/šÃ•‚èõš8šð™¨]O] Œ‰€è )–>ˆiWŸ —ùñ€‡Ì-É^mEN ÆY_&Pߪ4a‚Ó1nO qØ“L bÉÚÓÇts·no_ß F û9Þß1ìXØ€àCã¬Jµ<¸<¦<Äõ\‡‡Ëõʳ¼ºº)‹í_£°XGÅ+mÃ{ws¥ëì4UnÑyC6J ‰pÇÎò¥zt‹ªNëê`ˆ‘~ˆô$é$®ÐÂg:fõT ™Ú2ÇõÀÐ~$»0YáB¶ Ù{ÀðLíñi›iÈm€Ûƒöóìqk ÕúåãïÃãýÊðàUê~«ò…±óÆ£[LU‚³Í£ü*ÅOŸYýÔa¹;Ù $Çja],~8Ū֭U¯z§ Àûµ£Ǿ¼ìo/œò€ÑP&íGX¶TpºZá0ZMl{_( ~½ 7o¹zACãBM;‹„O´æ¾˜DLhs3ª°_4ÃAè_Œ4ŽpFåÂõÓ…j&Ô?ú³z«SžOú."œà" šäCß›ÿYœÏþ¹ô¬A endstream endobj 626 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Contents 627 0 R >> endobj 628 0 obj 1248 endobj 630 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 97.514 186.0 106.514 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 621 0 R /H /I >> endobj 632 0 obj << /Type /Action /S /GoTo /D [620 0 R /XYZ 72.0 720.0 null] >> endobj 633 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 85.514 174.0 94.514 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 632 0 R /H /I >> endobj 634 0 obj << /Type /Action /S /GoTo /D [626 0 R /XYZ 72.0 720.0 null] >> endobj 635 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 73.514 180.0 82.514 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 634 0 R /H /I >> endobj 636 0 obj << /Length 637 0 R /Filter /FlateDecode >> stream xœÅX[oÛ6~÷¯àÓÐ5Ç;Åàbé¡(Øh¤ym:Ñ&K©%7ɿߡD]lÑró’Ù>¼|çÎÃC›PDà;u?Ú0´ÚN¾ù9Š4C\ù)©˜I´Ež–(u»zk(ø©7q¾L² ALnnaq'ä˜]žO®{òÝ yuù} 8eÿ‹ׇQÐLã£ØTh^ÏÁLÍÈ-¥Þmþ·æZ“µrõïI¥H§ ;Å«ûz º›¼_L~þ %h±é’Vs˜Á3îÃÐb‹nÞDÑÅ-Zü9¹\ BùÊ.DÑÉnÕ!ª!„ØTEV{›j“>Å[[ðˆ3˜(éöG5àóÕå—éåßWóÅ|úª¡-€2†5q»Iú•1} à  ¨Òt@ [”Úä;TÞ[dŸ’¢´ÙÊ¢|ƒb´ŽËx}Oì#nŒÐ#ÅÄ8µTÍ÷Ã>[•Iž5˜ÓþRK£©÷×ü9+ã§hÂ(Q˜ ¦9õfTŸ#Ë#Øé,™VfÓ‡cW)âݨŠéBUH™¬ðúÔeüô¯}ÄXHPþ˜ÙÝIIL=5"D…ÖäÀI9ÕÙÊùõ7´³Å>-ϧå g&"²FÏvwû­Í 3ãl>ÇéÞ§w)! ÖJ@r3ŒÂàØ¾ÈN€ƒ¹äw§Áå ŠAT”»$»{‡Šçí2Oœ–ùõG8-`biŽÇ•‹¦š#D.¬Ý3kµ8\‚CUB?]}<-LÑ ÆùKœ¦ã¦1¨+wLÊp¾­Âf]±É—ÿØU‰ï“Õ=ZÛM IT 2Goý`Úl}{F9¦0ˆ D4>ÌȰjÐ ½ÏóÔÆ]”O§2؃#)áÆ„ßm±Ú%ýb¼"¸„4Q{oÔ•ùLÑW =é2Ó“]¹ö¸žŠ³†r™êÉ*¡=½‚ØÚu3© œ‚E`+u÷Ç@ËÑcV{ã$¶žd? †Š°puq%¬Îf§j ß(P'´¹×x>o¨g¢aGÇ+€A@8pþ*Zòd)ˆ`ÙÀÓZX¨å#ÐVôò¹%½7ÚqãÅz´…£Ói\ÞÇÝÆÅÛP¸¹Ú <5Œ7k*iÈàñH 6 Å,n©º u!.Ü•ÇÃü¶Y^Â^€N!yUÍÅ“Î#ÝÈÈwÝлØ7‹ÞÉ~¸ìí« ­¡×‹x@Õq15 îÙWÖú‘õSUhÏêÊ¡µ0’½Éë ¥b ÜÉOz.uwf7‚bõlê/…ì $T­C¡­'ÎßE\H,ˆ°¿c/ûvT¨·æ®àÀMDÍ›â°gF7©Í’¬˜ÞíòýÃí׋€ÖFñ€fp1Ü' Òîë÷ñc¦ .°QpIKåŽódmÑåfC1vÏ‚3±’ÐèЦ7Ê3ûÎá÷eþbŸUÂàø,ŸÇJÊ1#ÀRG8¼<΋—‚A‹ š³&˜+[u1¼X“r;zÔt©4¼Œ0nø‹l—Fbí=ãBxo[‹fi‘·õî­ ‚¥ØDÕŸOÕcygE˜¼ûW;—vê2-ø€ãÊøK¹®wùÃ8OW^Æ3…cPñ,zLÝ÷?ªºa6 endstream endobj 631 0 obj [ 630 0 R 633 0 R 635 0 R ] endobj 629 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 631 0 R /Contents 636 0 R >> endobj 637 0 obj 1274 endobj 639 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 561.292 174.0 570.292 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 632 0 R /H /I >> endobj 641 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 549.292 180.0 558.292 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 634 0 R /H /I >> endobj 642 0 obj << /Type /Action /S /GoTo /D [629 0 R /XYZ 72.0 720.0 null] >> endobj 643 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 537.292 198.0 546.292 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 642 0 R /H /I >> endobj 644 0 obj << /Length 645 0 R /Filter /FlateDecode >> stream xœÅUM›0½ó+渻*®?ø0Ç´J«VU¥4¨{XíÁIœ‰@l7ù÷c䃬ö’’ƒ›yoÞ<ÛÙ: (þ\3„‡ùÚÙ6s B"h¦ü˜G¸khbRóU/à‡ûàÑÉ _§g\\Å„W‡žÂÕÉSgÒã7+ôæüVΧØùøÅF!^v-ò‘Ňù ‰à‘y8Äkxºûük<ŠÇîïoãÇûgˆ¿;ãøH‹`ü?h™Õ€~†<$'.×ÙÂÎáŒ2Kic@3ZTÚâì8Xíj¢ý’Ž ¾)ù°·¡À"<•bÐÊ·ìÌEÃÝŠÁÒÑUi6摦ÚÙ°Ñd%–K=¯ôf{«íÒ6— "Bƒñd“÷°ÐKõ’VîBUj¦JýpH&Bâ#@²d¼›ëM•ä™B]Iõ¢L\^«#bDRŽÐ‘ßÔŸÁ=0IB¸ÓE‘í[R¶a™¬!E‘íâ² lÈuBÇ’vn°Gy׆j¿ÑÕ6m}ÅÀµJû>0*N„Uʵà(¬k86ZA¡ÓÚY˜7. ¶œ#,77ªïE8®v››l8TZhµØƒÞ%eU’··+œO©'¥Å˜j £´ÌÛ[ ;„¦'ž$œJsëSVHÏþ$E¾qÿ&úõâ½b0ú^ÌåÕ˜å hÈß jð\Û9wÓÃ}ãºAE¼`èg^é«'œ Ü!úh*lR2MzœçaäG endstream endobj 640 0 obj [ 639 0 R 641 0 R 643 0 R ] endobj 638 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 640 0 R /Contents 644 0 R >> endobj 645 0 obj 609 endobj 647 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 709.5 180.0 718.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 634 0 R /H /I >> endobj 649 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 697.5 198.0 706.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 642 0 R /H /I >> endobj 650 0 obj << /Length 651 0 R /Filter /FlateDecode >> stream xœÅSÉNÃ0½û+æ‡/±ã\YB@iÄ¡¢"Úš@Ëß3®Ó6KƒÄ¥$füÞ,oüA80üwD±€§)ù¨|"RW.¥‡T(˜Be+˜¸[5C¬,<ü%4^ážd„ÁyxÄà愵é–à!Ôò»Ûy~/ä0!§ 8ƒäy3¢0¦±bøE •"vŸ€d {Ç·×7ÁÝùÉýþ#$ä$it"¹ø‡NPÍHD´¥ñ-½=žÈ…&Õø«Ó³zÓçÏޢئ&V/©)ïN“÷+IôPÓPÔ¨^)w<²ŽŠM CãwkÝ^ÜnuÖu’eð•Úy±µI¤ä⯜Ž.° d.‚÷횇ŒûgðñUhhd$bå¹®òÒV¥m{ˆ£Lkd2±G$¯V¼ÞBhM™{º’©.4}ƹ-‚,/}ý½‰¹6¿ðÀ›ýžç³1Œf/ŸS›•Pæëš:ÊPep|Z†]®ñ,_ Ô[ .â/xH ­“ëXr*œBð.øèr8¸ìO¬óPoIl¥ÍŠ4Ïhmä´|Z9 endstream endobj 648 0 obj [ 647 0 R 649 0 R ] endobj 646 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 648 0 R /Contents 650 0 R >> endobj 651 0 obj 432 endobj 653 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 678.764 186.0 687.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 621 0 R /H /I >> endobj 655 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 666.764 174.0 675.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 632 0 R /H /I >> endobj 656 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 654.764 198.0 663.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 642 0 R /H /I >> endobj 657 0 obj << /Length 658 0 R /Filter /FlateDecode >> stream xœÅT±nÂ0Ýý7¶C\Û‰ãxl+ZQ¡J(Q¢n‹HTøüžã IZ±Pgðéœ÷îî='ÂáãÙMi³%Ù”9J€–)¨°„2–°°oUqˆps/að#²" žÉx‚‡ïÀ°#윮ÇdX©oOØÕë3ø$ ¹{’À$'‰Mµd¸Tõ…¶K@²„ñÍ 'Þ[¿7Šo'¼^RÅçâFÖz@;•PôÌäí»f‘=Z”ú—»cu¡kÎíM±SO¬ÚRÝß«ï¶Vù˜¡QÍÒHuZyeÉ.ÚÚÇa°ut5Â{Ék3Ϊr&7Rl Ü/²ô8؉7ˆÀgT¹¾àÕç"±Æ­ŸmÍ47Þ÷ÜìZµBÒ@\Jú¾M׿RÊàRJËæ™ý<Ë3o]¡ýC?Í©ä‘ÖŠ—ú½¦¹É¾¥.¶Æ¹¤H¥¥ƒ,°h1Í׸|œµažÁ °! ¹ý…¼ý8ˆ‡ƒîŠÒ‚Qi/s³´Ùçf•ÍÓ­ˆ5$?RJ¤ endstream endobj 654 0 obj [ 653 0 R 655 0 R 656 0 R ] endobj 652 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 654 0 R /Contents 657 0 R >> endobj 658 0 obj 406 endobj 660 0 obj << /Length 661 0 R /Filter /FlateDecode >> stream xœÅRMOÃ0 ½çWø‡fNÚ&é´¡¡ Qµb“¦¨´¦Nl?gÉX»¨×Ñl9yö{~Ù2HdƒÎ$¼­ØÖ×h ±ò¥TH¸La>OaioµyÊ(¸K”|Á”­Â›/èð{†—íŽà‚å­ùö¯>á“Ý•l0JA ”ç%‚›,EÄDá±Ìì'¡\Áüæe<œFÃÙ¸(‹èùvå#–5±ÿ &ïp GµÔüÂç#:v5ª¸Föhé-ðÑuu©#çb/)!ƒõ ©B(Ô ¼Â £L’p%ˆ5*‚ï'E>韧-–d¥dF8¸:ìªuSoÖ¼å`Î~qåú endstream endobj 659 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Contents 660 0 R >> endobj 661 0 obj 340 endobj 663 0 obj << /Length 664 0 R /Filter /FlateDecode >> stream xœÅXmoÛ6þî_qŸ¶¦˜5¾I” l@Ú¦C‡¢@cäƒlÓ±6YJ,¹ÿýŽ"eIMgÀÐ%|¤y¼ç^x|è§ ‚ÿSý!‹ÍäÉÎQ xd§Â¨X°r¹^ÕX+á‡Y„Âþ˜¿LnïñË%Tø:!ÇÛ5Ê7“ëž}ý ùæöû8eÿ ‚ëa$“ÁQnmnæpÆl¤¿ÊmØì§ÙÕˆœù< Št˜ˆ;(î·3Nàaòv6ùñC”ÀlÕ­ä8Ä,Ñ f¸}•‹{˜ý:¹šRùC6Ê¢¶}p¡cVcBøÔdVZŸŒKŸÓ2N9b b`I@¢P¯Â»ß®.gWÓŸß_ý Fó°ž2ÄT/Ž’±æcòX£Cœ’³±¼Ûª´VÂ2­ÓyZ)ÈŠ¥zZÀÒXЀ$DC0›|Ø‹:+‹Vçtl¢$iœ$’ÚØÜì‹:}n‡1JBÌŠ¶&B‹¹ù;r3Ž•‹Æ¹iãÑqXô1oÝ"AGPhÄ E/·#ô4vÚøîoµ÷bÌe¨‹îÈ ã.ß}q(ìŠìiwÚ&ÿeÀXìò#­ëm6ßÕª:i‰ —¢Çw–I[Чí$N~úβ>U$á„0n×åöa·QE]AZ,á÷4ßu.Ž!kÄaÈDàQ¤r\L£FA©Ke¶V Õ \A½¶‡Rºxøªýf^æPnáæú¨çÇ­ª*<­ŒF!"dÇèÆ6RècK“‘«ÿY’ÇFÔU¹nt#¥Kx[–¹JÏXc ›]ˆý“&'+Øiq¬x yVÕM4Ú-šøTg‰%ʉpW¶ÛþHí²ëñåü/µ¨áë:[¬a©Vé.Ç­KxmÓvéëàüa`’xh“X{#¼WÕb›=ö/÷Í'¬B¹àöêk:v  ¯Ò¢•LaÛÁ"ÍsµlGžž-x€qÀ‹Š1‡1ÿy‹¤O·5^êã׊M­ÛAõ¨Ù*ëðÎ÷ç‘3}Sâ-‰×¬tX÷„•ÅÔ§ÙÅó P›áMOEœ8¶:[†X>ý€©B;°õwˆdÙJƒÊœÝæXKœDGû›òEý©L€7ýè0hSd‡Ý¡î-);yWõ7±³ò¢,°íÿ=Õõ`¹)];ôÅ›T"=±tøã-WNCŸnÏÓmZ¿6íTSg¡ò8 ¢0"$DŽ36÷‚)„w‡aÞ¼ ’ÓøHùÌ…€\q¬£íákDê™›¼›ÉªN>Íöx°ˆb{ ÇþŸ?~:ÝkBáS팛ä¹;)í—»>äUOîͯӞ/i'e1õp?.“8f®pû\Ó5íQí|ÑŒ©â *£ž;ú<™’µn ¯™Ûìª×_”£epâ,h°T/¸ùx(ƒ„Føzm4WÏéæ1÷°[m7áA„=1ŽbK•îO¸§Û{xƒwË­ÂÝʽR÷ÇýCò:ÜozùþîÕí*ÛVõT·‘{¸ÍÓNV›4Ëïï.\6Ðu¯ ²úïÍ¡ò\–…ãx4˜ªgdLÕôÑDÄi":Žš˜9ÖI·çsb”…~îJn©ãM¶TpµZ!…òô·BtŸ&H!8µ¼è²° ;ŠÉøômršÁpdÕaó<¡ŽýÎ3AìÓý”xˆ%N¢_:¢å‘çˆ|¾÷zãÑ‹$aqlã6&—/øÅ€ÄHÜãDJ¶'l¡f™æp“Õ»TËÞ< ñG~ŠíU¿,Û<\`ltkPÛ->@ÚQÓéXeEË3í—«ƒèãœ$ yè°{†qŠÓš.„EYä´Ãm_W‡±yeµÃž³úÕuC÷ú:ÌŒRÙ¢Þ?ªÎÔS~È- – qä’9³9:Ö…<ÓOÆ­Ê›äBË÷O3'¢‰>–O(‡ oØ™þyö´.¤9ÔåL/ z?O^OþI˜SI endstream endobj 662 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Contents 663 0 R >> endobj 664 0 obj 1496 endobj 666 0 obj << /Length 667 0 R /Filter /FlateDecode >> stream xœÅXÝoÛ6÷_qO[RÌ?DR*°šÚlYŒm@ÓŦcm²äHò’ü÷;ŠúŠDËî0t΃H‰w÷»ïcfþÍÍC… –ÛÙCýŽ‚bÀeýJH ¾Çl¡^ H̩ނ5+|ØC¸ØÀï³tFàÇÙÇOøq gdÈ®"¾™]÷ä›/ä‹Ëï#à”ý/®_zA1å |SQsûßXFæSR›­~Z®viÁÙçAP¤ÃDÜF©á~9áîg?,fß¾@ ,Ö]Ð*Žo¼€…æÇ`±…g!;ÿ‹Ÿf—‹‘+¿°ÉF^4²[e:z5 „Ð:UžUµNV¥«h«­Rø°Ð#R˜ó%xóëÏ¿Ìß]½¹ü,]{šRêÙ“¾ÓÝ2¦†lŠÞäÙ"XEetât¥Ÿ¼¬r€õ©GB‚,¤eñvŸ.Ë8KšÃv‘¡'h†ŠÖv¹yNËè©! Â(^($òb âê7P2ð'W¨Ú¼Òghßuˆb„ â H{^a§Ê)ã«¿ôó„ F]‚âõ|•ébžfå\?ÅEyPj•$Ÿ£§.wÎKà.„S°9|SÇÛa9N—ÂwßÃñ8£K:ᄈ&Ì/òûýV§eQº‚ߢd¯‹ÃM܉À )òæR޽=Êa*‰ƒd±Ñ`È [C¹©s "E™Çéý7PÍð‰V|­ó·g&jà·çÞñhf‚{À²É¯»ƒ.–y¼ë]gWQÇLµÇPbE,àæC*$íÆg»]FI¢WÝ~¢8úÌãT!pî;dÉ9EÛGwzNG£çÒN°ÀvÛ†bgЬ[;‚³ûøn}šLpv;ŒÒA'«f2\2R¡&ÎLÁkÖ‡-àÈ"Ð\¹8~FšrŠQ‹$.Úe“#Í푞€˜ù ¸É—€;$ ›¿+ÇöbÆ´@ 5…5×å>O‹&GoTa¨|@¤ƒáÕ»÷‡±1EÚÊ~Üè\GEÏ»íÒÖ‡ 4p•Íãàá„\=ÑË…ô¤épDR'éÉQ‚­r‚ x[.=d†—€ÝîKѵ2Ìà8Õ¾{3Q.êcZ6¥¾S=YOPöà$IöXtû²5«Jx”toŠ^Æëx™½ƒëdzªkwÛ¬[›ð? µ-1v»Î³­×m›¸·¿ÎõÃ>ÎmO¨I³Üá.ÖXfÛ©q—Ïð—øðŒCÅ ½Kß ¥"8 Z^—OÑv—tÛëÎàêù‡ªê[‘ÕÙe1ßÁÇu–}º=ƒ÷)IŠóæÂq „®ÞXîØú‡éÐLNÁX:†‚§üð_k&éH$ç}ʨ)ú§|&Ðü¡ a¨šò&^i¸\¯qŠ+¦Á0t„ÂûasA¼Hë¡ÑXx‡ágFÉaG5;„ùF±ôNП²B`Èr‡DÑŒ²•æˆüîyR{^¸OCÕ^ÎÇ#Ä wl¢ð‚ù'y›2KÝš›¸ÜWµeÒ’ãDÇDσ¦aÒ«®ÍØ]U ì²m3ÝÇu»œòZœ0¼¬9äýÔ.„˜‰í:êpמvo/>Ͷ§¬¹µfè.Dí»ƒVÊ:C”Ï;݉zHZßâb>ÎBéûÅÊhn™£bÉ'Û6Å’È0 eŽÇn¶S´`J\úu ¶ÂUÃæá‘ ½D›¶?æuúüÀ¹ñ<æ‰À w€ÚT7Ùêfî·/f‰êߊ׳ÂRR endstream endobj 665 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Contents 666 0 R >> endobj 667 0 obj 1468 endobj 669 0 obj << /Length 670 0 R /Filter /FlateDecode >> stream xœÅ]oÛ6ðÝ¿‚ÈÖ‰ÆO}Ø€ M‡],Æ6 ΃lÓWYJ%y‰ÿýŽ"%ÊŤ/]òà»#÷}<êëŒ ÿê'J(Zíf_  ˆ"’áh‡ ,P¦võÚBð£7ð€þšå3Œ~›ÝÝÃâa`xšááq óíì¦'_­àï.¿¯#ôÑàæ8 ‚Aln¦i@Ñ©¥Ì¸ÍüêS5¨•Ó¿“Ja«v;Ũûý„côyöë|öÓ{FóMÚˆ%ˆi¢þ(šïÐÝiÂÏîÑüÃìj> åwvÙ(ŠJvg ¨Q1ÆäȦ&²‘±I›ô)ÝIm”ÃË*huºsàDêóÞïóU½-ò–gÚMa'IDŒ›ny>·Œ‰CÁa†c*Œ8Ôü ,޹c§²îÂX4ôªˆñÑ?|‘ÔªÊ ô!±c®ÖònÅ.mЧ\–“¦RæâñèB9v0´œ–;}úó/¨”Õ>«_"a"HOFM/ËÏûÌkȨ|þL³}ëo—â*¨!¤TJÆçŒ vð\¢ª.·ùçs4i-á *~Ìúéúã´0ØíâAE‰Þ¦YøM‹Y ð‰ˆ;$nëFl—¶(‹å?rU£§‡íê­å&…8U¨.Ѓ\´[ßø•£*ð1Ha‚çî„Zc†ùƒD947Õ5RR3‰RÕJÚXT‡Ý²È”³no>"ùüyUAw8ïµ›j†¨S*µoºüY„B à&«â "ÂÇú‚›hÓ§0,ÒûkÃíªÓ¥µ·ñíªÓÅEE=IxlNy'«U¹}ì7Xç… U 'rSÓm—?C8¦lë0аƒª–PJA¨n [jÓU-ªcÙ[µ°§ƒ…BÝLІ8wèÿbÝ0Â|üV]8ÚUPGRêào®©D û{YäbQâÁåºÊ“…'A¤O”8ó67ùX­ìåÁÂÆ#–Ð9T£;™æ=µë‡´··È³ÞQæ6î-ƒ³Ön±ûJ–½i)-¢X®K¸ÞŒý6ŽK€$ÐÕc,¾9rœz™Ý1L-¨Kk0+@1“ãÔ—yaê'×§hH9¥CTÙw˜ñ´F¬£Í¢ñ³Æ–v£§>¡£Ñ$„q G%ý΢ÂËl-k¢ªaT71}IKÏ BǤœ}³–Œ{™­7­#ÕÐ!õƒÌ­)½…¡ûf:á â &Ü»m!’8 èfÓ§¢\[Bjæ.KñŒ®< "Á .9¾1n¤iF+:Û§j¼î«®ïÏþjaá^OЄ"Ÿ8¦z”«íf+{>h&*°„ß¡Aélö™¥ýÛŒ¤ß¥·§3N_ï ;ö7UÛÈd²£GQ "¸øi§ù::ô!§½h]©QÓÓg–d»zƒÚ®ëT7]=¶¹Þ.51˜0yUäÕv-K¹>ïí°`7Ãw=@v¸š[X”bgKG) >ðÄÑÓN®Í$«¦•éº ™ú@0>ïÅñ„âæT3ï`ÖÚ€›@=Èïò5£"‹¹z¡`cÓ®®žÓÝcfß^®÷4§$ ÀDt<ýýàè¼8;“36àçââôD‚´â åã—t²*vi~hàt½.`™–'bÈùfW'‹È« z ½àÇÅé:ñÝ!÷‹3§žaâÔ³SÇêèd‡®é«í …€;ˆS˜ª8æÃÄ]m6ðn«|c»€Ç´€æ²¶Ö‹\¾"ú"äALb¸a#£ìe# zãòà•¨†Gÿ06Çï+¾ä¸Þ‰À4Œ»ä[Éæ•’fèv[ïS{m95­kh{ó-ðfö·91 endstream endobj 668 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Contents 669 0 R >> endobj 670 0 obj 1484 endobj 672 0 obj << /Type /Action /S /GoTo /D [662 0 R /XYZ 72.0 720.0 null] >> endobj 673 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 97.514 192.0 106.514 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 672 0 R /H /I >> endobj 675 0 obj << /Type /Action /S /GoTo /D [665 0 R /XYZ 72.0 720.0 null] >> endobj 676 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 85.514 180.0 94.514 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 675 0 R /H /I >> endobj 677 0 obj << /Type /Action /S /GoTo /D [668 0 R /XYZ 72.0 720.0 null] >> endobj 678 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 73.514 192.0 82.514 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 677 0 R /H /I >> endobj 679 0 obj << /Length 680 0 R /Filter /FlateDecode >> stream xœÅX[oÛ6~÷¯àÓÐ5Ç‹HŠ6ÀEÓ!C °±Hó ÛtâM–RIFâßC‰ºX¢åú%³tHñ;wêû„"ÿ©}(ÍÐj7ùîæ(R q馄D4ÀL r´@±]Õ!XMÁ£ZÄúg’Lúsrÿ/׈àeBúìJð|rבoß7—ßÕ€Sö¿hpwÅîŦDójf*FöUìÜæž׊¬”«ž'•"­NÄï§îÛ 'èqòq1ùõ³@” Å¦MZÅa‡LÛC‹º§åÕZü5¹^ BùÆ.DÑÊnŒÕ!ª!!„ÙTFV9›*“n£©Œòø Ó˜HaׇàæöÓõ×éõ×›ùb>E´PÆ0V®àCè7ÆTÀÀ®‡ëÑÂäEŽ6i†Š'ƒÌë6/L²2(Ý ­£"ZF¹AÛdm^qm„òPL4ƲbüyŸ¬ŠmšÔ˜Óþ’ j­¨ó×üÑk Ôa”H̦8uv”¿žåaàYYš2- ͧÏ}_I/óZФ§ U>I'âý©öÊøå?sĸOPú’˜ì¤$&}˜1!Šxuœ”éעßÿ@™É÷qq>(˜(Ø4!z–=îw&ÜŒ’5ú;Š÷&?­¸Í ¡±’.ÏQì;Ð×YÀ°0›þv?”É‚"PåE¶M? ü°[¦1‚ 3¿ûælÌ!Ññ¸v!lBŵZyBçWo€™5ZœÎ®€C]Boo¾œ&©cü-ŠãqÓ#Ô<&„?a¼Ö a³¶Þ¤Ëͪ@/OÛÕZ›MY”£"EïÝ`Z/}F9&1ˆ $¨C|œ’~Õ ú˜¦±‰Ú(ŸÎe°‡" „k·>™|•mŸ»åÐ{„p$B‡ÍÉQç+Ø—X¢w¶H×´MΚn‹v=Ù[“QÒ6_kºJìz´‚ ›u3«B kefÌ£ïèŽcBŽa;ªýŒ"pjP-59ÊÃìlrˆÞ¾Ñ ÊÀzÔdb†´!/ÎLÍzBÇ+‚òA@úНå-}²8hè¶ô.Cf£%‚„cÐVöòÐÒÎ#íDíM7ÜÁ†ê¨]> endobj 680 0 obj 1260 endobj 682 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 678.764 180.0 687.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 675 0 R /H /I >> endobj 684 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 666.764 192.0 675.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 677 0 R /H /I >> endobj 685 0 obj << /Type /Action /S /GoTo /D [671 0 R /XYZ 72.0 720.0 null] >> endobj 686 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 654.764 204.0 663.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 685 0 R /H /I >> endobj 687 0 obj << /Length 688 0 R /Filter /FlateDecode >> stream xœÅTMOÃ0 ½çWø‡†|4KrP&•UiÚ‰˜Ô}ÑIìçã4ÙÖv«Ð.%=Ørâg?¿¤Âá9£­€÷Ù„-@BH €ÇT(X@ðîTÍ{?„μ’%aðH&SÜœÄÂÚpUò˜¤µún‡õ^ŸÁ'¹ÍÈ̓Î û8Ž(æTÆ W`¨Ö-Ù&Ww/É0K¢§Ñ}òv=…ì™$YƒŒäâȤPP-4mÉ\eKÈr[EP Xê]ßœ·M±cO¬ÞRSá^‹w‹«%F¨iˆjy§”=ìDEWû@[GU»™ N•²:pò”Æyâ\ˆqc’QíŸ|…kÛCb'÷~ö½ZGóå,ßbÆâRÌb^n=f^v¡ªøRÔ 0Êw^Fëî#´œ*n¬Õ<Œp´Úîû:÷“0À¹¢† „²jŸ²Ìi­dJ~–b"± endstream endobj 683 0 obj [ 682 0 R 684 0 R 686 0 R ] endobj 681 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 683 0 R /Contents 687 0 R >> endobj 688 0 obj 356 endobj 690 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 678.764 192.0 687.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 672 0 R /H /I >> endobj 692 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 666.764 192.0 675.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 677 0 R /H /I >> endobj 693 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 654.764 204.0 663.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 685 0 R /H /I >> endobj 694 0 obj << /Length 695 0 R /Filter /FlateDecode >> stream xœÅUMs›0½ó+ö˜P%!!tl›´ÓNšÖ53íL&×È1S9†Öοïbáæ£ÍÅ…ƒ4+öíÛ÷xôP¼ýrQšÃ|í=V1ŠCV!„KXCµ—°*Ÿjløq‡‹{7Køæe…÷ÞÝ=&@1açÑS¸CòÔ›4ê—'ôìõ)øGê"MB ˆ’(ƒ¬'Ò6[û;ML »…¹]ofEú#]¥ÅìÒb ŸžP*Òxs'Þxéßà endstream endobj 691 0 obj [ 690 0 R 692 0 R 693 0 R ] endobj 689 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 691 0 R /Contents 694 0 R >> endobj 695 0 obj 582 endobj 697 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 678.764 192.0 687.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 672 0 R /H /I >> endobj 699 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 666.764 180.0 675.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 675 0 R /H /I >> endobj 700 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 654.764 204.0 663.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 685 0 R /H /I >> endobj 701 0 obj << /Length 702 0 R /Filter /FlateDecode >> stream xœÅSMoƒ0 ½çWø¸Èœ@€÷ÑMªJ¤Mªz¨Úl«ÔoÖŸ?Ch 6õÒÁ!–Ã{öó3[&éuò#ЦK¶-s ®_¦”ÂãRÁÊXÁ"ÿªÈCD‡ýˆ‚/xc+†ðÂFcºœà›á9]ŽYT©ŸßàÕë#|²‡„Ý=+ÉÇiDžÇ]­Ñó!ä®Ôù#!YÂèfЧ?|ê½÷âÛ1$¯¬—ÔĸBþƒ˜¨ÖÈ€ŸÙ\ ]›£Œ%ʯ¥åiYmh›³ggSxê «-Õ¾jñns—2<¬™ªU§•WYÃżöQ µN®†´™¢¦©p6(5YI±1p¿H×Ga'^/y`ù‚WŸ {?Ý™Ifœùjfö­Ã"VO^Ê:Û­7¿s*ïR΂Î1ûyš¥Î¦ÂûǵàJ„Z¢áp™Ôâ[ SoB(¢$*­,dAE­ž²±Bb æ)Làò 7ä¾ ¶Ñ-èÇA º+ú9˜F¤òn–6û̬ÒùzÅ+ãŠØ›Lù endstream endobj 698 0 obj [ 697 0 R 699 0 R 700 0 R ] endobj 696 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 698 0 R /Contents 701 0 R >> endobj 702 0 obj 409 endobj 704 0 obj << /Length 705 0 R /Filter /FlateDecode >> stream xœÅRÁnÂ0 ½ç+|Ü NB’öº &&„VµÒ‡it[%(CEŸ?‡„ÑÒõÊÚƒ-'Ï~Ï/;&é\°‰„· Û…š+A™PÒÄK ¹†µ»ÕHä)£à/Qò /¬bl±¤Ã ¾^¶;‚3–6滼ú|„v—³ÁXƒ@ÈßÏ+R W‰FÄ¡˜+™¸OB¾ÅÍdö0šG£ù$˳èùv ùå-9JÈ“¶8¥VZ~aô­|*¾‘;ZBô]}êÉùØK Ïœ°I©íñU‡÷ÛkUxܲ5±½V^yeÝì_1D\émŠ–¦£³6hò’fÛ}Q{Uƒqr¹„aìž9Câ€(«UqˆŠCYïëèëíìO(ÙÅBYÃ+œ0¦ƒÑÈ ÚhD|?ÍÒiÿ¼ØaI— .û¢ªËmÅ¦ìµ Œ endstream endobj 703 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Contents 704 0 R >> endobj 705 0 obj 340 endobj 707 0 obj << /Length 708 0 R /Filter /FlateDecode >> stream xœÅX[oÛ6~÷¯àÓбƋ¨KH±tÈPdKãmš<Èh“¥T’›äßï%Y¢èlº´€)~ç~ÈC~Y„áßRþ„1E›ÝâK;GPH Ú) â{”£jiŽr¹j@PCÁ^Ä=ú}Q,0úqñù>¦àqÇìøzq5/¿ào.¨#ôÑàê0 ! ½Qlšé9˜ÑŒä§¼u[û«¹jR+§g•½NØî”VÝo'£»ÅûÕâûŒVÛ>iC3^DcùGÑj‡>¿Š£“[´úiq¾š„ò»lE)»3T‡¨Fcr`“ŠlØÚ¤MºLvBeñ!{8àr}¤g«Õ§‹÷¿®Î—«?~9GÛ!?HÁ~dÁÞP޾ €>‰f_5jîjž*·Š®÷y&R”4M•­÷ðŒ¡Å Ÿx8ÆÀ7Ð|?ì‹M“•…ÁÌ;,ˆ=N¢8Ië°ëç¢Iž 0¶#˜{Œƒ´Ðä R#Ë#ß²²3g©¬í†#,¥V1F+Ði¤e6iM²ÎŬ)4°aÐw‰g‡$†±U>¢š•Ę ã‡Ç&`PRÏ[Ĭ>Goß©Ü:E•Ød5äÅ)ª7I3Å>Ïëe²Ùˆ‡F¤ÇÓ…0æÑX Ûz©îö;Q45JŠý–ä{QÏ&Ó‡‡¬xÓqRÌ*ñ©·‚B) ¾MÑdE*žPš 8w`æón]樬ÐõÕG$žÀµt€çV1Œ¼€0(SŸX2É®Þ3T/AŠÃ¡ÅØ# BÀbI>«rSÌY§Ål6‘ö ôòâã¼°8´b¤‘o’TØ7Cœéôôhð€2³ü>«Ò°ÕwˆÞ–¡j°Ðâ/¸<úk[î«æum ·\¡|ý9lG£ë‰îökõ⃔õ5ºJ;¢…oN ò`žÜœ¼ Ù÷#¨ø˜aBüöaèü)Ù=äÂÙ0pxåƒ+ÂÍø‰ð³.Yz«‰òYˆÛ›“©8FœÞ¾Co..Wþ)‚ÿ°Wœ"lùx¾eº æAä…AˆiµÈë,è|»›¦žo´@fL=@ÇA¶WªË²/ðq@±Ç}›jо€)iÐɬŸ]ùíCpBÞ>‘L[ÌÁËÿÕâoÌ¥8 endstream endobj 706 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Contents 707 0 R >> endobj 708 0 obj 1711 endobj 710 0 obj << /Length 711 0 R /Filter /FlateDecode >> stream xœÅX[oÛ6~÷¯8èÃеFŠºØwK· é%±ÖahŠ‚¶èX›,¹’¼Äÿ~‡ºQ–(9{é’ó<ç;w’ú:£@ð.\ß„õnöµž£àšÀœzÊv€Z†iÃê± ±Ü՘ͪM8ØÂ³dFà—٧ϸA†‡é‹+™—³›¾\!ß¿«£æÿ¢ÁÍi\Ó5z±)¹Y5‡3• ¹×n«+©Õ°R®úUŠ(ˆÞ)µºßœÀýìu0ûþ ”@°QIëJFJ ÏôåŸ Á>=§„\|†à·Ùe0ˆæ7öÚ »µ‡ÅÀz„zbV\·6ª²é߉Ê(,Lß Ž-÷{ÃõÕ2˜/‚àöêõïÁå<øóÃå* -uÐÞò4îLÓí3¸S p+ŠC–ä%›4Ûñ"Jà«ôP@±À‹"‹V‡B@qÜ‹Ò p(ø*Fc™«±Ì¢ñ ¢8Ê›C²–’žq':¾aSÏ÷]Z;qyL þØ0ú0JlƒxÈãx5”=?x–fgåż5r^Ùã3‰ŽPŸžJf9Õg(6j†iéx໿Åq Éu4\éC"²Q$Ft< eBŽñ|Ü"æh-úáGÈD~ˆ‹ó©@™i¸N7Ùýa'’"ž„ð‘LJ&Z:ÅejØŽÁ0‰íZš0 Š’Jç x,„k¹“ýÀQÈ1o’û—w«4†4ƒåÍ5ˆÇ=š˜cºÓʹ®aËb´LG9½ržE«Åh(¨Åd˰¾»ºs¨–GùŠÇñÓ|û;öBØú|Ñ[7`[@Ãéê/±.àa­·Š Ç$Ê¡HáEMÌ›­/¦•3M‚Y)ÎcÊiFjU2-@6ã|›–‹6CfÖyü³È×Y´ïvDíùàRƒIo8¶[16ÍúËËpá9oGR—–X§Ø3£³¢ê¶÷–»ló %Û}3–iÜΗ¿¡°š¡àÍ|WPÛZóŽ&ÚUY5T¾ëh‰°Y§ƒê±ž¯¦+ÝÕ± Øœšxm«”¬Çã¸>s¦·™FÚù”gx›&†?©L•ò-¹å¹"¸Öe &þ‘ R‘eˆê±¦fžb0cžAˆC(Å“}¨òtÿbÎ$sÇùùP—áùâú†o_–FÚToc¾;ŪÀWÇ ï–QéÝÊKÝ“·¼,Ù9®ø2éy¡¨4‰Š:)—f:5T䪳ý‹¬³“gB²!ˆÐPW5žºRxó-BMËÖØr&Âd’YáG]­Õ°:ÉŠ$-Nfø©ñŠ’çóËS·cÈÛSéÔáÌ*ë¤qxEV¯Æã~£Œ&7±=Gƒsædw&™~áŠèD¸š¨"|NSß)¶ßfÿ]SÓšdVøQÇ¡ò¾ (lúIÇ¢î’.Ó&ÛΪˆEu;T¡Üœàj2‚ú=²òˆ­À¶ ¯=ZkªÖG-åŠ|ØŠîju¼ÕÄ&ʺbj]ÕD”0–7Ï–ª,Òlk}÷rdC.ðZ>Qƒ¨kÞ4žcýˉ¼(”àø¸g-xCDY¨ÈºÃkö¡ Eá=zÉ‹ô˜ØMzÈŠíäækwÈú(îSï]5•„cèÑf œv¦Ïbiœkõ%¾^‹=%9`Á”{õJQdöáý˜<á*ÊðFI,\ðìúmsùÈwûX=£tllM†ƒ¯yÏfõµüNûp†Oe¥G!>ß] ²¨×ƒÁ;”õL²Eá3xuõ.°À<¼Ü]àâ³û,=ì5kñØOÅË(¢¬¼/²ŒPÊÇÅíO¿.n±w•’h…ó©,ËÔc‰âŽJNp°w{žûéAlK²ã ¿™Fˆ\ÝŠè~[àÒ›ë÷‹ÀoÁé¶EÈ2¼|£×ïß#sWþ*Â’ ùƒ«·—Ë`ñöÃ$ˆÛ{ ² ¿Ѝô9ZÑQq@û GJóuQ8Ÿû6¦Ÿ)¿&x¤~Á-£PÀåfƒÏÊ|êf[ÔðJtIóe/MÄÊÍ–_³XrQ¢á颞3ZDŸ•¯M…8¼°?á[¾YÝ‹/eÁ†ÊcXFÅ¡|NÚîàÏÆl/¿ÕÞÌþ/ö¡þ endstream endobj 709 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Contents 710 0 R >> endobj 711 0 obj 1606 endobj 713 0 obj << /Type /Action /S /GoTo /D [706 0 R /XYZ 72.0 720.0 null] >> endobj 714 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 678.764 204.0 687.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 713 0 R /H /I >> endobj 716 0 obj << /Type /Action /S /GoTo /D [709 0 R /XYZ 72.0 720.0 null] >> endobj 717 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 666.764 240.0 675.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 716 0 R /H /I >> endobj 718 0 obj << /Length 719 0 R /Filter /FlateDecode >> stream xœÅSMOÃ0 ½çWø‡;iHsܤ†b4¡i> Lê6ÆŠÿž¤É¶vB\F{°åä=ûù)sF€îO|ÐFÀÓ„Íc@ §±¤NR.L æ J«‘ˆeæB¸ä’7¸cS†pΆ#wø è_ 7éjpÎþþÞá•u-;9S@öe½"A•q_ª!ãRøÔíÌN`xtÙÏmÒ±ö¦ß½µ½ÄÞ_÷òãØ Ö³-Q’Ä?ˆ´fpÆj¡ù†Ý5Z†š«"TF'b ¬! Ã…¸w(\τ͑ÚN´ù~“µò¬e/!íuóÀ[Û2Ò÷^é‘@ÎØ ©%«6WGQAS^Ð)³•°5ošD®Ãë¯yÍæžpë > endobj 719 0 obj 353 endobj 721 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 85.514 204.0 94.514 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 713 0 R /H /I >> endobj 723 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 73.514 240.0 82.514 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 716 0 R /H /I >> endobj 724 0 obj << /Length 725 0 R /Filter /FlateDecode >> stream xœÅXKoã6¾ûW9Éb­ò)JZÀ‹f‹,‚²vÛC,d›¶ÕÊRV’‘øßw(Q¢lÑrrI탆¿ys8ÔAþcý!E‹í臙#HRÄ|3%|D¸GÚ"C ”èU‚6<êE@lÐߣt„Ñ£ûGx¹DÏ#|Ì®OGwùú ~wù] ¡ÿ‹w‡QTzG±©Ð¬žƒ™š‘~•·™g͵&kåêçI¥°Õ »bÔ}?á­GŸf£Ÿ? D0š­lÒJ $Ø h¨Ͷèþ’`zõˆf_F׳^4ßÙk½@jÙ­= l€1&fUÁ•ƨڦ¯ÑVÕF9ÜÀDCûB¯jÀíÍt6žÌfßn>ý9»ž¢ÜBó=,@2â~ Tø}Så.O TnŠÊ2ç»R([¡•Ñ<ÙÈ$.J¯±C:ìàÄÃ!Æ~Íøó.]”q–6˜Ó.óCO %1.›îÓ2zi€¡CÁ¾G9H“Œ;ªß‘éw¬Ô–Œ­¥ÇÞ’. j”UŽ´!vÒNÔ{Pì”ñÓ¿j? V;PÙsªòÓ’¤ 3$DúÀ2‚LˆŠÓ1ê´è×ßP®Š]RžO„‡%lœ²´BOòõn«Ò²/]¢¿¢d×Ë¥¸N zÒç‚,ìG¡·÷@_dÛ@Ãz €„I×Q±ßγe9šÞÝ"õòçÞ°nõˆda(Béœ[¹fÒjq2„3]Y{Я7·§…ùĉÑFþ%ɰiÍžÐ% áN§u}Ø5@”ÍÿQ‹=oâÅ-Õ*‚‚•¡f0n–~8£õ=1o|˜nÕz Éaý;Æ`ŒÅ64›àwU,òø©[ Ç@'aÐMa¾Bc!=‚.#KjmìRµ¥ëé r¥3öLÛY]í-c[ö<ë]ЪGx„i¿ðÐaÑàv„3~kÅÇékTaCìàæs»³)Ê$Â[êm‡m²Zïe–†ô8U @Øç¸æ@4@Ý!QSAû,ÏÔ>¶ò㢯K¿ ßãBÃ}æà6X‹ÀïP+|¾·´qºhƒR·*J;z—›¨³6K“«Ã½`V€ë–nÉ»Bå•Q®ì@oRµìÄîf5X«˜®ˆoˆ™tA@dU“QKÕÕ¡.Uš•Ý »RÖôÆýØŽŒÃ ¢ë/óÞ¸«ÍíÚÝJˆBƒJ\¼ÞêÆÁVÕ*85mcSoV¯Ñ2„M‚L\XÞª%§ƒ`WÜôÙÛ b§ýÒÁˆÄHc:AÑFcÏŸ^Œ c ÜÌ‘|ýmŸÛw¹zq¦û¦ëvÐ\BŽ{lt¯€M¶WêñáÊaøõ4Ž—//ÐÅ:ÏvOµŠó¢ü®óIdiµâD?Ùö)J÷Õêm”Fk•ÝÊ¡]=ª/¯7e…ÍóXi.ó8/7Ëh¯Éå÷]ƒÀ‡+ç…£º¾÷>‡‹ZèCÛ!|sžÆK…®W+è…Š¡æKâùZ7Òt{Yª^o¸ÂÕ ®ƒ„šneR ƒí;ß Tx’ËÀûÙ+Ä 8c%¼Œ6ù¶PU«Á=<.w‘¦M2€žbÊBö&Û},=î+”qn¼­š$EÖ~‚°_@5< ª¯jÕ'€ÞVÀ(€#´û9£Ýãrÿ¤œ_64c¸ù¼‘ñáöª¸öúÿyI“ endstream endobj 722 0 obj [ 721 0 R 723 0 R ] endobj 720 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 722 0 R /Contents 724 0 R >> endobj 725 0 obj 1335 endobj 727 0 obj << /Type /Action /S /GoTo /D [720 0 R /XYZ 72.0 720.0 null] >> endobj 728 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 626.028 210.0 635.028 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 727 0 R /H /I >> endobj 730 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 614.028 240.0 623.028 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 716 0 R /H /I >> endobj 731 0 obj << /Length 732 0 R /Filter /FlateDecode >> stream xœÅSËNÃ0¼û+ö‡?âØ>¶R@p@”!TõPJ€H鋦þžuœ>Ò6â€T’îÖÙÙ™gA80|#´0žE]ã Ȥ.©xL…‚ Ô¹‚µ“ˆu†!|„É;<’)apEC<|† Ÿ„íÃUÍ}ÒÛ™ïOØÉç3x#]G..pîu»"™P–0ƸÔ`¨Ö?Ügç.ÜÓ]z>wCR×#¹ø9½´T M÷Œ®ºe¨a%ù£¢ö Ž5¤\ˆ­¤Ø–Û¥Ôôø¤ÃÛíÕ+Ô4lµ¶ÕʯìÀE?{#©£«Æ_Ά¦ÊY]k ’Ò¯q6/óÙt„Ðy¹ù|dÙJl@Z¼÷xñ¹©!ngÓŒ®;ÚG'š*챚×}ý,ƒN±œmvº•„cŒ¤qUI²ûLØÁOWäË2•åGþ¼*³åQ«ت¿Gå÷¼þÛÊ¥@çc±1ë…mè_1ÚM•ÔÖÆÒ츚Ù#?é2Û endstream endobj 729 0 obj [ 728 0 R 730 0 R ] endobj 726 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 729 0 R /Contents 731 0 R >> endobj 732 0 obj 386 endobj 734 0 obj << /Length 735 0 R /Filter /FlateDecode >> stream xœÅQÁNÃ0 ½û+|„Âã4MrdÒ@C©4ˆÃ´ 8¬CHü>I¶fÐki~²ól?¿=H¤ðÏb0Žñ©ƒ}ÎI4ŒªÎ)]£¬kì0cÛøjø…ð†°ÂkX­Cñ)¾€NÛõäšÁüX¡Éç¾ÂÜÃÅ•FIè_Ž'RZ0WÎÙÊ Š]ü}‡«³Ûeëg—Þß/ç~Ñž¯ÑßÀÂz”äÐÓ;O qâtÏV)2©Q,m³ 9¦® ¦åR]ŠŽ;Ñp¥ÒäI‡ûk"Q’°…³’Ô¨›_í—‘qöABŒµD$ Y½¹&‹JšîÞ?7IÕw¨,*'¨®C'{`ì6bp‡¾½°Û endstream endobj 733 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Contents 734 0 R >> endobj 735 0 obj 280 endobj 737 0 obj << /Length 738 0 R /Filter /FlateDecode >> stream xœÅSÁnÂ0 ½ç+|Ü'!I{ܪ2iBH8 ¨Ë6$ZÄÊ´}þ’&Œ–®W–lÙy¶Ÿ_s Ð~#gtÌ¡(É!ÄhB…TÀ&”K(!øvîVËá'ÏÉ:ï°$Ax «µM¾ZÀÁËr xA²V—Á«÷Gx#÷9O%0„üõ¼"TGhŠ!¢‚ÇîpÈKXÝ$Oé]žŽiöœÎ“ôv ù#IóÁø?ðÉ:3XM5×ôBé-|ÌF|!—Ú‚õU½ë‡óvp(<τ푺"_µù°¾ÚÒ¨£,C9¨æ•·ÖÒõþå#€YaÝÊ:´qu å9Í÷GS{Vãi|¹‡I"¦¨”­Dña6G3ªÍáÓT…9a{;dâ0lkØÀ £z©¨bÍÃb}p2[d³á~‘ÃZbÒÊÑol¾¦ª·ûж4ÌÈÁþÎ endstream endobj 736 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Contents 737 0 R >> endobj 738 0 obj 342 endobj 741 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 73.504 210.0 82.504 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 740 0 R /H /I >> endobj 743 0 obj << /Length 744 0 R /Filter /FlateDecode >> stream xœÅXÝsã4Ï_±OÐÞ¡OÛº˜)\¹›£Pà¡íƒ›(M ±SÛ¡íÏÊòGj+N:Ì”äÁ’­Ýý鷫ݵF (þÇöjÓõè¡ºÇ ä ‚ê– €I¬¡+XÙU;^ðâá`Ž’…ŸF×·øpG´«®¾]îØ·Oè›ÛßE ÿ_\¾ôBÈCÒñM)-Ü=¼ãÙG«Š¶êê´º¡ç®{AÑõ“RÁ};ãîG?LFß~TÀ(LæmІVQqm&k¸>a48½…ÉçÑù¤çÍ7f­çHk»Ù†Ž(¥ìŶJç†Õ¦Üž.âµq›òÐ #àšÐ@Ùõ‘øðÛ/¿Ž¯Î/?¿øñœh#À'!·v9ï‹Þpvä|ÈÒ Ä0‹‹ø.Î äæak’©!5äÐY2B5E-Óòq›L‹ešÔ2ûÙ 4Q,Ò:d;WÏI?Õ‚Úc c‚0‰ÊxPE ”¿Î>#éY9ÃÝë-u‰ÁEÝ5ÒÁ˜dǽ=øL{m|õ·y0ĹÏÐr>ž¥&'i16O˼ØkUúº ,òª˜ØoÇË9|÷=&$‰¢@k!™“;Ëî·k“9ÄÉ þˆW[“ï‡lCi"#Œf.Eß½£Æê™, X1HçP,Úø‡q@^dËäþÈŸ×wé Ò ®.¿€yÚd&Ï1àÉ0Àˆ‘ˆâÙcZù)õƒì‰µç3½ûËL x\,§ ˜™y¼]!cE ïªÉ¸^ún§’0âæ‡Ì‹²/VÑDàg'ÈÛ|»‚J?Bœx¿¼OR¼"‹ïM–áåæÄR^¿9%‡Ã†cú{6L>Í–›ÝôãͲ*ìxÞf¾Nñ9ƒG5l" šOãÕÊÌêÙ@zPŠ1ËÈgn86C=$[Ÿgéú0ëŽ9V ®=ÊÆ W|H¾àB°š4‘Xó™Ö#O\Ö>Íèïdkë {xm¸Z9‰5N0nÛIÀíÔ¦”f2àCŽÔY?،طwü á< Üv*E-–åÎêÒÜ@Z’c`s­‹@k”û¬yª ²¢!%-ŽÌÛ,ÉûÀúÕ›2¢©Än#ô¹ïâÓ—ýG–é!ÑÖøãÂd&Îw]í L©/¸„ìçHº;áËùPñG‡ f;§@{Ô½&2""l? îQd!¹ìxD6̶¬Ê¥Rüü)^oVmáô5TB˜C¥-ÙUvÓœ:>oàzž¦·7§}.…Š:âXð'žuØâwͼˆDgËB—»ºRx­G¼oݳLËÿ²GI»¡ WoïY¶Ä]VvW9QÊ` Õ‘ÂvÊõÄË™óù }>TÓdˆ‰š3É(hJpM.Æ‘e{ƒíÊÆ@_+ì‹O_ÛáJÁ˜_òˆØÅ¨%Ú¾D„¢nË#Þ»ç¡]+®ˆÒ–èÚZ¿Äa^áë¤U…º>:SS¶1¾.‹mlǃü«0"Z¡ö0ª·`Ó5F‚-@e‚©gešwÃ6á4çÍpÀK’f»Bå±{ ñ•û%}]!uã¸Å]õÂÍÜõÄõtg³¶Gnhh{åæÞ^–Ò–ˆâycZS«Æ·8÷z²³±"¿:Ç <õ-ÚŒ{4z»’›á’¯ p ®lGö—slrà¥óè:¾Öa=5T åµ(_rÊݾÿ]w,Î!&ºH‡ÕÊ•1p¶ÊÓæëMûñ½EìÇ‚éÚ}=éU% ¶(î~ šbQ/L§k)¿ Ùÿ¿ÄÉÐû endstream endobj 742 0 obj [ 741 0 R ] endobj 739 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 742 0 R /Contents 743 0 R >> endobj 744 0 obj 1356 endobj 746 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 109.484 210.0 118.484 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 740 0 R /H /I >> endobj 748 0 obj << /Type /Action /S /GoTo /D [739 0 R /XYZ 72.0 720.0 null] >> endobj 749 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 97.484 198.0 106.484 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 748 0 R /H /I >> endobj 751 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 85.484 204.0 94.484 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 750 0 R /H /I >> endobj 753 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 73.484 198.0 82.484 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 752 0 R /H /I >> endobj 754 0 obj << /Length 755 0 R /Filter /FlateDecode >> stream xœÅXKoã6¾ûWÌ©Ø,Ö,_¥-m½Å‹ Ýä ÛtâV–KF’ß¡D‰²EËñ%µ")~óžáPO#ÿcóP1‡Åfôd×("´KALÀì8€Ôìê x3ÂG½ ð×(Qøuts‡/—@ð<¢‡ä*ðttÝáoÞÐwçß•@0þ¿Hp½ïÅ9ðM…õ®Ô„̫ԚÍ>kªõ°®~Š:™¨ß(VÜ÷cNá~ôy6úþKŒÂlå‚V £$â±ùq˜màæcôâf¿&³ž7ßÙj=GÞ­>:6¢”²=µ*ç*«T­ÓU²ÑµR3ÈxLh˜ýQ ˜N®ÿ˜\ý<Oþþ:MÇ¿C oALF$†w$úð[ÎÕ! ÀLe«| åƒý².J-4ä+H`™”É<)4úig–I£Œò(#¡1EÚaMûË.[”ë$ncž¥ŽJçn¯1ÔÒÇpWè­Û–lu;Ö/Éf(ç ¯«7øJŠ‹ ;‰‡þ¹«:ÄøRùh,c¢P@7¬O7_ê,/÷V:›šnf’õ“›ZÛ5t;Æk6XëÙé¼³{ KcŠí!6y1å­† !ø ¸£cå1;éºÌ.U>;)«ˆ9Áª€*<_VÉÁŽבæ˜u3¬îY¿bÆhóѽUùôI%DL$Ç›dAMn‚àÇÔµZ¾¾[`ñ‘HŽÑæŽsÛï¨áf•çw·0öáØ(bÍðöïÜGtw)ˆ %:B0ÛÐL×K “Õ {‹b(é$n¡’”1nñ«<Óo°©Ä*R ¾éd+f˜-ó×!†XIG¨$·¾è7:§¹‚c–ÈXQÕ8t¡«Æ#Á›íºÜ%f<¨y„xFpJc¥yáïpa¬¬É¦ZÃeZäí¥ÞÝ©‘žþ„²ê;Uu©îÅ…ˆˆ½‹­NJ=n¢Íû±ÀPfü\ÊËmþxš.—çÒM1ZºÅQÂ"<—p›qiR”ºæÿQï„U endstream endobj 747 0 obj [ 746 0 R 749 0 R 751 0 R 753 0 R ] endobj 745 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 747 0 R /Contents 754 0 R >> endobj 755 0 obj 1292 endobj 757 0 obj << /Length 758 0 R /Filter /FlateDecode >> stream xœÅQMoƒ0 ½çWø¸šÚ $pÜ*:iB•L;T=TÛ*µT¶Ÿ¿„„•qíà`Ëγßó;34ÿÌ ØÙÙ×´©|)T@!Áç!ì«N"ÚÌ÷È$ŸðÊ*†ðÄÖÓ|4€o†Ãq 8gYg¿íàÍ÷#|°Ç‚Í—!Bñ~=‘Ô\‹ Ž£@CÄ¥ˆí' 8Âú.O²—dµHféC^Üo xfIÑS#Iüƒš¬ÇÁ8ª…柴t5Sqƒlëà-ðÑMu©#çâ$)¼rÂ.¥¾Å7]>í®¶@Bõ|%’“nÞøj##íî?=È!"õd5æj/ÊiZ.eíTÍ—ñðA2樔™yD]ž¿ÊjWÎÛúÒ"G$¡ÆPØ×°…£F˜ àŠ kT4/Ò> endobj 758 0 obj 340 endobj 760 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 73.49 210.0 82.49 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 740 0 R /H /I >> endobj 762 0 obj << /Length 763 0 R /Filter /FlateDecode >> stream xœÅWIoã6¾ûWðTL5Ë}9´@ÚzŠm€ n§@fŠM'je)‘äNòïûhm¶DÓA© C¤ÌoùÞB>Í("ðû‡¶ ­¶³§öEš!®ÚWR!*0“h‹Ú±D™_u0`ÝÍ"< ³|FÐO³ÛÏðç|™‘ñv{ðÍìú@¾ÿ‡¼¹üC 8eÿ‹×Ç,h¦ñˆ›=š7ïàM³‘ÿ+kÝÖ>›]›a£\ó<©t"a§´ê¾p‚îgß/gß|ˆ´Ü A«=l˜õ†–[tûŽRqñ-™-–6ߨk"½ìÞŽ(k!ôȬ=¹º5ª±é*ٺƨ€„AÌb¢¤_oÀÍâú÷ÅÕ‹ùÕâÏ%j =€r†5¹JÓ)ôcz 1ú9_•nëòÕý“d;‡Š JÐ:©“»¤r¨rO;—¯îŒÐ#ÅÄØW5û~Øå«:-òsÚ_ÊbIµš¶þºyÉëä¹Ú€0J¶0Jvfì?#ˬ쬙çî¹»J±ÐÞ* ÈHªBÊä„OÔ§6(ã«¿ÝKDc!AE'…1­B¾ý•®Úeõyv|¸‰#ôey¿óñR¡$_£?|ÀT§÷lI‰µ:d8e%*YBpz˜M¨(=PU—i~ÿ5ª^¶wE†ŠÝ\ÿŠÜó#˜YA⸂Za# +8adž•œÀ.‡¤)îþr«}yHWhí6 x»BuÞ·“y·ôý嬯–qB•”cêªM@—9JóÚÝ»Ÿ'1‰…8³¼ÿèªU™>ft°” ƒ  —­K†òr4ǽóQÓKWïʼŸzb»qS‰º°ZÔGA÷b•d™ö$”ÔXi0ÞP;¡Ìж—žæ¯QÄ2l µV¨Ðfg#‘ Ã÷4‘ØÍúˆì½ZôãJ¤'YAצÌÃÚ’pÆ‘¸2sHMÚ6±xN¶ÙP@BÕž3Ž5£(4°¦Ë U²µ…H϶Ê›½ã™‡»ùŒôp…­ö®a,>›éL‹þù'¬Á¶Fš®cíÝóî%Fd 8ÔjzØW»²ô•½a ª‹6LNŽ1§p8Õs¯«á1q6$”8i%u‹§á+á,,ýñWËÖkÓv|Þ|µŸ0eú2¶rûæ˜Àí!­w‰GƒZZ-vÏe›Ó,ó5˜a-½÷{uÓ$,áxÓÍš¾¸Ö/nÀ?e½EM?Æ¥.@Ýtÿbè¦ûéi9„¶‘’P¸L‹²È%‰a{éëÂUý$/êÁ#Ïi5ÌÒüú  ÖK$š„¨8›ŠBÉþ©¨´m ±K„nË¡sè2«Šþþ;\?!^W6+èþú9é“5¹0\¥áÜ•ÔnÞ‘zp­ößÞ$%l endstream endobj 761 0 obj [ 760 0 R ] endobj 759 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 761 0 R /Contents 762 0 R >> endobj 763 0 obj 1193 endobj 750 0 obj << /Type /Action /S /GoTo /D [764 0 R /XYZ 72.0 720.0 null] >> endobj 765 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 121.504 210.0 130.504 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 740 0 R /H /I >> endobj 767 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 109.504 198.0 118.504 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 748 0 R /H /I >> endobj 768 0 obj << /Type /Action /S /GoTo /D [745 0 R /XYZ 72.0 720.0 null] >> endobj 769 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 97.504 222.0 106.504 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 768 0 R /H /I >> endobj 770 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 85.504 198.0 94.504 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 752 0 R /H /I >> endobj 771 0 obj << /Type /Action /S /GoTo /D [759 0 R /XYZ 72.0 720.0 null] >> endobj 772 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 73.504 198.0 82.504 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 771 0 R /H /I >> endobj 773 0 obj << /Length 774 0 R /Filter /FlateDecode >> stream xœÅWKoã6¾ûW{(’ÅšåCÉ-à¶Þ"‹E€Ôn{XïA¶éÄ­,%’Œ$ÿ¾C‰zX¢äz©}ÐðñÍ›ÃáÓ„"ÿ©ùÅÐæ0y²s †x`§üQ3¥}™]-‚U|ÊM@< ¿&ñ„ ß&_¾Ââß,–ÓÅüîùí/ó*±5‚r†3‚ëcWŒ‰.À ßu~Lã …(Úg9Jvhæá:Ì4ÊôÓQÇáJáÐߣ˜(ƒ’ãÇc¼É÷I\a†](ìS©” ÖU‹×8_* r£$ÀÔf,°)ƒŠ_Çfé9vû¦µM]/Næßý£_Q¥¨Óш— ä9Öé Œ»0cB<âTQ–#ýøJuvŒòóñ¡ÜÃRJq–èYz<è8‡t‰·èÏ0:VŽt)nâå+ìIH8æq‡szçv`f(ËÓ}|ÿ ZK=n Jz{óyXX@”¤è‡0Šð¸i’bIà`Qå»Câ¶®›5'.Yÿ­79z~ØoÐVïBˆS†ò½·ƒiµõý¸r˜˜R‡’ÙÀŸÝ©Z4«‹B€¦ g ƒuš5¿êl“îÛEÁY}Ñ DU›®÷¡ø_…5U¨U @½Š´jÖãT?‚á±0Ûl²5 žˆ¡D7˜}\“#‡Ò/J¡îõ5?› Ü7‚¯5(S¡Õ)QM@jTäÅ)\v4… b¤K,ÁiYMžQ Ë ®F!<«Ñ“ ulZ‹^¿Ö¤õF=®YŒ:Œó‡°Ù˜ÄQÃ¥¾.šepÒÖ%ð˜é´Ù¦º¦M²ê-®Ç7»ž¯úâJ`!$¡>u™<+‚]Q ›‹3Ô¹MÂ@åêd¹Ž{²¦ÐÐ%K4#sÄ>4Cëd;j{¹Ú`Ýl‡ëÖî±›Òd%$ð„CÝqŸ1aÀÐÈPFà–Ehí ‰­(‚{VSW«ð«ã¡¦<7ò÷-‡š ­å:nYÔ^êŠV•wd_Xœ¿8cÐaû„xÒvŸó—ðð5=„«åã>ÄEz¦‡±mâªÓÊ­®ûªr0æÏêêÝ.IÞ­®{ £AHÖA´[Ë1»> endobj 774 0 obj 1196 endobj 776 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 85.484 210.0 94.484 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 740 0 R /H /I >> endobj 778 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 73.484 198.0 82.484 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 748 0 R /H /I >> endobj 779 0 obj << /Length 780 0 R /Filter /FlateDecode >> stream xœÅXKsÛ6¾ëWì©Ód,o‡vÆm•N:­SÔæ`û@KÍ–"e‘jìߟ QÊŵH|ûü° øi€âoê&ä°ÜLžêw ¡ëWJ“„+Ø@=V¸U¯¼á£Z„ƒGø%uØêg%µVÆUÏ£FÑÎ&êJmîÛ)§ð0ùq1ùîƒFa±îHkQðÐýqXlàæ[Æô»;Xü:™-Ù|㨠ét·þ`˜Ø€RÊÜ*“kj§*Ÿ®¢­œò„AÀCBµrëƒ 0Ÿ-¦óÙõŸ³«ŸfÓ?>Í?.>~º‚JD d†ÃP¿6l(â–sÓc˜Û"‡âÑÂ6Ëã"ÎRÈÖÁ**¢û(·Û§½M—–4®+’R”ª+©öéÒÉj0Ç£¦C¢X††ÕQ›¿¤EôÜC2FQвö¡üë¹ÈáÂÜÓÆŸiãoÇQáPCcOùñÀ Îôp}ú*õ¸üJ Ò£áÐzŸ–Ðøæû2¢Ji ŽªÆ—”ï€Í÷IqšLb$îÍëzp¹{ØolŠÔŒÒü%{›7Û‘Bb Ê–Ü s0Ø~ŒjdÛÀÁÜp[¢á DhäÅ.N. ÙÜg d;˜_ÿöy‹næ˜ 2n qL—”eü)ô9€]¦§…}°»q…œ2,k& •fþDza—]1Èîÿ¶Ë¾<ÆËGXÙu„éÅê‘Áûz2m–¾?ay€e¨Þö‡Tñ[ÖÇx"qœc\1‚XJüg›/wñv4ÎT£çš2Áêš9{Þ&ñ2.ÜJ0•Š+-ÝÄq§´uµ}ƒìò/mùÖ¾YFIbWÝ|¬J„ªbóÐæÑÝÀ C¬ÄÀRæÁvêãô,SE4J †úÂw’†ËÁþ¢³¡"b;mÙ…7ëÆöʾKt`zšJ"_8~w6ЄbÔ© Ê#áôr _oµ8ÇZZìw©]AuÁ‘\ ˜jm¶IWB}mUà‘(ŽÑæsÛršDy7ë,»»}7ŒœÐ¢Åâ/=ë0—Cžž\©E½Ú0JmŠz†áqRû<â‘dý`8̳÷]}Ë’Äxk‰ýG°º²Ïã•…Ùz%6«H褌ñº”ýž­âul«ƒÜ¿®[ZØq³beD ¹”Ùã•O½#Xpãxàš„®3lûCðÉ:Áß±S$p‡ãöÜQF+îýËXwÅ6À¬óz‡ àÚÖ,»†šf›.mÙ"¼ŒÄÅ>rãQ*¨sÇ9¥!¯+Æç8I°æá-AcC‰œ¬f¥íÐîvx€ifeGª†ÅËÖvø§¤u¨*›‡¸¸ÃE¨ëbÕ‹¶‰UÓ‘ã'"PªÚLC×F™(öÚW™ÍÛIš]Džã¼›ÅéöJ̬ÓX6ª¡Î“–ZáÏ °¦ÁfêÐÔ¬Ÿ[ —Ižµ×éî6‹|ÑÛ +ÿCT^g€ <¸š/w6*l[£½×t'Y试¼Úe[Ÿ\÷ûÇöJ endstream endobj 777 0 obj [ 776 0 R 778 0 R ] endobj 775 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 777 0 R /Contents 779 0 R >> endobj 780 0 obj 1236 endobj 740 0 obj << /Type /Action /S /GoTo /D [781 0 R /XYZ 72.0 720.0 null] >> endobj 782 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 133.5 198.0 142.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 748 0 R /H /I >> endobj 784 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 121.5 204.0 130.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 750 0 R /H /I >> endobj 785 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 109.5 222.0 118.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 768 0 R /H /I >> endobj 786 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 97.5 198.0 106.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 752 0 R /H /I >> endobj 787 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 85.5 198.0 94.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 771 0 R /H /I >> endobj 788 0 obj << /Type /Action /S /GoTo /D [775 0 R /XYZ 72.0 720.0 null] >> endobj 789 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 73.5 246.0 82.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 788 0 R /H /I >> endobj 790 0 obj << /Length 791 0 R /Filter /FlateDecode >> stream xœÅWËnã6Ýë+Ô,Ÿ¢´h7õ(ŠR»í"“…bÓ‰ZYr$cÿý\êiëådP¤öB”Èsß÷|vPüÏìCûÖ;ç¹úÆ@snõI¹À$á vPDvÕÙ€×#|”‹pð;±CáWçî'7@ðÅ¡]qxéÜžé·3ôÍõŸ[ ÿ_,¸½Ì‚æštrS Eù ¿”‚ìTT…­z–RËai\ù5ж6Ñá Tæ¾r ÎÏ+ç‡ …Õ¶-ZmŒûöÇaµƒ»wŒÊ÷÷°úÍY¬zÙ|ã¨õiu7þ`˜XRÊ.Ü*’«+§JŸ>;S:5é÷ u•]ï•€›?óÕb¶\Üþ¹øt³€Ü@˜”Ä—¨™KÙæ\wj 7© rl‚˜xmHm¶0[2B}ŠrÜRÎÇC¼ÎÃ$®1ãr}¢˜çûšUZžâ<8Ö@@£.A’³…¢+³‹_ÇSO¬\þÍj§ºÁÑC¨AS:Ö0â³$÷àtPÇwÿšÓ„".‡ÕIWæ †ëÇŸàzf˜p Ó'|Uâæéãagâ<ƒ ÞÀ_At0Ù¸É6S.#’3JWýÐôê-€¬ž X$[ÈŸÚ‚„í€,OÃøñ{ÈN»‡$‚$…åíï`ŽûÔdV ™6ÐCñ8¥B{Ã!6²›· “<ücÖ9|y ×O°1ÛàaÄò>T/³zér= œ Ìž{_L¶NÃýy{ 2‰Àæ˜uÁ«Î*{»ZÂuEf3UàŠ«ºš ˆœN§v§°Æ“åmyJI|5M\è)ü–×#RIÊŠ)+yq vû¨mŒ!T< ]z¢bê.3ÁÝ6Iî?¿ï0”£-—à¦/–!¹wuÔÂgæfy6ÛOhAJïiY R­]¯DgýùÊ© OÆfGU!\†‹íÛ(›*qI="”ò=­j†jK;Ì  éæJ¡IM\¿Úû¯ó¯¦ð/¨!iKÕÅ=دkh^øŽ–?œ&ýw¡ ‹\«ŠÙû5üõ>GÆÅŸŠº„צà—Ï?a~ìx2 …c—ã6N+Kæslb¢áIS¤åú óR³ð1®¨žÜ6éŒQÂ(²¯Ð;ÍH®GY'y3Z»«=§y/÷žúõÌY»5ah÷¤æÛh”’6ùioZUÏQ“[Ìú¨°ï/˃Y)kCŽ¡ 5Q‘Üë§‚ðšOû:&ÃÎí½g A„º9AÉJ/èì0B=<¸zJV”a Ì£,i. íyÝÆD÷ßâ°Þãc سMšì;GÄÎÄÊÄ£Õ+dFèZ#3Š»åk„öø|T.ãß$7 ²|T&—ß$36Çq™âU‰ÊLÓÙ>ÉÂöPTȶÿ¯ÔéT endstream endobj 783 0 obj [ 782 0 R 784 0 R 785 0 R 786 0 R 787 0 R 789 0 R ] endobj 781 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 783 0 R /Contents 790 0 R >> endobj 791 0 obj 1090 endobj 793 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 709.5 204.0 718.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 750 0 R /H /I >> endobj 795 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 697.5 222.0 706.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 768 0 R /H /I >> endobj 796 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 685.5 198.0 694.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 752 0 R /H /I >> endobj 797 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 673.5 198.0 682.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 771 0 R /H /I >> endobj 798 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 661.5 246.0 670.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 788 0 R /H /I >> endobj 799 0 obj << /Length 800 0 R /Filter /FlateDecode >> stream xœÅTMo‚@½ï¯˜c{`;»À.\ki“ÆØRiz0ŒÒ–DQ‹Mýùí‚‚ÈAHf2»ïÍÇÛeÍ ½Ž1:”0]°u %¸ª ù „Ç¥ (}æfWÍ‘•GÆn"çÞXÎØhL‹3@ü0<¤ûY\ËoVðâù>ØmÂnî}Éû~D®âAÒã†pW—f–,`tu÷òôì £ø5ô¢ë1$,JݸBþC7q£RTKÍtþC»6FKd–楥µ¬ÖµÅYÛYîkÂzIM‰/š¼[]m€yÐÐU îTóÂSk ÙTÑ ìñÚuvˆ­S;ÏŠS¤ëï4Ÿ¦ÅÑF‰VÈSy+J'ÝR†ÂYuQKïlêù¤ØtÑÚßÖY´yºí¤¥ïdÚý|Õ²È6Ù2¯Ñï¸\t/D‡”׿LjáZÎÁrSiu¤£†•"ª ´Ù×rµ«£‚¶n€ê²&PT äy\ ª•8‚îõ‡q¿;£6`—o®S;5i‘æŒ×f³_ܸny endstream endobj 794 0 obj [ 793 0 R 795 0 R 796 0 R 797 0 R 798 0 R ] endobj 792 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 794 0 R /Contents 799 0 R >> endobj 800 0 obj 412 endobj 802 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 709.5 246.0 718.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 788 0 R /H /I >> endobj 804 0 obj << /Length 805 0 R /Filter /FlateDecode >> stream xœÅSMOÃ0 ½çWø‡'YÒôÊThšTµˆÃ´*mS‹àçã,ÝÖõºµ‡Xvßó³_ºcÞÀa$aµa»&' ” L“ÒÄ„K hb k÷U+‡ˆÿ_ðÊJ†ðÈK*¾à—aŸnNYÒêï*xñþŸì>cwBöqZ‘2ÜÚˆåJºv–m`q3{J³ “—x>ÓÛ%dÏ,Î:ã(!¯0NÒÑ@–†2ä=£÷hås”ñD®´n> endobj 805 0 obj 364 endobj 807 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 709.5 198.0 718.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 771 0 R /H /I >> endobj 809 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 697.5 246.0 706.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 788 0 R /H /I >> endobj 810 0 obj << /Length 811 0 R /Filter /FlateDecode >> stream xœÅRMOÃ0 ½çWø‡'iÓäÊThš¨ZÒ´*mݦ±Ÿ»t[?¶—Ñl9yÏÏ~Ù0H¿W‡ÐJ˜/Ù¦© %(Ý” Âç2€%4y‹úV+‘ûŒ‚»Dɼ°‚!ܳéŒß ððO·',nõ¯Oðâý>ÙmÊnîéÇqEÒp£|k-0\I[Ò%L¯’(~Ž&£È‹^’4ñž®g>²(íL¤„ü‡‰âŽr5”!ïy½C+W£Š#ª Mt¬.uâ\<+ š°-©kóE›Ÿw8¬¹éx+„8ëæ…·60²ë¢oÜó:Lhûâàå–Ùæ;+æ™WdÛêäœÄ*äßi+ï@½^•y•¯ŠýK ×hQô(}ÃC£èÀŽs²ª²ÒqœÐ@2CÅQkb2¶7\¶Í˪ôÖ{ôÀzày o°ÇèF® D-†àÑ8‰ÇçûÙKû h·ÃÆäEV”´2ÞÚYÌ~«42E endstream endobj 808 0 obj [ 807 0 R 809 0 R ] endobj 806 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 808 0 R /Contents 810 0 R >> endobj 811 0 obj 383 endobj 752 0 obj << /Type /Action /S /GoTo /D [812 0 R /XYZ 72.0 720.0 null] >> endobj 813 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 133.484 210.0 142.484 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 740 0 R /H /I >> endobj 815 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 121.484 198.0 130.484 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 748 0 R /H /I >> endobj 816 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 109.484 204.0 118.484 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 750 0 R /H /I >> endobj 817 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 97.484 222.0 106.484 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 768 0 R /H /I >> endobj 818 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 85.484 198.0 94.484 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 771 0 R /H /I >> endobj 819 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 73.484 246.0 82.484 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 788 0 R /H /I >> endobj 820 0 obj << /Length 821 0 R /Filter /FlateDecode >> stream xœÅWËnã6Ýû+ j–‘-ඞŠ@j·³H²Pd:Q+KŽ$Ï8ßK=mK–“.R{!’â¹ï{H=OPüOÝCáfò\¯1Єª—¤æ.aõXBìv x3ÂGµ Oðe’L(ü6¹½Ç—+ ø6¡§âJðbrs ß½¡ï®ÿÐÁøÿbÁÍq4×ä$7%ZTk¸R r¯â:lõ³’Z +ãªçY£hgJmîû)§ð8ùy9ùá“Fa¹îŠV; £ÄçÆý8,7pû1~uËß'óe/›ïµ^"îÖ ëSJÙ‘[eruíTåÓu°±•Sað|à†P%Ý~¿,æ7ί™O?ÏK¨ -€ F¨D½‚Ê>ôŽs} ðÆð‡-vYÅ“…8È °±Ýؤ€(VA<¹…Ü>ïlZÒ8¢qŠ EÙª’ýi—„E”& æ|Ì”!’ùÆhVÇlñ’Á¾šeŒJ"5º¢¼Ú“òwâ¼ïõ76¾L¿§ÁR|@rcZqbS–$ ï™Î̆ïþ±/#j8PÓ$ç¬*®Õ€ª‚Ìæ»¸¸œ&ÑÖ²âuβÇ+‚dñÎæçÍvi’šh²=®ûÑéµ£j²Äât0H×e¡6„퀼Ȣäñ{È_6i i‹›Ï`÷[t3Çò#ãjW{¥Zêá¸كͺnIþ¶aßž¢ð Vv`´s(RøXO¦ÍÖãÆqÊ’´1R±JËqêMëƒf ¶samF.'#Gx ƒù¢‚ÿjó0‹¶‡­<ÈcRÏgÆxªÖÜrÒ\êšqÉ5Íä««£vÄq…]µ+ѰŒ¶ š…¡°‘~’ŠhƒÞ{LØ=Z¢´1ìÑ#†N„qíIÍ€°‹¥(<:†o-¨J±™µ%ÙF5m‡G%:=¡G—e%O”×ñHaA”ö/ëóa¾6Û¸#!šXZ ƒÜ«ÕÝ8Ü®Óôþîªo©ÀóèŠÔÇ ·Ãw¼ÿpç˜gÂgÄàùÊêó+ZY˜¯×HùXÏxHÏÆ]¸ªäë4±¯¦'<¸¦xº×Ñœ•Ú°ü^F5JŸ0)Œaäî²ÌúU#æEš¡,àÞù?vF¡EBЊ7zZÆ[ wc¢¯L{PÒO•‡ì‹…DÅ [¹©Ï¬—c(©ÇtÍñ6߇¶ä¹oQ± Üx4Rp̧Ôð:_¢8ÆnÒœ(¤¨èÑÉj¦AÒm–áIÕÌð`k†ÅËÖvøç¸õ¨êÈc\Ôá‚ÔñbµÐòb5=ŸCÁñ‘ûÞâ\M¢t Ûj_¥6o'IZtÙGy7‹’WØëajFªéP*.Ò§‡d6‚EJ…ŒWWetM kaçiûÓ}F¸zÑŠPV~š—ß=ΣPõB÷MfOÃi“ÕÁï#'Ù÷ß*y•¥Û‹r¥o•c"[¹ùYÁŒ¿UpËüe­äÓíYÙÜûϲ»/ÎÊoN_n»XL·iu÷¨R¾ûÿ Tì I endstream endobj 814 0 obj [ 813 0 R 815 0 R 816 0 R 817 0 R 818 0 R 819 0 R ] endobj 812 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 814 0 R /Contents 820 0 R >> endobj 821 0 obj 1183 endobj 823 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 709.5 198.0 718.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 748 0 R /H /I >> endobj 825 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 697.5 204.0 706.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 750 0 R /H /I >> endobj 826 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 685.5 222.0 694.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 768 0 R /H /I >> endobj 827 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 673.5 198.0 682.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 752 0 R /H /I >> endobj 828 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 661.5 246.0 670.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 788 0 R /H /I >> endobj 829 0 obj << /Length 830 0 R /Filter /FlateDecode >> stream xœÅ”]o‚0†ïû+ÎåvAwZ Àí [²"Ë–/Œc ¢–ùówjAù¼pNLÚ´¼Ïùx[öLÒcéÁ $¬7l_­ ð$تZr‡K6PÍ]Èô[‰¬g4˜—hò /,gl±¤Í7@ü0ìâŽâ9‹ñõ^=>»Ù݃ !~?·ÈVÜ\DtøÜ–þIˆ7°¸™‡Ñs8›„Ö,|o—?±0nUc ùÕD­ÈQOz¼ãóQm›5Z1 ½•UT£¡š©IÎŒ£Iá9'l¦Ô¶øªÁÇÝõ´P ÷[¾ Ꮊyå®õŒl»èøæx* ºbïÔ¾}mwV‘ì¿“| ÖIT!/ÅfiQž°ÅW:—rk¤•(BaíÆÐæ³õ't¶*Ê1,ý/Æžaí¶EZ¦Û¼?±lt/}ú¸ˆ.Òáž>“ž° s¶-ë¦ä  À£R„òƒNuyr(kiï©´°‚Z¤z"ÇáJPިĀz2GÓñˆžS»\}ú¡)Û$/¨e¼Ñ³ˆý ênb endstream endobj 824 0 obj [ 823 0 R 825 0 R 826 0 R 827 0 R 828 0 R ] endobj 822 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 824 0 R /Contents 829 0 R >> endobj 830 0 obj 414 endobj 832 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 709.5 204.0 718.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 750 0 R /H /I >> endobj 834 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 697.5 222.0 706.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 768 0 R /H /I >> endobj 835 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 685.5 198.0 694.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 752 0 R /H /I >> endobj 836 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 673.5 198.0 682.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 771 0 R /H /I >> endobj 837 0 obj << /Length 838 0 R /Filter /FlateDecode >> stream xœÅ”=oƒ0†wÿŠÛ×6`ÃÚˆV©¢¤ªQ†*¥-!‰œªùù=Çð†fHaðéÌ=÷ño †¯c X®È¶òqP\Y¹| ܣ‡T¶…ùªaˆÚÂÅ~„Ƽ’’0x$ón¾Àº¸CpBâF~³Ã®žŸÁ'¹OÉ݃œAúq—4}Ƙ'! ®Í# ]Áü&‰R'‰â—h:ŠœçY2NdzéíÒ'¥­®\.þ¡«¸U*«„¢½Ñ®õ¡Ç‚ÌVQIQ­–jM[œ]‹b§šX³¤¶ÔWM>¬²2œÑ ¥/çjPÍ+O­'d[E/°ÇëØaØíõNo‘룳íwV.3}¶QÄrñWnt²=fÐÎf-¼‹ÑÅ›Þ aíõu¶ÌöMì‘áÇ'À[€wPJPeâ®eM×»z˜grcy¡¢LJ$aý$ƒ³Yë|—¯ËšÐ¿”×G@®á êÙ‹ •«g’÷ƒG“$ž æÂÄâ¬|< ýÄ8°¬ÔX0mÌ-&¿îr[ÿ endstream endobj 833 0 obj [ 832 0 R 834 0 R 835 0 R 836 0 R ] endobj 831 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 833 0 R /Contents 837 0 R >> endobj 838 0 obj 408 endobj 840 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 678.764 180.0 687.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 587 0 R /H /I >> endobj 842 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 666.764 174.0 675.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 632 0 R /H /I >> endobj 843 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 654.764 180.0 663.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 675 0 R /H /I >> endobj 844 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 642.764 198.0 651.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 748 0 R /H /I >> endobj 845 0 obj << /Length 846 0 R /Filter /FlateDecode >> stream xœÅS=OÃ0Ýý+n„¡æÎ‰x ¥ !„TÄ€Bk R›Ò&|ü|ì:¥IÓ©CIŸÎ~ïîݳ—ŒíßsK¤ŒçlYå"ªRR…\H˜CK˜¹Sµ@l"»øC6xƒ–3„+öød7'€ðÅp—n ±a­¾ÛÁ£×Gxeç);»”@éËvD"àˆ¡ÖšÄ<Ú}Ò9<ž¤w÷·ý$ô.’49OFƒÓ'H¯Ù m( Hüƒ¢a£ëj$"¾ãõøœÍx"·5«l¨VÏêCßœ_;›ÂmOXo©ióQ‹w;9 !ÞéN7<µ–‘®ö¯žÈ#"5d­Í*Q^ÓÈHfÅâWØ–7Œ!@ù§¿æÕ»sÂÖýŸ¬ï½2{ž™½£²œ¡8ˆósj¾º(exå4Ÿ˜ï.N¥â,ÌòÃäãºú¿,Á€KеލòävQšÂì)l{#ûnc–KK)Wù8+Mo’Ùág…ÙÀ[W›$îÁô€ 6 Õ©˜+²Í£¢=èþÍhxÓ]Q;°“tï¤]Ú|—&/¦‹œ×†6d?2„bk endstream endobj 841 0 obj [ 840 0 R 842 0 R 843 0 R 844 0 R ] endobj 839 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 841 0 R /Contents 845 0 R >> endobj 846 0 obj 429 endobj 849 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 336.348 234.0 345.348 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 848 0 R /H /I >> endobj 851 0 obj << /Length 852 0 R /Filter /FlateDecode >> stream xœÅVMs›8¾ó+tl;±ªo¡½9­ÛÍNÚ™lèöÐíØ"fcãìöß÷•„1±§—Ô> žçýÔ#=DøOÜC†æ«è¡Y£H3ÄU³$¢3‰V¨KT¸¯:¶Á#|ƒ%ú•A£oßáåü‘c:¾n:öÝòâö»pÊ~‹7O« ™ÆGµñhÖ`%¹WE“¶æXÃ08žƒN‘ƒO¤?)»/gœ ûè2‰Þ~ˆ”d‡¦ÕH Ž™q?†’úöŠ2úú;JþŠfÉI5_8k'…t¶Ûx8¢PؘBŸ„å‹«› BLŸÓ• Aõ¤AĈL”tßÇðæÝôÝŸ³I2½¼žMn¾Ìþ¾šÝNÞÏ>L¿\'oÐk€qƒzH[*Æ$ÖJ¢„>%ý—1} àc€Ž¡ÛçYn·µzi;³…ÍÒ]QwVîì2}Ì×»ª³–­»³y:_æå}geu&i]WùÝ®¶G^CÆ_Áo7)®lì{’,9&†@t* þI«<½+Ú ×3¦X‚!£©ÙC‹E ˜«*%Ç„Ÿ‘7Ei‘/PZÝïV¶¬Q½F>‹ pÑP!±0à“¦‡0×ùºt‚‚ç#h´I+èÌÚVÈå½a1Ç,ŒkÌ„p"{X\í¤v©œ<ìlM2è—»kÝçÐʱÅh]ÚQ‡¸‰±vaÅRô°$ÃE!b x1lR3†ü|u=lôÔèY±Û.{\J,5 4g=(|¾k)w§’$DÄÍ~¾*ó:O äÛw´seŒ%ׯÞ@˼x†ÅXa㶘æ4ÀÞÛí¼Ê7£MêôB[hA ÄÆ^Wo4¦{±ñÃƒÒø©“™ü1ÈŒ_ã‡ñS¯.~ÔJKËïõc?ûdÓpٮد<ºœµÞ¤U îRÈãÂÄ’Ëž‡»”6¼8oÙÀ{*TÁh³R9mã/ûaèÞöÅöT«ãG4 ßwv\­Î( t›r‡’‚Þ?¥:§€ ú#è'J<,€DaÝÿ%éc¤Ÿä[™lÂ5t<@fÿ§«M1bÌe]+L(­›ºƒ®>ÑŠÊÜ4Ë켆b]þ3Ȩ²€3™±_³'¡s@6ˆ¤¼ÙüÖ¢i±]·÷ÀÃ5ÌÙÑSéïbþvR.8°1r§¬“¿cž¹Í9é7°–jX=ž{ᤗj8æˆ:É…·yýÿÈj endstream endobj 850 0 obj [ 849 0 R ] endobj 847 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 850 0 R /Contents 851 0 R >> endobj 852 0 obj 940 endobj 854 0 obj << /Type /Action /S /GoTo /D [847 0 R /XYZ 72.0 720.0 null] >> endobj 855 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 544.028 238.84 553.028 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 854 0 R /H /I >> endobj 857 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 438.556 238.84 447.556 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 854 0 R /H /I >> endobj 858 0 obj << /Length 859 0 R /Filter /FlateDecode >> stream xœÅTKOÛ@¾ûWŒr$›}ù±H­)Tˆ6ÄU„ƒ±×Ä’;¢üûÎf§Ú؇íì|ßÌ7;ûbQ øÛzñ%ƒ¤´^º= >îu[®T8Ì…:Û…BŸÚ0ØÒÂÅBc ¿­Ê"ðͺ@g ^-² ·[£ ~í!ÎOàÉ:¬ÓK(([KÄ0”)%õ p8“úc•pt1¼¸ íhx~Ú£_áÝu8>~€è»F[5qÊ>¡¦ÑVØWŸùÎN·ÑÜìáŽÒ®¢kD·TcšäÌz0)²Î‰l¦´Ýè%?Üc_Râ[Ý¥Œìæ«Ök¤æ^Õ#w뾪®®ÅóL1“£$N¦ÊnãÇBÙ/s5ËUƒ¬®p'm^Wp–óf:96Uo¢ápàçQ÷å+ôOq¶sjrTäMkÇm;Ëç-²¿=/Y÷Ñѧ™ Ê O1ËëÛH€€Ûë “ct ¦*š¶èº¼ù1Œ°èMg— ]ç?/®†wúMë|}Z×Û¡ü!©ËRUm³F¡„,aöyÁ è”:½ä@qôÓ­vžãëËçSnÇyª Ì2•´Í2¼wm‘‘2ê9i Md4UW­šUq+åaÑ}ÈêÙ*ÛÁ£>êïšôûÀiŒw'nÔÁtcï„CÞ@Y§y–«Ôù·"THÇÅ`”¤.ÔP)<¾­Ær=Z Ïu„ýcNzøÉž¡°S•Åó¢=ÙþÞáda8­XºþIÔ³*lÂ8oç±¶ßí$cžãr_JÁ;ŒÛºRÿ¡s…#%A¥xwëÆJÁ°hêý21|í¤Ÿ '¾ã3OÒw—%¶ê]U8¾)§ŽHß全àYÏ]ô% endstream endobj 856 0 obj [ 855 0 R 857 0 R ] endobj 853 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 856 0 R /Contents 858 0 R >> endobj 859 0 obj 674 endobj 862 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 438.556 204.0 447.556 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 861 0 R /H /I >> endobj 865 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 426.556 204.0 435.556 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 864 0 R /H /I >> endobj 866 0 obj << /Length 867 0 R /Filter /FlateDecode >> stream xœÅUKoÚ@¾ûWŒr‚Î>l¯·Rª¦-©Z©©ª*ppðBV26±Mþ}gYchzIÍagßÌ7O ³É`¶t«3 ‚ª#?ê¹Ì‡%T²‰yÕØNÂÅ>Bá~:©Cà‹s7ÅËžÒV·œ›†}sCÞÜ>…óqìœ_ù@ Œçuˆ¸ï áB}¡Ë™4ƒñîz_¯GÃÛñàvøéÇíçQ ãoÎp¼ç§ì?¸s³ÇS*˜p[‰Þ¢¹=ëÈ\%UªÕjµ¢%g×£¤H͉4)íçøMO¯0@JÜp/±”ùG³ùÆQ;H¤±ýâlûã…¦J}ãKXg úÞÍó ÷j¹J²RSëaɈË‚_@[Ч•+¸»°pOÒ)jà옆¹VIW³²ØÁª -R"] MJ‹üžÅz®gQ©³´€㸌PW™Aù `Æ*O6:]@•Ñ}T(÷ïô(®_eårKMÅp¿9I/ nHj”¾^gé«,JS–8½0´ÀáóL­ŒSÖª.×ÖÁSÆ™™t\HéñJÇe }x  §ò<Ëëm6¯år³Rõ®xL»Xm…A ª‹Æc½@‚ ¦¾nhÞÑE²-¾ GA®aà‹æh>QGåä$¸›jš•õ&jFæY¥©: ÆzCKú<ºÄ¢æ4è µ éñ b7À7R—wÌ´ÞcL+5ÃþÀEe™ëûu©l—˜pÌ3ìWT'ó=WJ‚ýÀ«F)—I‘½ÌñzŒ6˜\éyf–vÏQrðg¿^a€Ô W³,‹Î¿£8dÿª8V‰êT¼UpÜgN¥+X C)^Zcwª9ŽXBQ—â û·6oœ?KwA° endstream endobj 863 0 obj [ 862 0 R 865 0 R ] endobj 860 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 863 0 R /Contents 866 0 R >> endobj 867 0 obj 766 endobj 870 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 440.556 204.0 449.556 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 869 0 R /H /I >> endobj 872 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 428.556 204.0 437.556 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 864 0 R /H /I >> endobj 873 0 obj << /Length 874 0 R /Filter /FlateDecode >> stream xœÅVIoÛ8¾ëW<ä”5ËE3hںŠfKíÁ`Ðô X´#@’jã?¢,ïžô’Ê}"ù¾·?ú1b@ñ7ò¯Lr˜-£Ç~AÆA¤ýR’‹ O` =N ö§¶_#|…Cî៨‰(|Œ>ÁÍ( |‹è>]'<‰n¶ôûúâú),¢·Óèõ‡…é|"!H’$”RÁ '‚Kÿp˜.áóåß½¿žŽGŸÆïþüô~rõ¦¿FãéŽ;‚ñàÎÍŽ ˜ÒŒgd/Ñ´k¸ˆüVÝç Öƒqá}Ò(º±‰n›´›ãU~:½™d”ä;‰e<;™ÍŽÚA"½îÁ¹ïOœû*M¼/iœùég¸½¼½¼ø·5Õ\|,…©D‹€ÞXýµRŽh³¸¸½º½ žo3rJDŠ-@S(¡{ÂÁ×0¬®÷ÙŽ-eI– ÜIœT¥‚ñ|®fήÅr‚3AhŠ*Y.ƒàﺬæÕ¬p•n,FÁ²@*§ÁÝ+h›R™zU5 ( WÜV‘ÿ·ŽQFÔ 3Ök¹î,S%Ü­ÎYÇxBrÊ‘qí׺y–ÆÄ7)N“8σàøi¦¼S&¼rmpð¬ò,'‰È¤ŒEÏqÝÀÄ‚Äp©ŒÑføÒóºÕƒ>ìc=ZÇ©£]¹ÊnŽV 4­Æ ›Òµ™ŒîÛÉSN2‰!ˆYrÄbT]«“NryVø˜™v.¶ÂñTYç«bƒW¼!hžáŠ ¡1&3Oâ#Ö¬ãx:e¨àŒü«cÅš>ìB&鞬}P3ìŠ.9#,IôÝ9SݵNÙÍ’Qa x®±k†¯.ûvvè{k'7¿ غ©¥j6lFÙ¶îCÝó½ ÜÈx*s™ c+ÿ\ˆ˜Êü…”e“»Óyý¨º‹ó endstream endobj 871 0 obj [ 870 0 R 872 0 R ] endobj 868 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 871 0 R /Contents 873 0 R >> endobj 874 0 obj 868 endobj 876 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 678.764 204.0 687.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 869 0 R /H /I >> endobj 878 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 666.764 204.0 675.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 861 0 R /H /I >> endobj 879 0 obj << /Length 880 0 R /Filter /FlateDecode >> stream xœÅSMOÃ0 ½çWø‡'i—æ¬ !êZi‡i´…©ÝØâïã4ÙÖn—ÑlÙñ³Ÿ_³dNÏm$L+¶ 1Z‚ê‡PÜqCÁ¡t·ŽÜzdü%rÞaÄæ áž'”œRÁ7ÃC¸º8gY£¿ËàÙû#¼±›‚]ÝÅ Š×ýŠTÄUbèS®¤sigEã‹Aú˜io˜Þ>ù劖-:JÈ “µf IµÔü@èºZùE> endobj 880 0 obj 347 endobj 883 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 520.556 150.0 529.556 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 882 0 R /H /I >> endobj 885 0 obj << /Length 886 0 R /Filter /FlateDecode >> stream xœÅTMoÛ0 ½ëWð¸&ÉŸ:f7lX;qÑEnL'»±­ù÷£,ç{ÉrÊìƒR$ß㣽`½sZÁdνOB Àñ{—çƒt¹ò`½íAaníjmÑa/‘1ƒGV2_ØÓ3S”ð›‰Ãr]ò˜vú›ˆ¸zSö1f>{ ÄÙvDÊç¡ö„®!w”6‚xOÑíC nÜÝ ï?½†ø‹â=>ŽTÿÏhi¨€(Ýe;ÖG[È„Š^„þ´U­iÁÙó$(±Å$v!í‹|Õæ§õ L¢<ÜSV:ò¤šWžÚ‘¦÷†’„ i?å­NÜ 'e9ó!Ê2œ´%÷—q¸!8š ß§‚aŸø8KZü…5 M†v†€o8Y¶yUB•uŽñè;4-ÝœcÙÂ,i€b&°,S¬‹U^N!MÚä%iðò ’rÅ×8NÓðîÈͰ)¼¬Î±Ð’‡BQ=íÙ¼ûªÄ úIe¦ïRCÕ'Fo|5L’$o—‰±ÏNPºôA;Ö®Ú_³K†V`’Òt+3Àº®êæ†lkv)«W„fQ ÖƒØPÞ@“O `é%ŵÄÑ‘ýn °hªÍÒowÎð C®]×,^·tú³8ú5.–X¯v>¡,«R§_”±Z<;bå .ˆv=y¤o×qÄþûz3 endstream endobj 884 0 obj [ 883 0 R ] endobj 881 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 884 0 R /Contents 885 0 R >> endobj 886 0 obj 538 endobj 889 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 73.49 210.0 82.49 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 888 0 R /H /I >> endobj 891 0 obj << /Length 892 0 R /Filter /FlateDecode >> stream xœÅXëoÛ6ÿî¿â /K€X#EQ”´@6¤E† hoEQƒlѱ0YJ$9‰ÿûE½¬‡kdXbÐñq¯ß'=L(üOÕCx,7“‡rŽ‚°€9åw€Ú¦Åa%Í!R»Z„UQøÐ›X×IµTMjãôsÔ(ÒØDÚ&í‡öU•GU(FJLw/ž”±Ñh¾2j½@*ݵ?èMÇ!»Ÿ«PFÁ4ö72Ó^ à@1Ѻ|p Ìô9 ³š¬x=–mº®Cå^OÒl\/#ãlµÖÅ®&¹ò·Q^ŸÖár]6Òc󵟷²¦3¹Lâ >úѶYLe¾Mc ¹ï×TfìdÕˆÎÓ0¾ËZÒîS™É8ÇYB;T鸬­œZÌôàd™DÛMáO9‘ÉH.ó´r¦@¦¤+ûIAm<þÂA-*¶2ÝMå³²3 “x4V–ÍÆ¥˜W«cl²¸0=Ê q¹ÝwLÎ2¥bTBcC˜õíéå/cŽIËsÝ!ï>]]›Áíœgî½Ø–ùSŽ’U7ê͸¡íM?˜e2Fð¹Lk“ê<ö3ð¡Lù"ÕÍñ¨ 0ŽÂð@âÐ2‘Ÿßº/8”µ^NÖ~Ö ü†lŽq9QÁr¨ÑôxÍÔô\LHÓ¾‡bF]ïg£ºª.å°*/å°¬/õ¨e?ž%t¯í{º·Z—˜jy¦*Kú ¨•̼jÍ|¸¾˜}îç†cw¼ÓÇA°Àª£©X(g}þñbî°l•R¿(¼™ÄÑ®¡eEjìªQcn55^%iEJ_‡Io[&i½©]2Õx±ëzß?Œ`év0;°+è;rt½´ ? 欲£Ì›ÆóÚaÌ™~<…ÓÔ>çèìïš 0U|P9RŸu†ÇÅ´\ž=+•÷–éÚX?,V­Ëgs5¥·— heÂ¤êæ¶[sÍ54`hÌA¢Œ08[…i–ÿ£ªØYäWÔZ†wëVi²)ö%;)ái-ñ”h6xÔ˜Ÿöý§¶×Ñûî=ÌQ9ãïÈÂM˜`\Ë8Œ  &çŽí84 óÓù)‚ÞèÐŽ@hh;PTãjÖN [éòÿ!_¼nP@ÿÎ[*Äa4d³Eþ²â{ ,»‹ü¬| =}0§ùîþ|Î|Ú9 Q#hŒè½ €Œ¼@Fð—ùÉyç þçA²]Drl¥^’‘#ÂøÏà¬Á;„Ú{àB¡z"Èõ8]ü £‹8H“ûä þÆ2þ7Aúc’.ðö’jþ«Äê_äÆç-¾0ˉ”QASš†Ì²I·Ì½Ð}J†²Æ¦]të¬ÑP ñXGfÚ ?½ûa®{¾½½CkùùÍh n: {Á…æ¼  —«â5þb¢tb!ÆÞûK—kÎ/Ø,ÊG™‚ÔÜ î}ù,—é$V¶š¸½¹Õ9ã¼šÜÆL£¾ABàçþÂÏä„xÃÇ»#®wŽoæ6³=OpG›rQX€ÃbwÈn;¦°…çr·ÄíviÇhø¢È(¾ŽQ5Ky¯üô#¸ ó­¯èƒr›Ü¶±Ía%€W«ŸAI?@\ È4MÒì iMÛ±ü@öM+§z {Ì,¼Cã"áŸcY&Ár//¹ÅcreIýÕ¨ùh£ZpõnIÕ‡›â£M¯›"½/ÚI9]&› 6Ì­Qêÿr5 endstream endobj 890 0 obj [ 889 0 R ] endobj 887 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 890 0 R /Contents 891 0 R >> endobj 892 0 obj 1405 endobj 894 0 obj << /Length 895 0 R /Filter /FlateDecode >> stream xœÅM³Û¶ñþ~IFb‚$HßR×é¸ãiÆã7ÍÁÍ’(‹DÊ$ågýû.°ø" BozHŸÚ±Àbw±üõ‰FþmÅ/“hyúªÚhÄ“ˆåª)Ë#šÆI]"gÑYôr€DCðƒ8E¿=µO$úûÓçßáã!"@ðòDæÃIâOOùÅò§ÏO¢/O}~úË/YDIô|´"ÊÊ8Ï3BªˆYRŠ¿$z¾DŸøôîû·Ï?þ=ÿãéÝódŒ&ÿ‡e|œðªä g –Ô Û ŸÎJöêGE™ÃßU¦ˆå‰¸,Muû§N¾®V.)‰‹‰B)+Vµù'Km¡H1·Y¬f¶ ´X˜ç±©Ï‡m[]êWå‘…Í>§û9ú1â,¦Ñ»®;×Ukð—f<¤2С>V·óhðoÕùV¬;P³QÎÙHr°Ó4!$e傟çUîv•,6ÓþvªÛÇ<0ßsØé,_ÊdFÊu²™v<5ƒAŽ·v?6eª¯Ç[ßÙõ¾kE[!ƒÅ&dÆÎ¹„–ÒŒ‰”–b0i1±A•ôY× ã1-ÁQr–,'þçûëJ̲åÆL­$¨8¶T«iÏwƒXqêµµÛ:ÃÛÖ59õÝËë…x÷ ôã)%„R†ü÷õ±¯‡Sp.ˆžq©Û’¹+Ôý¤V­0°”¡9Ô}}°m/¨=…½ýðë'‡z÷Ÿz?:ÃU½3Ï®nÚ/ê3t®±múÙ錞Âc„Y:[œr"[cèÛ™ÙN,}k-}ûÀ‰$Eœ³ )ãËiƒ&˜æÊØL­¶ÂVíèú1³n§uϧ0cšgËé÷ÕþšXw@E 6³ÿQß_ºþ`p4£0c)cqQ¦eQºzÝ'‚;Ðm<Ú7·õOž-)KÎ(Ò¢/d"zþP½5 øºMÓêJhÉc’e™•|9*Úöºy€Ö‰Íäûê|6ÈKã è ŠFðÎÖ ßšúÅw®†Á`M;ŒU»·}ÕæMƒ0Îõõƒ0y1ãü¡oâÅ’HÌ—?„àú´E—6+ér¨u¢e Û˜‰G܈ çn´<ÉMhz¸þ¾›Z†¬¥D/ˆðíz¨FéOÕ7Û­­h¨ú{lšÞ;ÌÜö'A—d¶–}5ÔÃ&ºw·èRÝ£—f8Ecußê¾_ ÞO]÷GÈ[Ò˜ˆ˜Y€ºãëåm)­Hs!jõwãª'_ÃB“Rù™í&‰5„)t“Hr7ÞνˆŒ˜¼aƒk6Ø‚f~÷’ï»óíÒ:}UÚfv~:íGÔœ­%I¸!¶Ãýâz™Íd²ëÎͨ¤ÏÆŒ£ÄdgaXé54€ïm¿˜³X…îßøgÕ9/t€ÝßËP¶=߯æû¥;hß0ïošÚC³¯ìã©—kd„ÏÖ¨ d)©r^ƒÅ ¨–cß],6!žx0lBZ\Ié-ÔE“Ñå¾xåØô®NoVlÑg—Ø9,ÑlxÔÏh9µÝ-DÊ"äê (sJÁM,‚¸¼H"ݼfv Zåi.ÝÅrˆƒ¬‘NŽfY€üuä$.†‡*Ë1„ÕBr¢}Ýü(ƒ$ T<=öÝíºÝÝGBÅ:õ«æORÌ\ÕÛË1NÕ·Pý ”!ê×qRL3°#^PÏçæÒ ¿ŠA–³¬,rÆÁ"Ëu”à:¯eaﺖC½ˆâe}Ó&AbÃ:|ªüGÂèç¤òí¥î)d·“¡†­£±ÄUýŽŸÚ±ú¾ñí»bïŠwgÐ}wáØ=:Hçiäïb@1¦°ÉdìA6">ÉÚ[,hý`'‰<I¸g†GÇÕ¨Ãe8˳¸LUí”á[.÷È ñ‚ss×ëZNª:ÏÍ}‰„Pg¦·®¨ð› èæ+ªMv5͘Iø(“, ª:›Õ}gnï^kƒË”q>Ôd¬±÷ǰ 9ÿŸe¸ •5•gNƒ…ý |q›JEh^Œº£ ‘ÚÉÕÑ"¸4‡5µõW#\ýÙéj_Õ =ˆÛC±t^9ÓiåLÊYÂoªº D/uÕN†õ¦ºE9[³*p ÇÆ‘š4˜º1@æ½€›ünZ… ¹©‹„ÂZ&ÂÊ4Õa›±Aá›SÈÁXY$õ°þš×ŒñІ‰fXðã¹Ä,â<“'À>IP@† 43ï¬4­! ®ýbZ×JS^U§„zU½eÜ=½˜½ÛåS{¸ºEåú.“Ï&auÌ'¦ŽãLj<Ùæp`ëZÅ-ªŽÇ<3ã¢$öÞÌpU,ñ Ç#2‘§Lz†‹ûHÄ!äª â­Èi)÷]”3Ò »úÌS•˜’{ÁOÛ‘Ñ+8Ÿ*R 5ï9 IYƒÕâí¤= DÏ3 ¬ŽW ªYtƒ>YR:ç"Øàž‹¨îïªh,Þ5È·K¶%%Q;¼YÆmGüPƒxÕA†løÞq#òV\Ô¶·Üȃo™qn…òÜž¯#¬ÏJíÇjwÆ´Ñ΀6¬KTªQØX ­'Äo  à™Ý‚æé ¡™Ô>iB¼2Τ$‚©”• y« æÞycËË©s&oÒ=j€jiÊžŽõø”¡-¢O}çŃBܳ,ÕdO‘W‘|IÛ×âNÏé‰~žžÓÓqü.ì ¶ø'XæÖæľ®RŒZð\©ÎW‘ÑË®ZÖ,—'3‘áIï–‹S%yÀˆ`}¹ž»;r+0 ’àµêGƒ h¸sÞ%a·Ú‘ ªÜQE½cP]WI¤i½ãjf¨yóœð¹©g}á"± ±™Þ9€Ci(÷gyí¬.Ÿ/%e,!•I™x&{°)Áé…¨¼,ÒYÿGï/Jâ!ŠänŸ?ðPêOHœð©åXÁøI‹©™{w7 ÍÁ7µšÄt†˜ÈÁ¤6°öQ1> Wìú(Ùâj²Á<ßÀ]¿9_•R] $Ÿx6j9o|@$*–VÓgö]€x?®ÌÄëà‚¤džéX#… V“㣀 ½üÖt·kq5X×zÍ0Üð:[`ï3Î=¥F •}™ŠÐÄ3ù#ÓeF€Üp¥EÙßd´e¦þ2jC‘TÚL–*ÍÈ<šºÙ;$öÅ+"ö±—þ:XØ<÷²M:Æ!¦¼'"N¢Çj+}åùzn5®½T-ëUWN<ëœ?úª¡+ø,™‡uP…0m˜5„:(V/QÕÞ#+Œ€ò>«Ã§ZzF#žÌ9Oó 3J›9oi&Ãa‡Op3ɳÆmö¬Z´H%2¹vTmú:sc›Bò$æTì0°«%£Çs5^œ æeÁIî!¶ó«WjtÎ6°Áä%jõÇå<ÖĔӲä„{¸EV©Ü¼r@Ô¬ ª<½Á<ž6‚'ƒ;GH™õë»[?:ý ¤kn‰¨·sº}ˆ úÞ~ ØTĉxP-ƒ/˜}`,Hl¦oì*,ãÊžqêe¿B\ úáàl …¨ðŒ auƤ{îõífì/xt%^;OV ÞÉ Ëj­=¡5·ŒVO‘ùÌH߯xG”A¤É“’$3ï*Hí9Ã2Ë+¢œ‰ìŒ‘„3uÈýoµ¨èó±é‡Qžƒý½‘û³ÊµeƒÐf4Foô•gä9,ÊÓt6|äû{ã¹EmsVòÿ’}|ú/éLL endstream endobj 893 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Contents 894 0 R >> endobj 895 0 obj 3619 endobj 897 0 obj << /Length 898 0 R /Filter /FlateDecode >> stream xœÅW]oÛ6}ׯ K‹Å#)R– tÀRdÚ¬X£EáƒÓ6aYr)¹YúëKêÃ’é+YO©ýÀ+š<¼÷œ£+ù›CÖßK3Œ'=noÕAcŠ<¿šâ>"lD9Ú¢*æ(6«Z­#=”‹t°F_œÄÁè½3õ „õ†'ÛpÅæ;ç¶u¾ù¿øù­œ«™óÇߌfˆ">ù>Çk¢‚‘G'æCÑl‹æw×7×ïf¯C4ûà\ÏŽÊðýeÜå ¥ÓñȸØí•sz¦2?Å÷ÕX¢–a™\9v&…›œp;¥cm_ôðnYÇf#Á£àHPâM:Õ|aÖN„4gê™Øõ°À¸“›Z|¿,AŸ©Ù>Î/óçÈP"cTÜ¢xäùÚñØ'}H©ZuùðŒæK©²ü2‰¶"¼}ŠçQ ïíŸèþ½J•Ì\ä~H3±ÔãÇ4Éò(Ée¢/nDZr¡ƒäfÉXGŸäFæ‘>ÇÑBn¥rOOd ¨ÀýºWÒ…ôkùýE&bñ˜•†æé>ÑsoÂM—*Õ+Åv§ÏB„§ Á ‹2±I<X©t¿³µ8!"¦_Q…ø}(K)âE±·¨"œP›ñÂ-S-”1ImŽúúÈ$õde–öeaªM¤ŒÞ×x¬F:x­ž8x¹´š*\U®OómÊsÅÑÁ[¶ŸqíúŸÖB -7Âàé‚Bä¾JÕÊ…¤ l!N¬Ð$ u Øä¶ &C`CjP¶ñtGùåÔ³Ù+»Ð_ÉB¥»ô»–ðJ‰ëD˜ð&1É&ÕñûT=Dëbþ£ÚgUx#’„ÿîD­{—Gq±o¦Ò<Û<ë諈óLÏiiÑÖîqÛ>ÛèÿÒ1rt$ˆ·€Y`] ©"˜øg0ˆïá``"Gn˜Fû<…Ÿ0ØÂ+Ä%\ÌlJ£ï+4_ ¹Zç¥^†49ÛL•Ix ŸÒ<` 8½À®¥I¯»¿sÔàm³žèç2$ÃÄ6WÕ†ImoÓÓ~v2 8IßMåÚÓ&ÁÿL‚ «µõ·kDÓ,W2Y ò5c6evB-rHëÞ ¹MM7äy¿3à×ßÃØtTÇsŽãóF:5OÓøë529KNÍs’êÓDþ$D¢ßœZ–Ä¡¹æu ßguNÏ’7@îë[½Ôsf;¶¼™‘þ»Œ¸£§swÒÀtöìšb™4€¿µR‚¨ìlÞ=ßïlÖƒÌâŸôæ.ÕÀWslQïÅßµ[ç'œhíW endstream endobj 896 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Contents 897 0 R >> endobj 898 0 obj 982 endobj 900 0 obj << /Length 901 0 R /Filter /FlateDecode >> stream xœÅTMs›0½ó+ö˜¬HâûڌәŽ/3ÓC&dL R"A]ÿûJ†àÜRû •´ïíÓ>‰w‡6ÿ•˜BZ9ïÝ‚tK~ÄCÔ‡ ºØ‡Òfz‰ÌÐ&™à?á`øî<¿˜Í °<¥;ƒwÎvTßîà/¯!w¾%ÎÓC²ZäÇ(|Œ±iT„\Û…¤‚ç»Ýz³~Lî_ ùᬓ«c¸„þ‡cl¯4+C¢‰Ág´Û®™•–Èn•]ï»±emÃV\;.ŠÂƒ&<–tíí—_¶5´@‚Qte(ñÈ¢›_ܵ™‘¶öòy¼hv;“C¡áÌ ðà®âL ³úÀê~RˆT*ÅÓaEªWh]ˆ¼Ÿÿæ§£T™þ(÷+>*ÉN},äÀ^«"ÏùãJI¥GrF2yGlWòMÒ°s”M™µŽ[Cñ¤7ÅÚ¬‡§xöâóàq@æ@ÍKÓ© vfCLo`áÀ2xå\@Æ÷…à4çÞv=¦ò¦â¢Öh~"×5¼$r/îòþFÄDG l?Z.öçÐ}ÁËl%XÅõâAˆKo0ÙêÄ'È‹ À÷â9XqÝ”õª>½Ý¨O©{ƒbÞ2q`½¦`Êgœ@ÔòE¾7ç{Üì¶›E-®o±q…áGZøßš ]H–;b ¼ ð“«ys˜ʪ’Xª¤Ö`ŸÈ¾imê³òì‹|ýexWR¦1æ’e¬fP1Q¼5%³yP2‘7,ç—‹vþÚmDˆÐŸ endstream endobj 899 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Contents 900 0 R >> endobj 901 0 obj 581 endobj 903 0 obj << /Length 904 0 R /Filter /FlateDecode >> stream xœÅRMoƒ0 ½çWø¸H“ð™ë¤uÒ4©«†´CÕC´e‚Ъuÿ~IC•@ǵƒƒ;ÏöóËQ ê÷´‰9ƒ¬Fû.F!fàG](Œ€˜…PCç‡Pé[ŽÃ®ž2æ’r¶ð$"ðŒ–+•Ì(À7"Ãrð;Z8ýu†Ü½? zLÑt%®íŠ¢ó àœGì3®?i ˇ×ùüm²‚ô=¥=>eÿ@bÑ›A ³ä½ }SSH§ªnó5Uk†3vt(bg"îH}eïÚ|\ÔX)ÁIOND£jÞyk7BêÞã|‚äæm¦Û&à Žá¡8·…Ì‹ÜF ÑéŒKQâHM2¬W5Íî ºéOÿdûd+Îö\­Ÿ5uÝH{Ù¡9:ùÖ¥²>ɬ-)* fÍçW‘µ^s( Ùº”sÑ {ª…,w§JèZ6Z é–înðڜĦ8bçµ,Ð/ý» Ñ endstream endobj 902 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Contents 903 0 R >> endobj 904 0 obj 367 endobj 906 0 obj << /Type /Annot /Subtype /Link /Rect [ 510.0 615.782 540.0 624.782 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 882 0 R /H /I >> endobj 908 0 obj << /Type /Annot /Subtype /Link /Rect [ 137.251 603.782 227.251 612.782 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 888 0 R /H /I >> endobj 910 0 obj << /Type /Annot /Subtype /Link /Rect [ 290.955 603.782 326.955 612.782 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 909 0 R /H /I >> endobj 912 0 obj << /Type /Annot /Subtype /Link /Rect [ 174.44 579.782 222.44 588.782 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 911 0 R /H /I >> endobj 914 0 obj << /Type /Annot /Subtype /Link /Rect [ 227.44 579.782 281.44 588.782 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 913 0 R /H /I >> endobj 916 0 obj << /Type /Annot /Subtype /Link /Rect [ 407.79 579.782 431.79 588.782 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 915 0 R /H /I >> endobj 917 0 obj << /Length 918 0 R /Filter /FlateDecode >> stream xœÅVKSÛ0¾ûWè3Ä•dËkKéL'˜f¦à A<ã¶ É¿ï*’#áØæFáàÝ•öÛoWÚU^=‚0ü¯Ô'N)ÊJïÕØŠ) "cb"¡O*‘‘*Ô.G ƒ½ „úëUF¿¼ûGXÜ" ïÃÿxwN|µ‚¿<¾Ë ô¿0¸ûx 1ýÑÙ½m‹RK…)›ùjT-jrú;K [Nxº(†î×ÇèÅû¾ñ¾Ý0D0Ú<ÛK+G‚ý„¦ê¢M‰î/Å—hóÛû¹9;Í/®ÚÙAªØ§|DC?9’ÿVúaš`L¢Ä§IŒ1Ž"ÜM_e2¯+^ k.9ºåUÞôW6õ †0ê§aœCŒø$dªJD­yõÒó.n®o×—Ú{¢Êa‚âÄÇ )b¦Æ›@—(‚ô/ž-#cÙ*bF.~ƒ-¯¤hŸyv‚hÚú-ߊí ?i IÑ Ø9½ë?wëÙ„ ¾JÁàFœùZ–YÑoE7ÎÓêÖîíD+óêåj°ô T £3Z¦xW*ñ€@áD!”“Q[‘Õí¶3Z^AìóÎÙ¥ªýÄ;aTP 1øXh±YïxA}ŒôÚ‹6Ÿðè$—¢•–Þs¹‚ìĉcײ;O“`:ʳ~Ÿ¡ª<6¨1´Bömu¼ÆÂÕuÞ5V“‡Ft¾Õu.Fù@ÛØÄ¾žÝz'[(Œc(ùÁ*OÂRUtqLQf;gópÿÒ³† ¦Ê£JrXjBÃkêæ¬¸Î á"# Z% Ù†Ii•Õ%ôêv–a †`ã)*–Ç©O|kÓãâ3¢”$~Ê ¾$˜ÑAwdr– eá’÷9Á+k:Î&#K—k ZkÕTÈqãEQ¿wrÝÎàdPÙöÙj¢Qh4¢jfåŠÂˆLÛhÙimÈC“h­ït³Õ°ÑJw(Ÿê"ϬŴа\I¾÷­á&‡é^®œ¸0Áa¾½9 £I?Ãþ`U3:Щ1¨ù aH˜¹}ÓÔ­jBõLÌÝ%Õ_a' à m½Zî7Âð’ÿÕBdh”Ï’7Ÿ„¦8]@ªëy…Ä^ŠJ=šYÁ{ÿêòOyŽX0?N7aS¸E]7óO&K—|Qɳ¶öŸ]wÞ?õ6ÑM endstream endobj 907 0 obj [ 906 0 R 908 0 R 910 0 R 912 0 R 914 0 R 916 0 R ] endobj 905 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 907 0 R /Contents 917 0 R >> endobj 918 0 obj 885 endobj 921 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 709.5 186.0 718.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 920 0 R /H /I >> endobj 923 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 697.5 168.0 706.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 911 0 R /H /I >> endobj 924 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 685.5 174.0 694.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 913 0 R /H /I >> endobj 925 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 673.5 144.0 682.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 915 0 R /H /I >> endobj 926 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 661.5 156.0 670.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 909 0 R /H /I >> endobj 927 0 obj << /Length 928 0 R /Filter /FlateDecode >> stream xœÅ”MOã0†ïþs\õŽí8ޝ v¥BÊ’Õ !1Pm>Ú$ô߯CIB©—ÒVòÈöûÌØïÔ[Âíwå¥9<dÛÍ1PDØMÉX@¹„ºXBîvõþÙÁo²Á3ü%%AøIîîíbh/Ǹ7ñ ‰{ùÝ žïªrB†4øÉD0ëæ‰oí“‘CƒÈ·×á„z|BüÔ­›z]¶«íÎÔûÉSZ&ãÇB³j™Èƒc‰EºYFúçéd^U›9šýIkLnÚï Àìÿ-BD6fT¹^SLxÈuÕšÆ3&ÚÓYšbZT¤½$y6ð®°ûÇïTHQÚÌå„öqmòlU¦ÅBR&øÒ2[ÈÏ$£¶jè umš]Þ®Úýf¡ÎÅþ™ýKUgÖO»Â”mc#顪p ´ÆQ &€W7ñÕl5B:±{ùÕd5æµ5e³®JÚë…˜ü¶Žd endstream endobj 922 0 obj [ 921 0 R 923 0 R 924 0 R 925 0 R 926 0 R ] endobj 919 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 922 0 R /Contents 927 0 R >> endobj 928 0 obj 458 endobj 930 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 426.556 150.0 435.556 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 882 0 R /H /I >> endobj 932 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 414.556 168.0 423.556 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 911 0 R /H /I >> endobj 933 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 402.556 174.0 411.556 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 913 0 R /H /I >> endobj 934 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 390.556 144.0 399.556 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 915 0 R /H /I >> endobj 935 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 378.556 156.0 387.556 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 909 0 R /H /I >> endobj 936 0 obj << /Length 937 0 R /Filter /FlateDecode >> stream xœÅ•MSÛ0†ïþ{lg¡[–í:¡†´†áàÄJâÁ±Û¡¤¿¾’å@œ/È…*¿#iŸÝÕ®”™G›_Ë~BIa0ñfõãõTÀøˆ0ZÚ]+‚.•ù¸MFŒá·—yμ»{³6<¼Ž«Œ»^gÅ¿]ÁïîÃÈ;éyG§ ½áËù>â\J)H1*í Ð›À݇ë›ó«^«ó³}sûñzß½v¯‘ #ô?äÒiÄ`êÒ­U¹²fnÎÌ8]JëÔ_GuÒç¾;ƒÂ/1áÕš~Wç»kZC‚‘hT•0¾³šï|j…´¾Ÿó‘½*l‹6Î]2À…ÒYƒ'¹ú;ÎÔ#@¿V_ ý˜¨é|àÒ^ÅQŒÇfpâxàvž'àÆqçzª /ªÕ+> endobj 937 0 obj 723 endobj 939 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 224.556 150.0 233.556 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 882 0 R /H /I >> endobj 941 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 212.556 174.0 221.556 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 913 0 R /H /I >> endobj 942 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 200.556 186.0 209.556 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 920 0 R /H /I >> endobj 943 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 188.556 144.0 197.556 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 915 0 R /H /I >> endobj 944 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 176.556 156.0 185.556 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 909 0 R /H /I >> endobj 945 0 obj << /Length 946 0 R /Filter /FlateDecode >> stream xœÅWYoÛF~ׯèÅ2`1»<–d€pR'Hê¦q­"l?¬¤•Ěܕy8Q}g¹”Dñãu©Îs}3œ= (üõËm˜%ƒ‡j‚oƒÃª-u-Ûƒ*ÚƒXߪö–—¹„Ä ¾ ä€ÀûÁÍΠ÷iŠ+™¯W5ýú„¼¸~ËÁ›ÉàÕ;(Éb‘G­ ô!.ƒÀrìP?6L¸ýòûøêÏ‹?¾žÞÁäãàbràˆCíÿÁ‘«0˜¾í[—ÜŽÙÃ#HÅúÕÛH5¤1μ{"{›HݤÃ辨òþÀúš‘+8)uÞh¾0j­@jÝ;¦?n óÓÓ¾0fœùégøôáÒøS¿çØ–Ã0¥ £æâíh®Æ…H7p‹‹ŒÇIÉq{ ÃLÄb–ƒÙ=Ó»°HUY”¬c1¼=mkp݆@Á©È‹T"1S2ƒ%úזⱆtèv4¤zË"d ãÑ|ŽDšv[–¯±ÈK7S‘q'H÷6Òn@UatSató,ëÍ;x]‚t#$µâ®-ž’6LýÏk•ÎE:žnêZîºÌ¦´ œæ¿­‹lUÆõn§©´¸·÷;n»M€M¾Š8Ï"9„á$Uyv¿Aê:çq¹õ¹ÈË÷¥åû×´Èf+ñˆä{•NyIwèòÚñ¾]‰T y¯ýM*þ^ÉRÒ¹œ§j­;Ó‚úMˆž“4hCÔHŒzVœlsà1´I×Z ñU>~äq!@ÀÉN*=Z›¶ì­m7Óó¿ ­ít¥ì¿ ­í¶ƒ£sóÕ;ƒoÙžÓƒJÀƤð±`Ã7Œ×Ñ\ÀÅbA̶ì­F¢ *¡a¨3ôª>òeÅsñ(R†òF께!Ñ‹ÅÜêè]XÿZ¶œâ¡gù0Ò6ì²H¦ãÝZÕ.>ò4âÓ¸~?Ðl¿ŒäžÞbƒÈ4À¡AˆhH02]¦ñtÙ¬Mc¼•z#.çûÅÞCÖðÕ<Ô\yžFÓ"ß9ÅjN5åÎ ?r±ª¾»u&j‹¹’'y׸A¾%<Ÿ­ X×2¢#ìÇÒÚe…Ø…¡ïTeä øyœ©Ý€¸ŸÏ´ k…®«‡´î´þ?”yÜ9njy!{®¼„¯ÇGez$x®ÌuÉü ©6y®ÔX©u¯8OŸ)ÎôÙšÀ’±?¶ -ßfXèý]­Ã4>V¡¼Ðµˆž> endobj 946 0 obj 1237 endobj 948 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 172.476 150.0 181.476 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 882 0 R /H /I >> endobj 950 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 160.476 174.0 169.476 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 913 0 R /H /I >> endobj 951 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 148.476 168.0 157.476 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 911 0 R /H /I >> endobj 952 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 136.476 186.0 145.476 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 920 0 R /H /I >> endobj 953 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 124.476 156.0 133.476 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 909 0 R /H /I >> endobj 954 0 obj << /Length 955 0 R /Filter /FlateDecode >> stream xœÅWmSÛ8þž_±Ã}(i\Y~Ó2”2׿Jr×ë„|±BƒÐr(Ó…þ û½óóïo‡ÐÿÒ9ío8áØôpâbà d@«ÞBÚ)çp¦ÒKIÅ|õ.QËai\ùÞjy´‰¬›´ÙWU¾=¨´‰n„Óv½­Ñ|eÖZÔºWþ°¦?n¨sÓÓ¾ø~éÌá!ü ;>‹—Sz¿ŽJ‰åøß^Áæ"Ë»3±¬ƒ²mX‡¶aÛ»\·½ëôN¤y÷Lñùä -áùm‰kO[ÂÛ'½óK8éh2ãj ¨P-­m2£ƒ¡·Ob&¡/rË2¢ífà-’qÞÍö¿‡Ã&¦O´ÌŽ,ØÔŒkâabw›½Î\ÚŒîýåÃéÅïG=˜ðl9¿NÄ;p øXdð·:9²?ýshÀs›áÚ‚ç5ð>Ÿ˜ñü&ŸWû‰”sKWûøW¤+([(ý¾zk€šÔ•¤\‹8½ÁGhÓbžˆSƒpØä§æt‰DŒrŒc…U¬µaðÕø`¬$ ˆÙ<‘K¦3¡ÉV3rREBu¯—ëÐC’ÝÌçR~$“ÂÊ«ý‘LGñ}‘_d&Æp™óÿ5hrMa.¼¾’y6]"ȱTq?E’gˆb¤) ÅåzŽgHW$·J»|"@‰F7ü3¥Fè66²îMVpp¬ |(S-ކà×ó¦š5% ó[:&KdÞ½ãÉBfÌ*ûÌùá°UæGŠyØ«Ù4‚è;²ísÅÎûÏÖ²ECŒ’½qgpÜÀbÄ!¶‡ý^!yGNÇcô%«å[Í‹ÖØ–Cô}T×ý –ÈP Jé"VâAŒ0•0丘¸¼èÁíBà‹§༞\¤Hz²ÔŽ8t<Ó.O—ÖN°Ð ƒ- KKŽ D×˧\p)E@JlÊ*ç¿ÉTì ›q+ô Úztoe‰úØ×iÝ–>ÇÙó¨m1°0 ‚*Íñ8J2¹ê¶›]ÝÄ9E¨«;^s·KZbE„Œ½»ÆÃ„y!ތϻOcúöK1#ù $æä !çxæÏ †ÞKQËÃz °Ü_@F\`^]ÉøðTýùºµÇ^ÔHUÃ}ÌðZ÷7?Â}‹x¨Ï<ƒl]o[5Úøõö„<—ÝT,ïñþÑåÊW¦ø-(F,WÓE}“'=<0¶×2åºhu]“ØÄ‹4ò¶ÖØ¿èü m½  endstream endobj 949 0 obj [ 948 0 R 950 0 R 951 0 R 952 0 R 953 0 R ] endobj 947 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 949 0 R /Contents 954 0 R >> endobj 955 0 obj 1300 endobj 957 0 obj << /Length 958 0 R /Filter /FlateDecode >> stream xœÅX[OÛH~ϯ8 „ÝñÝ®´•`º¥rI·B„‡Iqí×eý_é’âAá;–³C.‘m:ËÆ…&㬾ýð‰œ;ÏÜ5÷¯ªS‘Ô·7&ÝRjà6¼Pb—_ºŠgñ×ïGEûO:|béÜÐ8ÄÊÏõ6èËCoi_P~Wœ¥)—ÊiQdYMìjg|yÂïíóÅ9ÏçŠöf à¾Äû>¢Y® ¸àcø=CÀ“9+ ͧ+b;M¸œ~LÒ¥Ú`^Íò lÖU`ŠçIû8Ódš¼´¡}’²Æ1ÛßQ 1‹ŸÜNÒŽ û×t–•Û.‹yŒëÕ,ÇU‘ÑWŽEû6§QáØK“<{šãîŽEy†6åûib¬z ÛÌ‘mlÁqÉш§K’¶¦H`6‘}Q¶Ý„m!þ»Yʬ%aRñ]–Ä<¬²'í_ñlÉiœP¯èT¦tT‡ˆ˜&þ4¦<ªi@F¿äO<§UAHû_ ù„§K}(󹪱©{KUÉ çIÆFí¥rV}WD¤| ØžŠ{t>IRžÕ„§|A%M*TÒ[ò¹TÓþB.UÚ…‡jΣI@ÁùrÄ#SÄÊØV†yE¹"Ÿ©" 6è dVL(ÂXêÑ’w~8³ð-F7ÅñlÔ¾Z|õwtÛ°Ï'–ô¼Å †ÓÑñËþŠÿ€ 'FôH =ŒiÎ^X LzC>fÀþfC¬;‰ßx„áöº ’·1ÍíÂ8‹‘h.ž¶!Íé€fìøh<×_oÂ5‚FÇE,„Á|[®xlÔz¸Lb¦W¾(_·þ«iuÝ endstream endobj 956 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Contents 957 0 R >> endobj 958 0 obj 1208 endobj 960 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 558.028 150.0 567.028 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 882 0 R /H /I >> endobj 962 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 546.028 168.0 555.028 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 911 0 R /H /I >> endobj 963 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 534.028 186.0 543.028 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 920 0 R /H /I >> endobj 964 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 522.028 144.0 531.028 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 915 0 R /H /I >> endobj 965 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 510.028 156.0 519.028 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 909 0 R /H /I >> endobj 966 0 obj << /Length 967 0 R /Filter /FlateDecode >> stream xœÅVK“£6¾ó+ú¸[µI<ÇIj’Jj“Š3N¥R[{A¶IyÈîì¯O 1cðf.“™-©õõãSwûÑ£@ðß·ž1ÈkïqØ£À„ɰ'@£€ÅPà ÇPY­‰Àž%ü8%Žð‡×x~ð>|ÄÃ^øä‘9\ùÁÛLìÛòêö ¼o·Þ7ßÇ@ l÷cŠ¢4`<˲”§!Ëìƒm Þü|÷«¿ùýþ·?ß~„íOÞýö"’²ÿ!’Í…È&g<˜qÜßÝî8 {T é¾Õ‰Î9÷]uŠŒ>‘©K—ô¾ªñuf¹½HI^pJ£l•ÍWÎÚ‘Öö9ž(›BèEX=¹|ÊÅtÿ9—'SªF ti:aeíÂ\|òfI„Nˆ÷`Žäg™wö6(·ñ°ylŸ ’¢Ð`ˆæ dÛªV¿CÙ‰½úÓI‚~¬üB±Zúî¨Ô ËúVÉ"pNM]IèÌ•»ÞâRxãÎK´r–{s+¦]wÚŒ«ÝDÛù#‹q§œ"'ªÏYÄÎÒÈbÄ=O"~…êÌ©3~ï—>É|•;PLã,£Œ^ÃL<ԣܨI`b[™«CS~»jm·³n\§ž‡s§÷P•Ú¼k@ÀÜ€b™þGæFµ–ý¢×lÊjØ,^"6Ä&;òêV=­NXþ¥ª>ª®*ÎËݨ<áÔm”#ê ±8ïÀ‚ÇÿÄ0F˜”лúÌè#b”ûRê1ÄãAÓÕ;¹˜YÉZ6F_'™>3fI±¨ºü"Ÿ«¸•º« hil5å~/[ă}«jTHao;xðFóÁHc4–q:|î*­ÎmuìjÖÁ˜‘km}[Ëæ©#Wc·ï7‹MÚâ%áKñ å߆äñK!OmÙ˜¯ ¦ü¥¨•R§U¸,{)œÆg“› àWæ O1!ÖBð‹2òæa ¹Ë' ‡+[û WË-I‚HHâ…»î™öå¶n•bIÜÀ€¿åÓ'Õ ÚCg‹Æ¾xqv)¹nQQ[ÿ”/À}÷'àª/,ÁË6ç,YÊŽS#ã4XO‰ÍbÊf7kq𾮥4¶pÏ›«ºÆ.òViÝ—ÿ¾kòáçíj÷¾ _µ%¦¦×P‹¦> endobj 967 0 obj 900 endobj 970 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 709.5 168.0 718.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 969 0 R /H /I >> endobj 973 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 697.5 282.0 706.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 972 0 R /H /I >> endobj 974 0 obj << /Length 975 0 R /Filter /FlateDecode >> stream xœÅTÉnÂ0½û+æØâŽí$NŽ,]A RˆC ´ &D@¤öó;©d=ôBƒ¢ýÞ¼Yž @úY™Ñ¾„eÌöyL€– Ü<ä¸ m.ˆ!÷ˆèVÑ‘'Œ¹DÎ^ÙŽ!<²ù‚W€øbX¥ûÏØ¤?;Á«çGø`Ý€Ý=8 ‚÷K‹l‚¢ƒ(PƒÇ•ô³GBÃü¦Óï[Á´3šuzÖí‚— L ®l›®*ò±‚ žÇ#k:»ÞÀz}”Z¡„ü‡VLJh´Ô¼²$ôÚ\™E QvåóË­a5®gl«(¼h¢¤ò~\5yûjè ({¥á W¶NóÊ]« ²Ž%$V+Ž®KLžß¬åTmAMÃH)ëT°=B'Œ[ÃÐÿŠ+H,º¢î g“a{>a©ƒŽhJ¼þN×»#Éç…þMؾµC endstream endobj 971 0 obj [ 970 0 R 973 0 R ] endobj 968 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 971 0 R /Contents 974 0 R >> endobj 975 0 obj 413 endobj 977 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 709.5 295.65 718.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 452 0 R /H /I >> endobj 979 0 obj << /Type /Annot /Subtype /Link /Rect [ 529.999 709.5 539.999 718.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 452 0 R /H /I >> endobj 980 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 697.5 342.86 706.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 481 0 R /H /I >> endobj 981 0 obj << /Type /Annot /Subtype /Link /Rect [ 529.997 697.5 539.997 706.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 481 0 R /H /I >> endobj 982 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 685.5 345.64 694.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 484 0 R /H /I >> endobj 983 0 obj << /Type /Annot /Subtype /Link /Rect [ 529.996 685.5 539.996 694.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 484 0 R /H /I >> endobj 984 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 673.5 332.32 682.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 471 0 R /H /I >> endobj 985 0 obj << /Type /Annot /Subtype /Link /Rect [ 529.996 673.5 539.996 682.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 471 0 R /H /I >> endobj 986 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 661.5 317.31 670.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 465 0 R /H /I >> endobj 987 0 obj << /Type /Annot /Subtype /Link /Rect [ 529.997 661.5 539.997 670.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 465 0 R /H /I >> endobj 988 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 649.5 162.89 658.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 560 0 R /H /I >> endobj 989 0 obj << /Type /Annot /Subtype /Link /Rect [ 529.997 649.5 539.997 658.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 560 0 R /H /I >> endobj 990 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 637.5 226.78 646.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 563 0 R /H /I >> endobj 991 0 obj << /Type /Annot /Subtype /Link /Rect [ 529.998 637.5 539.998 646.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 563 0 R /H /I >> endobj 992 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 625.5 222.88 634.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 565 0 R /H /I >> endobj 993 0 obj << /Type /Annot /Subtype /Link /Rect [ 529.997 625.5 539.997 634.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 565 0 R /H /I >> endobj 994 0 obj << /Type /Action /S /GoTo /D [559 0 R /XYZ 72.0 720.0 null] >> endobj 995 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 613.5 219.0 622.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 994 0 R /H /I >> endobj 996 0 obj << /Type /Annot /Subtype /Link /Rect [ 529.998 613.5 539.998 622.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 994 0 R /H /I >> endobj 997 0 obj << /Type /Action /S /GoTo /D [569 0 R /XYZ 72.0 720.0 null] >> endobj 998 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 601.5 322.766 610.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 997 0 R /H /I >> endobj 999 0 obj << /Type /Annot /Subtype /Link /Rect [ 529.732 601.5 539.732 610.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 997 0 R /H /I >> endobj 1000 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 589.5 218.44 598.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 576 0 R /H /I >> endobj 1001 0 obj << /Type /Annot /Subtype /Link /Rect [ 529.998 589.5 539.998 598.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 576 0 R /H /I >> endobj 1002 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 577.5 206.22 586.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 587 0 R /H /I >> endobj 1003 0 obj << /Type /Annot /Subtype /Link /Rect [ 529.998 577.5 539.998 586.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 587 0 R /H /I >> endobj 1004 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 565.5 206.22 574.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 589 0 R /H /I >> endobj 1005 0 obj << /Type /Annot /Subtype /Link /Rect [ 529.998 565.5 539.998 574.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 589 0 R /H /I >> endobj 1006 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 553.5 222.33 562.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 597 0 R /H /I >> endobj 1007 0 obj << /Type /Annot /Subtype /Link /Rect [ 529.997 553.5 539.997 562.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 597 0 R /H /I >> endobj 1008 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 541.5 212.32 550.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 621 0 R /H /I >> endobj 1009 0 obj << /Type /Annot /Subtype /Link /Rect [ 529.998 541.5 539.998 550.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 621 0 R /H /I >> endobj 1010 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 529.5 200.1 538.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 632 0 R /H /I >> endobj 1011 0 obj << /Type /Annot /Subtype /Link /Rect [ 529.998 529.5 539.998 538.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 632 0 R /H /I >> endobj 1012 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 517.5 200.1 526.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 634 0 R /H /I >> endobj 1013 0 obj << /Type /Annot /Subtype /Link /Rect [ 529.998 517.5 539.998 526.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 634 0 R /H /I >> endobj 1014 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 505.5 216.21 514.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 642 0 R /H /I >> endobj 1015 0 obj << /Type /Annot /Subtype /Link /Rect [ 529.997 505.5 539.997 514.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 642 0 R /H /I >> endobj 1016 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 493.5 217.32 502.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 672 0 R /H /I >> endobj 1017 0 obj << /Type /Annot /Subtype /Link /Rect [ 529.997 493.5 539.997 502.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 672 0 R /H /I >> endobj 1018 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 481.5 205.1 490.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 675 0 R /H /I >> endobj 1019 0 obj << /Type /Annot /Subtype /Link /Rect [ 529.998 481.5 539.998 490.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 675 0 R /H /I >> endobj 1020 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 469.5 211.21 478.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 677 0 R /H /I >> endobj 1021 0 obj << /Type /Annot /Subtype /Link /Rect [ 529.997 469.5 539.997 478.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 677 0 R /H /I >> endobj 1022 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 457.5 221.21 466.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 685 0 R /H /I >> endobj 1023 0 obj << /Type /Annot /Subtype /Link /Rect [ 529.996 457.5 539.996 466.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 685 0 R /H /I >> endobj 1024 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 445.5 227.88 454.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 713 0 R /H /I >> endobj 1025 0 obj << /Type /Annot /Subtype /Link /Rect [ 529.996 445.5 539.996 454.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 713 0 R /H /I >> endobj 1026 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 433.5 257.88 442.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 716 0 R /H /I >> endobj 1027 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.998 433.5 539.998 442.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 716 0 R /H /I >> endobj 1028 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 421.5 229.55 430.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 727 0 R /H /I >> endobj 1029 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.997 421.5 539.997 430.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 727 0 R /H /I >> endobj 1030 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 409.5 238.44 418.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 740 0 R /H /I >> endobj 1031 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.998 409.5 539.998 418.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 740 0 R /H /I >> endobj 1032 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 397.5 226.22 406.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 748 0 R /H /I >> endobj 1033 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.998 397.5 539.998 406.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 748 0 R /H /I >> endobj 1034 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 385.5 226.22 394.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 750 0 R /H /I >> endobj 1035 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.998 385.5 539.998 394.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 750 0 R /H /I >> endobj 1036 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 373.5 242.33 382.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 768 0 R /H /I >> endobj 1037 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.997 373.5 539.997 382.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 768 0 R /H /I >> endobj 1038 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 361.5 224.55 370.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 752 0 R /H /I >> endobj 1039 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.998 361.5 539.998 370.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 752 0 R /H /I >> endobj 1040 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 349.5 226.21 358.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 771 0 R /H /I >> endobj 1041 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.998 349.5 539.998 358.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 771 0 R /H /I >> endobj 1042 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 337.5 266.21 346.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 788 0 R /H /I >> endobj 1043 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.997 337.5 539.997 346.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 788 0 R /H /I >> endobj 1045 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 325.5 253.99 334.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1044 0 R /H /I >> endobj 1046 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.997 325.5 539.997 334.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1044 0 R /H /I >> endobj 1047 0 obj << /Type /Action /S /GoTo /D [905 0 R /XYZ 72.0 720.0 null] >> endobj 1048 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 313.5 337.537 322.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1047 0 R /H /I >> endobj 1049 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.811 313.5 539.811 322.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1047 0 R /H /I >> endobj 1050 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 301.5 317.87 310.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 854 0 R /H /I >> endobj 1051 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.998 301.5 539.998 310.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 854 0 R /H /I >> endobj 1052 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 289.5 258.99 298.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 848 0 R /H /I >> endobj 1053 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.998 289.5 539.998 298.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 848 0 R /H /I >> endobj 1054 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 277.5 228.45 286.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 869 0 R /H /I >> endobj 1055 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.997 277.5 539.997 286.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 869 0 R /H /I >> endobj 1056 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 265.5 232.89 274.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 861 0 R /H /I >> endobj 1057 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.998 265.5 539.998 274.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 861 0 R /H /I >> endobj 1058 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 253.5 231.22 262.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 864 0 R /H /I >> endobj 1059 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.998 253.5 539.998 262.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 864 0 R /H /I >> endobj 1060 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 241.5 246.21 250.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 888 0 R /H /I >> endobj 1061 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.998 241.5 539.998 250.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 888 0 R /H /I >> endobj 1062 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 229.5 178.44 238.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 882 0 R /H /I >> endobj 1063 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.998 229.5 539.998 238.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 882 0 R /H /I >> endobj 1064 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 217.5 210.66 226.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 920 0 R /H /I >> endobj 1065 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.998 217.5 539.998 226.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 920 0 R /H /I >> endobj 1066 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 205.5 180.67 214.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 909 0 R /H /I >> endobj 1067 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.998 205.5 539.998 214.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 909 0 R /H /I >> endobj 1068 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 193.5 196.21 202.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 911 0 R /H /I >> endobj 1069 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.997 193.5 539.997 202.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 911 0 R /H /I >> endobj 1070 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 181.5 170.11 190.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 915 0 R /H /I >> endobj 1071 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.997 181.5 539.997 190.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 915 0 R /H /I >> endobj 1072 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 169.5 203.44 178.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 913 0 R /H /I >> endobj 1073 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.997 169.5 539.997 178.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 913 0 R /H /I >> endobj 1075 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 157.5 220.931 166.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1074 0 R /H /I >> endobj 1076 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.921 157.5 539.921 166.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1074 0 R /H /I >> endobj 1078 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 145.5 249.55 154.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1077 0 R /H /I >> endobj 1079 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.997 145.5 539.997 154.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1077 0 R /H /I >> endobj 1081 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 133.5 185.11 142.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1080 0 R /H /I >> endobj 1082 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.998 133.5 539.998 142.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1080 0 R /H /I >> endobj 1083 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 121.5 197.89 130.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 969 0 R /H /I >> endobj 1084 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.998 121.5 539.998 130.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 969 0 R /H /I >> endobj 1086 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 109.5 237.32 118.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1085 0 R /H /I >> endobj 1087 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.998 109.5 539.998 118.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1085 0 R /H /I >> endobj 1088 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 97.5 316.19 106.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 972 0 R /H /I >> endobj 1089 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.998 97.5 539.998 106.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 972 0 R /H /I >> endobj 1091 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 85.5 328.97 94.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1090 0 R /H /I >> endobj 1092 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.998 85.5 539.998 94.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1090 0 R /H /I >> endobj 1094 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 73.5 233.99 82.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1093 0 R /H /I >> endobj 1095 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.997 73.5 539.997 82.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1093 0 R /H /I >> endobj 1096 0 obj << /Length 1097 0 R /Filter /FlateDecode >> stream xœÅÝM“$×u é=v#µYå¸û9÷k Åf@ŠjÊZ½€IjÍ(hº[œùûã' ÒŸF\*¼·*ªž¬Ìð“ׯÿ_ìmçÿÞÕ?Æ:>ú§ýÅÿøþÇöÆñQôï¨õö|9ÚGÿúÑ÷ÿÞ>úcU?ù—ã‡;ÿñÿò}ô_~ñÝ/¶þó/þë;ÿã?´ þß_loºÛâo~ñ›Ÿüúõ_¶ÿð_ûè÷¿øå‡_üï¿:xûèÃÿñ(ÚËZÛ¶í}~4_âXõÇGþõ£ÿú7Ÿ|þÍo>ÿÛÿöчÿã\ÙÞ®ìýaÁG¿ý_ÿò?ÿ×ÿöÑþÓþù_^¾ÿp÷Ûýøÿá·ÿ›»×p~Œc¼¼ùÀ¸­Ž×;äõ'ªÿôÇï;ÿçëÏúú¯¯/îõŸ?û¢¶_ÓöÓ—tÿ1ñú‹ÿùÃáuä˾Ÿ[?_Öö2ïxÿðÿü¬éðŸÝgýÚáwu<|¨~úÙ7ÿòó÷ïÎðw_¿ÿøÓ÷_¿ûæ¾øðñï^‹^zñÒó\ëñÃýo?zwþ­þæaQ™õ×êØÿV½<Ä â8$nOˆs—8%·Mâ¸Ïÿõùø±ó/ˆû!q“xBþüóx÷þ‹kõùµ¿d‹öø“Õë<¿hôÇËÀó3íʾ홫ß6w‰ÄçgZˆ›Äâó3-Ä)ñ¸Çù™bŒ cÁØA0vŒãÁ8@0    LLLl"ØD°‰`Á.‚]»"8DpŠàÁ)‚K—.\ ˜æ‚¹`î ˜;æ‚y€` ˜æ!‚!‚!‚!‚)‚)‚)‚Më“ù¾oû6žÔ?ûöõ­öضuÌÇem<¾×>‰Î/Ð۶ϸ¯}ù;.£¾ãrþÙÛãÏv{¥ãé›íþ2ö¾mç—ÚÇeÏÞ@C}¾ƒ–ºQ=¥>ßDKT¨ë}´ÔAµXÖ[i¨w±¬7ÓR‹e½–Z,ë 5ÔA–A–A–A–I–I–I–,Y6²ìdÙɲ“e'ËA–ƒ,YN²œd9Ér‘å"ËE–K,ë¶ÔbYﵡÞŲÞmK-–õ~[j±¬wÜR“eeee’e’e’e#Ëzë}œAdÀÚ×·Þç/r<ù5Úz|ç}þ†ï£¯ßóá˯Ÿ¼ã~÷͇?¼ûö¯×Ûûsýˆ'?W½Ì~¼ï»Ï¯ §Ìš}›ËÞcž_A¤^RŸ_A¤nTO©Ï¯ R'ÕCêó+ˆÔd¹Èr‰elb›XÆ&–±‹eìb»Xž9©Ë8Ä2² ² ² ²L²L²L²ldÙȲ‘e#ËN–,;Y²d9Èr’å$ËI–“,Y.²\b™›Xæ&–¹‰eîb™»Xæ.–g(õ!–yˆedddd™d™d™d™dy^/̯Û[®¿ÿéõÂê¾?^/œ_&î£_}öùûË[b²½Ä¶Ö­?þL·yZ=^-äù±4ÏßÛù%íqÙÃ{ƶSTŸ¯oæ¶Í±.ÔçÅ‘ÔAu§zI]×DP7ª§ÔuMuRM–‹,Y.²\by»&‚Z,o×D×ë],o×DP‹åíšj±¼]AM–A–A–A–I–I–I–,Y6²ldÙɲ“e'ËA–ƒ,YN²œd9Ér’å"ËE–K,o×DP‹åíšèz½‹åíšj±¼]]¯±¼]AM–A–A–A–I–I–I–I–uMtœï—æÖàrãnûÒòEççÛûèÏG ü¹:ß>ÎY» b=æõRöóMÉã÷sV¾´º<Ûúx\öö÷»Äû¶QTwª—ÔûAu£zJ}ìT å~e”e;?¸¶¼RÕê%uT7ª§Ôm§:©Rw²ìdÙɲ“å ËA–ƒ,'YN²œd¹Èr‘å"Ë%–Ç&–Ç&–Ç&–Ç.–Ç.–Ç.–Ç!–uŒÔbYg¿@ddd™d™d™dÙȲ‘eûþ½Ï\ˆÄý¸I¿ŠHTwª—ÔçW©Õd¹Èr‘åËcËcËcËcËcËcËcËãËãËã Ë Ë Ë Ë Ë$Ë$Ë$ËF–,[Y¶µöc¿P÷ê ºS½¤Õê)õÜ©NªÉr‘å"ËE–K,k3¡ÔbY› ¡ÞŲ6J-–µ™Pj±¬Í„R“eeee’e’e’e#ËF–,Yv²ìdÙÉrå ËA–“,'YN²œd¹Èr‘åËÚL(µXÖfB¨w±¬Í„R‹em&„úËÚL(5YYYY&Y&Y&Y&YÖžŸ}_ëür#ï'Mk¶™Ëú“³ÐÖÛcjÒôåWï¿þøÃ³ASí+<ëœóqåíU­'‡!×|*Æ<_Ø“Uóƒó·p=®!®Ç!q—xA|^¢@Ü$žŸ×'‹àÁ%‚K—.¬ Kƒ`mWºï X›• ÁÚª1ÖF%ˆE0D0D0D0E0E0E°‰`Á&‚M»vì"8DpˆàÁ)‚S§N\"¸Dp`mO‚k{ÒõxÁÚž1Öö¤ëñ‚µ= b   LLLLl"ØD°‰`Á.‚]‡"8DpŠàÁ)‚K—.¬íIƒ`mO‚k{Ä XÛ“®ÇÖö$ˆE0D0D0D0D0E0E0E°‰`Dóäèú(çn+ÓòþäÈÏ}{{ÐϦ/¿~{žãÉ‚ÛΪz›öd²´½´½â\O>ΖÂònù¢¼n°¼Y>)¯Û,$OËåÓT§©NS¦ºLu™ê"Õc#Õc#Õc#Õc'Õc'Õc'Õc'Õã Õã Õã0Õ0Õ0Õ0Õ4Õ4Õ4Õ4ÕfªÍT›©vSí¦ÚMu˜ê0ÕaªÃT§©NS¦ºLu™ê"ÕØHµˆC9©Ö#q$ßIµŠC9©Öcq('Õz0ŽäaªaªaªaªiªiªiªÍT›©6Sí¦ÚMµ›j7ÕaªÃT‡©NS¦:Mu™ê2Õeª‹Të‰9”“j=3GòTë©9”“j=7‡rR­'çPnªaªaªaªiªiªiª6[º Ôf¾>€]fXw{¶Ž·Çbçühßßž÷ÙgŸ½ÜŽ˜Û눹_ýé»ú÷?üÛwßþñÇûôÛÿö'ÿß¿ü÷?|÷‡j~ü±Ï¿ýî÷úö÷ÿòãüãßüêÓO?ÿÇ¿}¸²Ù^Æ7ž<¾–×?¬‹·=®{¼€ê–/Êûay³|R>vËÓòAùÜ,7ÕiªÓT—©.S]¤Z[ ('ÕÚ^ ùNªµÅ€rR­m’¤Z[ (7Õ0Õ0Õ0Õ4Õ4Õ4Õ4ÕfªÍT›©vSí¦ÚMu˜ê0ÕaªÃT§©NS¦ºLu™ê"ÕÚœ@9©ÖÊIµ6)PNªµQAòƒTk³å¦¦¦¦¦š¦š¦š¦z^@õ}nûnWuý4Î7+{)Ÿ»åi¹©.S]¦ºLu‘jC9©Öñ0’ï¤ZÄPNªuD å¤Z‡ÄPnªaªaªaªiªiªiªÍT›©6Sm¦ÚMµ›j7ÕaªÃT‡©NS¦:Mušê2Õeª‹TëôÊIµÎ‘|'Õ:A†rR­3d$?HµN‘¡ÜTÃTÃTÃTÓTÓTÓTÓT_Ÿ;}c§Öý愇…#Ÿ ×òí¹3Ÿ~ýåWÏGkuòÏQéñlÝëËj/ãq´vÒÑWÝ…ô¸îa0qRÕê%u;¨nTO©ûNuRM–ƒ,Y²d9Ér’å$ËE–‹,—XÖPj±¬ùŸÔbYÓ?©Å²fPbY“?©É2È2È2È2È2É2É2ɲ‘e#ËúÙÛ6·~%ï›åay·|Q>Ë›å“ò¹[ž–›ê2ÕeªËT©Ö¸rR­qŸä;©Ö¸rR­qå¤Zã>ÊM5L5L5L5M5M5Mµ™j3ÕfªÍT»©vSí¦:Lu˜ê0ÕiªÓT§©NS]¦ºLu‘jû('Õ÷I¾“jû('Õ÷I~jû(7Õ0Õ0Õ0Õ4Õ4Õ4Õ4Õ÷–Ûj6W»÷=,ýɸ¯½=èóϾùð:îûæ/Îû^œ÷=¬û‹ó¾ uPÝ©^RÿtÞw¡nTO©:ï»P'Õd9Èrå ËA–“,'YN²\d¹Èr‰åݼïB-–wó¾ µXÞÍû.Ôby7ïûëõ!–wó¾ 5YYYYY&Y&Y&Y6²ldy7ïûëùݼïB–wËåwó¾ y³|R~7ﻧ妺Lu™ê2ÕEª÷ó¾ 9©ÞÏûþz¾“êý¼ïBNª÷ó¾ 9©ÞÏû.䦦¦¦š¦š¦š¦ÚLµ™j3ÕfªÝT»©vS¦:Lu˜ê4ÕiªÓT§©.S]¦ºHõ~Þw!'Õûyß_ÏwR½Ÿ÷]ÈIõ~Þ÷×óƒTïç}rS S S SMSMSMSMS½›÷Á\í~Þ÷°pÌ'ó¾þö„¢Û¨ïÝûß}ö͇oÞ}õ0wúÉñqíëKÛ^ö'G{ÇËŒm­óëÅ“…ó­nù¢¼ ’¼Y>)¯Ã‚$OËåuXä¦:Mušê2Õeª‹Të¬nÊIµÎê–|'Õ:«›rR­³º%?HµÎê¦ÜTÃTÃTÃTÓTÓTÓTÓT›©6Sm¦ÚMµ›j7ÕaªÃT‡©S¦:Mušê2Õeª‹Tc#Õ:«›rR­³º%ßIµÎꦜTë¬nÊIµÎê–Yø0—8?,(”Ÿ”‡åÝòEy;,o–OÊ»©vSí¦:Lu˜ê0ÕaªÓT§©NS]¦ºLu‘j)'Õ9RNª5r¤œTkä(ùAª5r¤ÜTÃTÃTÃTÃTÓTÓTÓT›©6Sm¥:·mmq%ï›åay·|Q>Ë›å“ò¹[ž–›ê2ÕeªËT©ÖÈ‘rR­‘£ä;©ÖÈ‘rR­‘#å¤Z#GÊM5L5L5L5M5M5Mµ™j3ÕfªÍT»©vSí¦:Lu˜ê0ÕiªÓT§©NS]¦ºLu‘j)'Õ9J¾“j)'Õ9J~j)7Õ0Õ0Õ0Õ4Õ4Õ4Õ4Õ9žÜ{ä³üç§{÷#LJ…óÉ£3êºþ¾º¥W#LJ£ô~2s|\vqæø¸ð/ίäƒòŸÎ¯äay·|Qþә㕼Y>)ï¦ÚMµ›ê0ÕaªÃT‡©NS¦:Mu™ê2ÕEªw3Ç+9©Þͯä¤z7s¼’“êÝÌñB~êÝÌñJnªaªaªaªaªiªiªiªÍT›©þtæx!ÿéÌñJ–wËå?9^É›å“òŸÎ¯äi¹©.S]¦ºLu‘êÝÌñJNªw3Ç ùNªw3Ç+9©Þͯä¤z7s¼’›j˜j˜j˜jšjšjšj3ÕfªÍT›©vSí¦ÚMu˜ê0ÕaªÓT§©NS¦ºLu™ê"Õ»™ã•œTïfŽòTïfŽWrR½›9^ÈR½›9^ÉM5L5L5L5M5M5M5Mõ§3G™îÝÍÎ'Ïï¨kãûªÆ?{œßùUó¨¹cû“¥¯¯ìx9žÜ¢<^Fìke' ç_›åay·|Q^çáJÞ,Ÿ”×y¸’§å¦:Mušê4ÕiªËT—©.R­Ã)'Õ:,PòTë°@ÊIµ ”ü Õ:,rS S S SMSMSMSMSm¦ÚLµ™j7ÕnªÝT‡©S¦:Lušê4ÕiªËT—©.RTë°@ÊIµ ”|'Õ:,rR­Ã)'Õ:,Pò0Õ0Õ0Õ0Õ4Õ4Õ4ÕfªÍT›©vSí¦ÚMµ›ê0ÕaªÃT§©NS¦ºLu™ê2ÕEªuX å¤Z‡J¾“jH9©Öa”“jH¹©†©†©†©¦©¦©Úl)m¶tÆöºÓ&^w‡>.œOž­Q{=î«ï üì‹Oßÿîa¢Ö~<-ðqåë Û_Ö“Q\ô¸¶-Û³…Ó¯Ýò´|P~;jò°¼[¾(¿µ y³ÜT§©NS¦ºLu™ê2ÕEªÇFªÇFªÇFªÇNªÇNªÇNªÇAªÇAªÇAªÇaªaªaªaªiªiªiªÍT›©Þã4×\G¿”/Êoq‚¼Y>)¿=Æ ò´|P~{Œäa¹©NS]¦ºLu‘jl¤©ÆFª±“jì¤;©ÆNªqj¤‡©†©†©†©¦©¦©¦©¦©6Sm¦ÚLµ›j7ÕnªÃT‡©S¦:Mušê4ÕeªËT©æFª¹‘jn¤š©æNª¹“j©æAªy˜j˜j˜j˜j˜jšjšjšêm¶6Öêg!3¬ûáÚÃÂõäIu3Ò}u;Ïïéhíûó͵Ë^_UöÌںߩokµœO>Lê~'Èë~'É›å“òºßIò´|P^÷;I–›j7ÕaªÃT‡©NS¦:Mu™ê2Õeª‹Tk*H9©ÖTPòTk*H9©ÖTrR­© 妦¦¦š¦š¦š¦ÚLµ™jÝïÔÏwÛÈKù¢¼îw’¼Y>)¯û$OËåu¿“äa¹©NS]¦ºLu‘jM)'Õš J¾“jM)'Õš J~jM)7Õ0Õ0Õ0Õ4Õ4Õ4Õ4ÕfªÍT›©vSí¦ÚMu˜ê0ÕaªÃT§©NS¦ºLu™ê"Õš RNª5¤œTk*H9©ÖTPòƒTk*H¹©†©†©†©†©¦©¦©¦©ÖTðüÌ·ïOÇv??»¿ýõaázò”:æç¾º¹w› ¾8tïüCýñîׇ•¯/,Ÿl¸;^F{²àÙÈîb8/†µõýZ˜WÃq1¬î׸ö«áºŽ«2ãªÌ¸*3¯ÊÌ«2óªÌº*³®Ê¬«2ë¢L Ð.†ejhv-Ü/ÊÔ ìbxQ¦†cË25»^•‰«2qU&®ÊäU™¼*“WeÚU™vU¦]•iWeúU™~U¦_•WeÆU™qUf^•™WeæU™yUf]•YWeÖE™=] /ÊÔ¸éZ¸_”©ÓÅð¢L•®…ÇE™%] ¯ÊÄU™¸*WeòªL^•É«2yU¦]•iWeÚU™~U¦_•éWeÆU™qUf\•WeæU™yUf^•YWeÖU™uQ¦†6Ë25¨¹^”©áÌÅð¢L d®…ÇE™Â\ ¯ÊÄU™¸*WeâªÌÕ@^äÕÀmœÒÆVw ÂÔâ~‹Õòõìùç%kÍÞÆku›£üüab?§<¬}}aÛK{¨Ô—†sõê‘O>Ž,šå“òúb!yZ>(¯/’‡åÝòEù4ÕiªÓT—©.S]¤Z'ùQNªuö>å¤Zw>SNªuö¾ä©ÖÆRÊM5L5L5L5L5M5M5Mµ™j3ÕfªÝT»©vSí¦:Lu˜ê0ÕiªÓT§©.S]¦ºLu‘j½O9©ÖÙû’ï¤ZgïSNªuö>å¤ZgïSnªaªaªaªiªiªiªÍT›©6Sm¦ÚMµ›j7ÕaªÃT‡©NS¦:Mušê2Õeª‹Tëì}ÊIµÎÞ—|'Õ:{ŸrR­³÷%?HµÎÞ§ÜTÃTÃTÃTÓTÓTÓTÓTkZ¶¶µFØPêu^Ö·íx6[ÏŽÞ?ßnßWøðõg¿üí‡÷ï>üÃW±æÜ¶-ç|²¶^Ùù™àÉÑûç— èûZ«íOÖ=NœË›å“òóKåiù üüDyXÞ-7ÕeªËT©Öñõ”“j_/ùNªu|=å¤ZÇ×K~j_O¹©†©†©†©¦©¦©¦©¦©6Sm¦ÚLµ›j7ÕnªÃT‡©S¦:Mušê4ÕeªËT©ÆFªu|=å¤ZÇ×K¾“j_O9©Öñõ”“j_/y˜j˜j˜j˜jšjšjšj3ÕfªÍT»©vSí¦ÚMu˜ê0ÕaªÓT§©NS]¦ºLu™ê"Õ:¾žrR­ãë%ßIµŽ¯§œTëøzÊIµŽ¯§ÜTÃTÃTÃTÓTÓTÓT›©ž_ÚžÛ6ΦFw㬇eëÙéõõ)ꮺÝJw?Óz¸¥nþt¨õð3ÔË›ýÙPk®—£ž‘™±ž¬{6þ ¼Y>%¯ñåiù |ß,Ë»å¤ZãÊIµÆ’‡©†©†©¦©¦©¦©¦©6Sm¦ÚLµ›j7ÕnªÃT‡©S¦:Mušê4ÕeªËT©ÖøƒrR­ñå¤ZãÊIµÆ’¤ZãÊM5L5L5L5L5M5M5Mµ™j3ÕfªÝT»©vSí¦:Lu˜ê0ÕiªÓT§©.S]¦ºLu‘j?('ÕH¾“j?('ÕPNª5þ ÜTÃTÃTÃTÓTÓT문hg!€)_¦ºLu‘jÝF9©Ö=a”“jÝF9©Ö=a’¤Z÷„QnªaªaªaªaªiªiªiªÍT›©6Sí¦ÚMµ›j7ÕaªÃT‡©NS¦:Mu™ê2Õeª‹Tëž0ÊIµî “|'Õº'ŒrR­{Â('Õº'ŒrS S S SMSMSMSm¦ÚLµ™j3ÕnªÝT»©S¦:Lušê4ÕiªÓT—©.S]¤Z÷„QNªuO˜ä;©Ö=a”“jÝ&ùAªuO妦¦¦š¦š¦š¦šë¥ÅX+cÊ\çû™Ó÷g"=¬Û·''L×›¡û쓯ßüáý»oÞÿæ·ï¿øäá6¯óíüù‡uþV2Ÿ,¾½¶ãéÌi½Ì~þDÛ>æ‹ò~XÞ,Ÿ”Ýò´|P>7ËÃrS¦ºLu™ê"Õ:ß™rR­³ž%ßIµÎ}¦œTë hÉR­ó )7Õ0Õ0Õ0Õ4Õ4Õ4Õ4ÕfªÍT›©vSí¦ÚMu˜ê0ÕaªÃT§©NS¦ºLu™ê"Õ:¥šrR­«)'Õ:½šrR­“¬%?HµNµ¦ÜTÃTÃTÃTÃTÓTÓTk’Sïö·ƒ¦%w»‡×íÛ“ã­ë[C÷Ù§_ùÕÏÎqj#êQGfÏ–Þ^Ùxò³ÚsÔë¢<ú“u£‚¾Y–wËåã°¼Y>)Ÿ»åi¹©.S]¦ºLu‘j£('ÕHI¾“j¤('ÕJQNª5–¢ÜTÃTÃTÃTÓTÓTÓT›©6Sm¥ºoÛjϾŒ<PIÞË›å“ò±[ž–ÊçfyXnªÓT—©.S]¤Z*ÊIµT’ï¤Z*ÊIµT’¤Z*ÊM5L5L5L5M5M5M5Mµ™j3ÕfªÝT»©vS¦:Lu˜ê0ÕiªÓT§©.S]¦ºHµT”“j ¨('ÕPQNª5 ’ü ÕPQnªaªaªaªaªiªiª5 :ƶÍíÙÛýŸÝ¨ÖíÛ“¥kÿï}v»½í‡ÕãÝm?P=¬½8¡zX÷—'Tò°¼[¾(¿›P]È›å“ò» Õ…<-7ÕeªËT—©.R½ŸP]ÈIõ~Bõ×óTï'TrR½ŸP]ÈIõ~Bu!7Õ0Õ0Õ0Õ4Õ4Õ4ÕfªÍTï&TòEùÝ„êBÞ,Ÿ”ßM¨.äiù ünBu!ËMušê2Õeª‹Tï'TrR½ŸPýõ|'Õû Õ…œTï'T=?Hõ~Bu!7Õ0Õ0Õ0Õ4Õ4Õ4Õ4ÕfªÍT›©vSí¦ÚMu˜ê0ÕaªÃT§©NS¦ºLu™ê"Õû Õ…œTï'TrR½ŸP]ÈIõ~Bõ×óƒTï'TrS S S S SMSMS½›P]ÝO¨ÖíÛ“3¢ë.ïûì‡áÔ»÷¿ûì›ß¼ûêaF²½DÔjÆ“å·W·?yÛíÑöçomµýÙ/û8Šé–/ÊëÑö’7Ë'åõh{ÉÓò!ùíÑö’“êíÑö’“êíÑö’“êíÑö¤z{´½ä¦¦¦¦¦š¦š¦š¦ÚLµ™j3ÕnªÝT»©vS¦:Lu˜ê4ÕiªÓT—©.S]¦ºHõöh{ÉIõöh{ÈwR½=Ú^rR½=Ú^rR½=Ú^rS S S SMSMSMSm¦ÚLµ™j3ÕnªÝT»©S¦:Lušê4ÕiªÓT—©.S]¤z{´½ä¤z{´=ä;©Þm/9©ÞmùAª·GÛKnªaªaªaªiªiª5Š™µ%gаãî\¢Çuûþä,ìúlÿ3£˜Ï?þæÃÛËúóWøóIØK¿'{…úKÊt{aˆu2ÞõºƃºQ=¥®Sñ Nª‡Ôu$ÔA5YN²\d¹Èr‰e=Mj±¬g³A½‹e=™Mj±¬ç²A}ˆe=•Mj² ² ² ²L²L²L²L²ldÙȲ•åßxøëy=TAò´|P^U<,ï–/Êë¡ ’7ËMu™ê2ÕEªõ(6ÊIµÅF9©Ö£Ø('Õz›ä©Ö£Ø(7Õ0Õ0Õ0Õ0Õ4Õ4Õ4ÕfªÍT›©vSí¦ÚMµ›ê0ÕaªÃT§©NS¦ºLu™ê2ÕEªõ(6ÊIµÅ&ùNªõ(6ÊIµÅF9©Ö£Ø(7Õ0Õ0Õ0Õ4Õ4ÕÛN ­û¾dÈs¿èaݾ?;»¿=séÏã§/Þÿîqü”/çåð¶õ±?Yú—oU›çïhþdÝãÔg³<,ï–/ÊëV5É›å“òºUMò´ÜT—©.S]¦ºHõv«šä¤z»U òTo·ªINª·[Õ$'ÕÛ­j’›j˜j˜j˜jšjšjšj3ÕfªÍT›©vSí¦ÚMu˜ê0ÕaªÓT§©NS¦ºLu™ê"ÕÛ­j’“êíV5ÈwR½Ýª&9©ÞnUƒü ÕÛ­j’›j˜j˜j˜jšjšjšjšj3ÕfªÍT»©vSí¦:Lu˜ê0ÕaªÓT§©NS]¦ºLu‘êíV5ÉIõv«šä¤z»UMrR½ÝªùAª·[Õ$7Õ0Õ0Õ0Õ0Õ4Õ4Õ»[Õ®îTëöýÙißóí™Kß¼ÿñ,¥w_}ùÍg>ûò‹‡ËûŸª~Šz…ç›ÛxT¯»åÙ®cåi¹©†©†©†©†©¦©¦©¦©6Sm¦ÚLµ›j7ÕnªÝT‡©S¦:Mušê4ÕeªËT—©.R­Û¦('ÕºmJòTë¶)ÊIµn›¢œTë¶)ÊM5L5L5L5M5M5Mµ™j3ÕfªÍT»©vSí¦:Lu˜ê0ÕiªÓT§©NS]¦ºLu‘jÝ6E9©ÖmS’ï¤Z·MQNªuÛ”ä©ÖmS”›j˜j˜j˜jšjšjšj •{nÛž]®Ñïï²zX·ïÏŽd^oÏÅùðõo¿ø¤žÿþéÇ>þåÇß<<7ì|—»êf-דå·W7žx3ÛËùÙÿçÖ½ýC¨Cc$_»åiù¼¦”‡åÝòEù~XNª5ýü Õš~PnªaªaªaªaªiªiªiªÍT›©¶RÍóSÔWò¾Y–wËåã°¼Y>)Ÿ»åi¹©.S]¦ºLu‘jM?('ÕÛ³D!ßIµ¦”“êí1’“jM?(7Õ0Õ0Õ0Õ4Õ4Õ4ÕfªÍT›©6Sí¦ÚMµ›ê0ÕaªÃT§©NS¦:Mu™ê2ÕEª5ý œTkú!ùNª5ý œTkú!ùAª5ý ÜTÃTÃTÃTÓTÓTÓTkúQ}ºM1®Ïî§ëöýíq¿9_ÿ²ÜeŸýýKý íüùõ§ïþéßÿðoß}ûÇ~äÓoÿýÛþý×ß~÷‡ÿûOü¶Š~ìóo¿ûýŸ¾ýý¿üðÿÿãßüêÓ_þûð.¿½´èkŽxò ~Xü°h¾´yþöZ?ž¬z|ó¾[ž–Êk.yXÞ-_”×$\òf9©ÖöjÊIµ¶WK¾“jm¯¦œTk{µä©ÖöjÊM5L5L5L5M5M5M5Mµ™j3ÕfªÝT»©vS¦:Lu˜ê0ÕiªÓT§©.S]¦ºHµ¶WSNªµ½šrR­íÕ”“jm¯–ü ÕÚ^M¹©†©†©†©†©¦©¦©ž_FßÎ"às]Ì}ß¶ìùdÕ~<9|òv%z—ý§O>þäïÞ¿ûðñ/?ÿî7¿}ÿõgï¿y÷éû_}üÛÏ?ü§·ïêÎßÖìëõTÍÇŸª^g]<¾Ç¿}v^)Åz²ìñÕê)õíä³ëuR=¤¾{v½ª;Õd9Ér’å$ËE–‹,—X¾vv½Ëףή×bùzÐÙõZ,_9»\bùzÈÙõš,ƒ,ƒ,ƒ,ƒ,“,“,“,Y6²ldÙɲ“e'ËN–ƒ,Y²œd9Ér’å"ËE–‹,—X¾ev½Ë׃Ì.×»X¾cv½Ë×CÌ®×bùz„Ùõš,ƒ,ƒ,ƒ,“,“,Ï÷öóüƒ9¯vº\ÜÝú¸n?ö'W/ÇÛ;HŸ\¼¼YV‡§ÿy[çãOpû¶ËyUóäÆÐíåüJ¶mOÝ· uv•Ôêu\%u£zJ][l Nª‡Ô‡XÖ‰UR‹eWueee’e’e’e#ËF–µ§&ÇZûÊKù¢¼öÔHÞ,Ÿ”מÉÓòAyí©‘<,7ÕiªËT—©.R­ï£RNªõ}TÉwR­ï£RNªõ}TÉR­ï£RnªaªaªaªiªiªiªiªÍT›©6Sí¦ÚMµ›ê0ÕaªÃT‡©NS¦:Mu™ê2ÕEªõ}TÊIµ¾J9©Ö÷Q)'Õú>ªä©Ö÷Q)7Õ0Õ0Õ0Õ0Õ4Õ4ÕÚbùzi“kýûYÄúýxrŽúmoé]öÙß¼ÿúû¯ßòåן>Œ!ÎK‹záê«=Y{;A«?;Ÿê¼ÆXûÙfÌ'ëfç5åÍòIùyAyZ>(?¯1(˻妺Lu™ê"ÕzNå¤ZOê“|'ÕzVå¤ZOë“ü Õz^妦¦¦š¦š¦š¦š¦ÚLµ™j3ÕnªÝT»©S¦:Lu˜ê4ÕiªÓT—©.S]¤Z»Y('ÕÚÏB9©ÖŽÊIµö´H~jíj¡ÜTÃTÃTÃTÃTÓTÓTÓT›©6Sm¦ÚMµ›j7ÕnªÃT‡©S¦:Mušê2ÕeªËT©Ö~ÊIµv¼H¾“jíy¡œTk× å¤Zû^(7Õ0Õ0Õ0Õ4Õ4Õº“ëüµz{–ÿì\çî®ÞÇuûñädôZsŸýö«OëD³Ÿ9Ÿíç\ëu#ÏÃÚÛKËg;_ê; 1ÎW—ùdÝãPhP^ßi<,ï–/Êë; ’7Ë'åõÉMu‘êíd8ÉIõv2œä¤z;NrR½ ùAª·“á$7Õ0Õ0Õ0Õ0Õ4Õ4Õ4ÕfªÍTëd¸˜Û~Œ+u uPÝ©^RסpP7ª§Ôu"ÔI5Y.²\d¹Èr‰åí(8¨ÅòvÜõzËÛ1pP‹åí8¨ÅòvÔdddd™d™d™dÙȲ‘e#ËF–,;Yv²d9Èrå$ËI–“,'Y.²\d¹ÄòvÒÔby;çíz½‹åí”7¨ÅòvÆÛõúËÛ oP“eeee’e’e’eÍ€ò,Æ AËý¶£‡uûñä\ûìoÏyøôýçï~t~ú¯3çÎßɳµ·—Ö^òÉ èxé#Öjk"ÉwR­}D”“jí#’ü ÕÚGD¹©†©†©†©¦©¦©¦©¦©6Sm¦ZÔç³ýˆ+y=R[ò´|P^Ô–<,ï–/Êë‘Ú’7ËMu™ê2ÕEªµˆrR­}D”“jí#¢œTk‘ä©Ö>"ÊM5L5L5L5L5M5M5Mµ™j3ÕfªÝT»©vSí¦:Lu˜ê0ÕiªÓT§©.S]¦ºLu‘jí#¢œTk‘ä;©Ö>"ÊIµöQNªµˆrS S S SMSMS½ÍrÛz4ÔÜÏÖíÇÛ§Ô i¼=mçýïÞòÛïß}òå¯ýñŸ>¨œÈçkû“Å·×¶½C¤š¬ìûí¼Ð'ëžNV$Ë»å‹òš¬HÞ,Ÿ’ß&+’§å¤z›¬HNª·ÉŠä¤z›¬HNª·É äaªaªaªiªiªiªiªÍT›©6Sí¦ÚMµ›ê0ÕaªÃT‡©NS¦:Mu™ê2ÕEª·ÉŠä¤z›¬HNª·ÉŠä¤z›¬@~êm²"¹©†©†©†©†©¦©¦©¦©6Sm¦ÚLµ›j7ÕnªÝT‡©S¦:Mušê4ÕeªËT—©.R½MV$'ÕÛdòTo“ÉIõ6Y‘œTo“ÉM5L5L5L5M5Mµ&+«oÛ ^ÜVÖíñìé*óíÑAu&ñ?¼½šßê( mÛŽÚÝÿ°¤^Ñ^WÁó”óRzm­þlÝÃÐàü9¤îT/©ÏËh©Õó¬OÝÜâJ~^DSž–Ês³<,ï–/Êë!=’7ËMµ›j7ÕnªÃT‡©S¦:Mušê4ÕeªËT©Ö Ž”“jÝàH9©Ö Ž”“jÝà(ùAªuƒ#妦¦¦¦š¦š¦š¦ÚLµ™j=Çç|K0çWò¾Y–wËåã°¼Y>)¯çùHž–›ê2ÕeªËT©ÖýŽ”“jÝñ(ùNªuÏ#å¤Zw=RNªuß#妦¦¦š¦š¦š¦ÚLµ™j3ÕfªÝT»©vS¦:Lu˜ê4ÕiªÓT§©.S]¦ºHµnˆ¤œTë–HÉwRÍTs'ÕÜI5R̓Tó0Õ0Õ0Õ0Õ4Õ4Õ4ÕzLGÿab Ïû!ìÃÂ=žÌÞ¶·‡i}õõg_|x÷t[ƒêó2d‹ÞŸ,¼½°ó­ÛãÓëöóâkŸy¾¶öláãp­Y>)?/¾(OËåçÅåay·|Q>Lu˜ê0ÕiªÓT§©.S]¦ºLu‘j=‘rR­g"J¾“j=‘rR­ç"RNªõdDÊM5L5L5L5M5M5Mµ™j3ÕfªÍT»©vSí¦:Lu˜ê0ÕiªÓT§©NS]¦ºLu‘j=#‘rR­g$J¾“j=#‘rR­g$J~j=#‘rS S S SMSMSMSMSm¦ÚLµ™j7ÕnªÝT‡©S¦:Lušê4ÕiªËT—©.R­g$RNªõŒDÊIµž‘H9©Ö3%?Hµž‘H¹©†©†©†©†©Úl)m¶T³¸Çë#eäu7‹{\¸G{2‹»­½mûØÖköÍûÏßòáí}íîëüéöñdÍë|ðxvTýù£ÇùšVoÏ~±‡ÁÁù€òIùù€ò´|P~þ8ßoÛù—þR–wËåyXÞ,Ÿ”·Ýò´|PÞMµ›j7ÕnªÃT‡©S¦:Mušê2ÕeªËT©Öp•rR­áªä;©Öp•rR­á*å¤ZÃUÊM5L5L5L5M5M5Mµ™j3ÕfªÍT»©vSí¦:Lu˜ê0ÕiªÓT§©NS]¦ºLu‘j W)'Õ®J¾“j W)'Õ®J~j W)7Õ0Õ0Õ0Õ4Õ4Õ4Õ4ÕfªÍT›©vSí¦ÚMu˜ê0ÕaªÃT§©NS¦ºLu™ê"Õ®RNª5\¥œTs'ÕÜI5wR̓Tó Õýòù.ÇúhØêA Û|²êuä;ž=âü¸óû‡›>.|6s¤<,ï–/ÊÏ Ê›å“ò¶[ž–›j7ÕnªÝT»©S¦:Lušê4ÕiªËT—©.S]¤Z3GÊIµfŽ’ï¤Z3GÊIµfŽ”“jÍ)7Õ0Õ0Õ0Õ4Õ4Õ4ÕfªÍT›©6Sí¦ÚMµ›ê0ÕaªÃT§©NS¦:Mu™ê2ÕEª5s¤œTkæ(ùNª5s¤œTkæ(ùAª5s¤ÜTÃTÃTÃTÓTÓTÓTÓT›©6Sm¦ÚMµ›j7ÕaªÃT‡©S¦:Mušê2Õeª‹TkæH9©ÖÌ‘rR­™#å¤Z3GÉR­™#å¦j³¥´ÙRÚl)m¶”6[J›-Ý6tñýˆ¦{ßÏ·mÏ~=ŸÝ\ýMöù—_~õ¦«ûqêq![ߟ,x‚ögãÆz#7ο¿GÍ)>L êœäƒòz#'yXÞ-_”×9É›å“ò0Õ0Õ0Õ4Õ4Õ4Õ4ÕfªÍT›©vSí¦ÚMu˜ê0ÕaªÃT§©NS¦ºLu™ê"Õ:r“rR­#7)'Õ:r“rR­#7%?HµŽÜ¤ÜTÃTÃTÃTÃTÓTÓTÓT›©6S­oŽX³Ïgïú±›åay·|Q^ß$”¼Y>)¯oJž–›ê2ÕeªËT©Ö‘›”“j¹)ùNªuä&å¤ZGnRNªuä&妦¦¦š¦š¦š¦ÚLµ™j3ÕfªÝT»©vS¦:Lu˜ê4ÕiªÓT§©.S]¦ºH57RÍTs#ÕÜI5wRÍTs'ÕÉO ÊÃònù¢¼À$o–OÊûn¹©vS¦:Lu˜ê0ÕiªÓT§©.S]¦ºHµæ|”“jÍù('ÕšóQNª5ç“ü ÕšóQnªaªaªaªaªiªiªiªÍT›©¶R]Û}\ÉûfyXÞ-_”Ãòfù¤|妺Lu™ê2ÕEª5磜TkÎ'ùNª5磜TkÎG9©ÖœrS S S SMSMSMSm¦ÚLµ™j3ÕnªÝT»©S¦:Lušê4ÕiªÓT—©.S]¤Zs>ÊIµæ|’ï¤Zs>ÊIµæ|’¤Zs>ÊM5L5L5L5M5Mµ¶sæ8ß¿oj÷s¾‡…{¾½…<Ïì|;ŸýýËí‰èÇËøèo>üÏo¿û_ßþÓ¿ÿáß¾ûñÿîÛïþùøî÷3®4ê&óÑŸü´?®2ìŠ6«ÝŸ¬{6ì¢|RÞwËÓòAùØ,Ë»å‹òiªÓT§©.S]¦ºHµ†]”“j »('ÕvQNª5ì’ü ÕvQnªaªaªaªaªiªiªiªÍT›©6Sí¦ÚMµ›j7ÕaªÃT‡©NS¦:Mu™ê2Õeª‹TkØE9©Ö°KòTkØE9©Ö°‹rR­a妦¦¦š¦š¦š¦ÚLµ™j3ÕfªÝT»©vS¦:Lu˜ê4ÕiªÓT§©.S]¦ºHµ†]”“j »$ßIµ†]”“j »$?Hµ†]”›j˜j˜j˜jšjšjšjÍÆÖù—dn)C¦Ûhì¼Øk­'ëö¶½YP[àÆÃ£k>|üõ‡w¾þø‹o>þäÃg_~ñ0#/­Õäkr÷°¼^Ý|²®&ÿÞ@÷°êqö–wËå5ù—¼Y>%?jò/yZ>(ßIõØIõØIõØIõ8Hõ8Hõ8L5L5L5L5M5M5M5Mµ™j3ÕfªÝT»©vS¦:Lu˜ê0ÕiªÓT§©.S]¦ºH56RTc#ÕØH5vRTc'Õ8H5RÃTÃTÃTÃTÃTÓTÓTÓT›©6Sm¦ÚMµ›j7ÕnªÃT‡©S¦:Mušê2ÕeªËT©æFª¹‘jn¤š;©æNª¹“j¤š©æAªy˜j˜j˜j˜jšjšêyuз¾Vö¸>Œ¸ßCô°joû“AÉ|{rÜ'_þúן=<ã÷¼ÄýñT¸‡5¯÷/î/ñä¿ýeG=TcË›å“ò:ÿLò´ÜT—©.S]¦ºHõvþ™ä¤z;ÿ òToçŸINª·óÏ$'ÕÛùg’›j˜j˜j˜jšjšjšj3ÕfªÍT›©vSí¦ÚMu˜ê0ÕaªÓT§©NS¦ºLu™ê"ÕÛùg’“êíü3ÈwR½&9©æNªyj¤z;ÿ ò0Õ0Õ0Õ4Õ4Õ:ÿl¶m[ãÙäíçç‡÷Ö}X¸·x2Ó\oIûúËÏ?ÿåÇŸüŸOæuØÊZ±ž¬z½[³?;þìüºŸ­VÖ|öaáãøî°¼Y>)?¿îSž–Êϯû”‡åÝrSí¦ÚMµ›ê0ÕaªÃT§©NS¦:Mu™ê2ÕEªµ+’rR­]‘’ï¤Z»")'ÕÚ)ùAªµ+’rS S S SMSMSMSMSm¦ÚLµ•êÚöœÏÞ<ÎívËÓòAùØ,Ë»å‹òyXÞ,7ÕeªËT©žÿÑrR­]‘”“j튤œTkW¤ä©Ö®HÊM5L5L5L5L5M5M5Mµ™j3ÕfªÝT»©vSí¦:Lu˜ê0ÕiªÓT§©.S]¦ºLu‘j튤œTkW¤ä;©Ö®HÊIµvERNªµ+’rS S S SMSMS½=+w®Ù:Mëîgˆ ÷Ögˆ}{{Ûg_üôîÑwo›[ã8¶mñlõíîÖx¶A²¾¿Óζ­ùdݳ9åiù ¼¾¿#yXÞ-_”×÷w$o–“jÍy('ÕšóH¾“jÍy('ÕšóH~jÍy(7Õ0Õ0Õ0Õ4Õ4Õ4Õ4ÕfªÍTkkp;ÖÚž~Þ6ç¡<-”×ö`ÉÃònù¢¼¶KÞ,7ÕeªËT©Öœ‡rR­9å¤ZsÊIµæ<’¤ZsÊM5L5L5L5L5M5M5Mµ™j3ÕfªÝT»©vSí¦:Lu˜ê0ÕiªÓT§©.S]¦ºLu‘jÍy('ÕšóH¾“jÍy('ÕšóPNª5ç¡ÜTÃTÃTÃTÓTÓTÏ«ƒÖÛëͲ0J¹›ó<®ÛÛÛ3ôëÕoÏûøÓOï=¯÷þû»/¿|»}ì|y/ûúþ¦ÞÇŸ¨^çùé{xÇíÍ­^ê³ðx}²Y–×!nû¶Ÿo­.å‹òÛ1š7Ë'å·c4!OËå·c4!ËMušê2Õeª‹Tc#ÕØH56RTc'ÕØI5vRƒTã Õ8L5L5L5L5M5M5M5Mµ™j3ÕfªÝT»©vS¦:Lu˜ê0ÕiªÓT§©.S]¦ºH57RÍTs#ÕÜH5wRÍTs'Õ)Ÿ»åiù |™ê2Õeª‹Tëî|ÊIµîΗ|'Õº;ŸrR­»ó)'Õº;ŸrS S S SMSMSMSm¦ÚLµ™j3ÕnªÝT»©S¦:Lušê4ÕiªÓT—©.S]¤ZwçSNªuw¾ä;©ÖÝù”“jÝ/ùAªuw>妦¦¦š¦š¦š¦Z—ó¼BÙW—7ò÷—ëöþä|Òžooùÿæý‡wÿö×ÏÏ)­GÔ·dZ®'koß:Ê—|² ·½œ‚纑OÖ½ý¸Ýœ yÝœ-yZ>(¯›³%Ë»å‹òº9[rS]¤z»9[rR½Ýœ ùNª·›³%'ÕÛÍÙ¤z»9[rS S S SMSMSMSMSm¦ÚLµnÎŽ8?×ç¼’×ÍÙ’§åƒòº9[ò°¼[¾(¯›³%o–›ê2Õeª‹Tc#ÕÛÍÙ’“êíælÈwR½Ýœ-9©ÞnΖœTo7gC¦¦¦¦š¦š¦š¦ÚLµ™j3ÕnªÝT»©vS¦:Lu˜ê4ÕiªÓT—©.S]¦ºHõvs¶ä¤z»9òTo7gKNª·›³%'ÕÛÍÙ’›j˜j˜j˜jšjšjmÚ­›îÖ2y¹{hÍ㺽Àãû¿øÍù¿ÿ"? $ endstream endobj 978 0 obj [ 977 0 R 979 0 R 980 0 R 981 0 R 982 0 R 983 0 R 984 0 R 985 0 R 986 0 R 987 0 R 988 0 R 989 0 R 990 0 R 991 0 R 992 0 R 993 0 R 995 0 R 996 0 R 998 0 R 999 0 R 1000 0 R 1001 0 R 1002 0 R 1003 0 R 1004 0 R 1005 0 R 1006 0 R 1007 0 R 1008 0 R 1009 0 R 1010 0 R 1011 0 R 1012 0 R 1013 0 R 1014 0 R 1015 0 R 1016 0 R 1017 0 R 1018 0 R 1019 0 R 1020 0 R 1021 0 R 1022 0 R 1023 0 R 1024 0 R 1025 0 R 1026 0 R 1027 0 R 1028 0 R 1029 0 R 1030 0 R 1031 0 R 1032 0 R 1033 0 R 1034 0 R 1035 0 R 1036 0 R 1037 0 R 1038 0 R 1039 0 R 1040 0 R 1041 0 R 1042 0 R 1043 0 R 1045 0 R 1046 0 R 1048 0 R 1049 0 R 1050 0 R 1051 0 R 1052 0 R 1053 0 R 1054 0 R 1055 0 R 1056 0 R 1057 0 R 1058 0 R 1059 0 R 1060 0 R 1061 0 R 1062 0 R 1063 0 R 1064 0 R 1065 0 R 1066 0 R 1067 0 R 1068 0 R 1069 0 R 1070 0 R 1071 0 R 1072 0 R 1073 0 R 1075 0 R 1076 0 R 1078 0 R 1079 0 R 1081 0 R 1082 0 R 1083 0 R 1084 0 R 1086 0 R 1087 0 R 1088 0 R 1089 0 R 1091 0 R 1092 0 R 1094 0 R 1095 0 R ] endobj 976 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 978 0 R /Contents 1096 0 R >> endobj 1097 0 obj 16100 endobj 1074 0 obj << /Type /Action /S /GoTo /D [1098 0 R /XYZ 72.0 720.0 null] >> endobj 1099 0 obj << /Type /Annot /Subtype /Link /Rect [ 138.0 584.841 222.0 593.841 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1093 0 R /H /I >> endobj 1101 0 obj << /Type /Annot /Subtype /Link /Rect [ 404.792 584.841 506.792 593.841 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1077 0 R /H /I >> endobj 1102 0 obj << /Length 1103 0 R /Filter /FlateDecode >> stream xœÅUMSÛ0½ûWè3D•äïcËôƒ”ÉàNÀAv”ăm- üû®,Yv§½Ñ$3Z­´Ú÷Þ®”'"ß…┡¢öž¬¢˜!?²®0B4À,D5²vˆ*½kb°Á‚Álc‹~yGÐWïöWˆ@À«Göëƒo¼å$¿^!À§ì¿ XîV!f1Þ«MíxÌAz©²²ÙÑœjLÎŒGA‘™ÅÂ}¿äm¼O™÷áKˆ(AÙzlÚXR‚–êCYnOhHNïQöÝûœTóU;(¤Îíøøˆ8éÁïТ>P"!$ £˜%1ØQdèe-o:^¨R6èoVUÙl ß…‚~˜& ä ‰=`[vèù8B'0ÙéJtE[æÂ­«­̲Q¢]óÂ9[ùR®Äj˜çoƒ5À‰öá°€bŸê‡ÀÎ/o–—G©°bY”¦!¨r;¤^Ëv0·VGŽ+žóÎáW£œÙ aiªiDöÒóª’¯½j‰Ã–|Eì$´ž¼’ÅCwfg…¬ëR©1ÀÓʪÝ9/† ¹C⚯„5»;µQ»ñüYIȵ8ä3à•ÂtGj^€åbË_JùÜâ¡6±~Ù¦µÞLc†!HÛ>ý!•8ZL ŒàT‹˜ÔD\hY†мSΡ¤3ÏA&Ù@«œ9×ц£ ÁQ¬. g2þ£ãài‰è¸(˜ƒ;¦ï;ߘ+±æÏ•×:Å[Õ¹i9rÜmãûø3»>¿¾ººÈœ«–}QÍän¬S5SÕg{0;¡¶âPÍ£dáÕœ ¾;Õ7#‚¶€«!™‹MOÄ̸³v)ßt£ƒá\šÝ™›eæ²8¥ðÆÓtŽ£y1É~üAôƒ¿äly·w=´¸A°·Ú2¨€ëï øýX•E©ª7<ùZzºÍ à endstream endobj 1100 0 obj [ 1099 0 R 1101 0 R ] endobj 1098 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 1100 0 R /Contents 1102 0 R >> endobj 1103 0 obj 717 endobj 1105 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 709.5 156.0 718.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1080 0 R /H /I >> endobj 1107 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 697.5 168.0 706.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 969 0 R /H /I >> endobj 1108 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 685.5 204.0 694.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1093 0 R /H /I >> endobj 1109 0 obj << /Length 1110 0 R /Filter /FlateDecode >> stream xœÅTMSƒ0½çWìQÄ$ÇÚQ§NÅ2ã¡Ó"*#¶àèÏ7ih ¤z©á]ÞÛ·°Fˆ|,u¹>ƒ¤@ëÖGÁe`‹ÖÅP3´6‡\½Õ1ØÎ’—~IðŒJDà-W2ø D~ÒmÁ vò«9{~ïè:BW·(èí0"›bÛ!òP¶™¯ƒ¨€åÅ,°¢§I°˜L£ÙC`=^® ºG7Q¯!›²h(ìÕ Eu™‹RoѶöI&R¡¼U¡½5«6uqú-Šj"Ý’ú*Ÿ5ù¸À®R‚½ž´”{£jžyj†}O¯×¾CØ!17©Š"kŽ6(é(;•oSåùKœ|Ž12çTÆ:m¬ø»©ŒJ÷$6P¹Ñžú2\‚`׳eÀçš,¨š´ÖG’Ëú<މ’Éó5"+­f—uœ4YUZ_;°±=ÔqL4d5İÃ#TýS5ÁÓù"œçóVΉK•ÌÄéo“–µ,wF¢?­=å endstream endobj 1106 0 obj [ 1105 0 R 1107 0 R 1108 0 R ] endobj 1104 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 1106 0 R /Contents 1109 0 R >> endobj 1110 0 obj 393 endobj 1112 0 obj << /Length 1113 0 R /Filter /FlateDecode >> stream xœÅR±nÂ0Ýý7¶CÌÙÆv2¶ªVPaÔ1 š¶H$JªöókcSÒ¬4îtö»{ï^„Ú¹ ÛœBæ T(IlH¹„B.aï^5~Êlðlò/¤ dµ¶—¯€ðEð²Ý¼ ic¾»Á«ÏGx'÷† &‚y;¯HŠ(jˆ©à‰û8˜V7‹±‰î–f>šÏfæv 扌MKŽ`üä¤-ÖRÍ5½0úˆ¾f+¾‘»ÚBô]}êÉùØK Ïœ°I©íñU‡÷Û«![Æ25ìuóÊ[ëéfÿêÀ¬±1Úÿ³%ëh®¢¼¦ç²Î*¯j0I.÷0ŒA$•²â€¨²:Ú|Öå¶Ìó]}‚vVÈïbaWÁNÕÁH¤ŠYÚ¨X<š.Òiÿ¼Øa­.Éþœ}×YQíÊ‚6,LÉΗU endstream endobj 1111 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Contents 1112 0 R >> endobj 1113 0 obj 341 endobj 1115 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 626.028 156.0 635.028 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1080 0 R /H /I >> endobj 1117 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 614.028 168.0 623.028 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 969 0 R /H /I >> endobj 1118 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 602.028 216.0 611.028 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1085 0 R /H /I >> endobj 1119 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 590.028 204.0 599.028 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1093 0 R /H /I >> endobj 1121 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 578.028 216.0 587.028 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1120 0 R /H /I >> endobj 1122 0 obj << /Length 1123 0 R /Filter /FlateDecode >> stream xœÅTËnÛ0¼ë+öØÄò!’ÒÑ Ò¢Eà±€‚hENÔÊ’-1Hú÷]š’_²Zø’Ú.HÍììÎ’›€ÅèpÈVÁ¦Ûc 9ÕmI,"\ ºXBé¾:xáâ?Âàî‚* ð5¸ÀÃG x è)Ý<fùÝ }÷üž‚Ïiðé‹F!]î[Ä%á\RJE 1ò–I>êæ;wm`¤Ë½«GCccœPvTÖÖ\Ýåkº~Ëòµ-êÊ ua_Œ‹[_æ™ÆD1ˆ„P¥:î(æÅ¢[0äMS7P/Áþ^çÐnÊðÑX³0mú£b =72ŸÞ+G¥PZÌô0MÏ4ªkI”F„ˆÄE UmÁ@OõâgžYÒŽwMi"‘(Ѭ/9ÏaR¶õnön`‡bA"ïÈÖäT(¼Y½Zöìp!_"/åkê²\˜ì×#£úRÊ¢ mcªÖdnBÂõ(5K.¥nsš[ÿ½ L°K‰_ û|¨ú€ú_÷DÅxÝðâØsMk›ïîÅ ·Ó—p"…N’HtÖšÆóŸ]&é¼Y³»/jBŠ¡xªØôÕÍ|v3ž1q`l•t×0uþfóªEÍä i³àòÊ endstream endobj 1116 0 obj [ 1115 0 R 1117 0 R 1118 0 R 1119 0 R 1121 0 R ] endobj 1114 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 1116 0 R /Contents 1122 0 R >> endobj 1123 0 obj 561 endobj 1125 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 614.028 222.0 623.028 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1077 0 R /H /I >> endobj 1127 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 602.028 168.0 611.028 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 969 0 R /H /I >> endobj 1128 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 590.028 216.0 599.028 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1085 0 R /H /I >> endobj 1129 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 578.028 282.0 587.028 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 972 0 R /H /I >> endobj 1130 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 566.028 204.0 575.028 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1093 0 R /H /I >> endobj 1131 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 554.028 216.0 563.028 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1120 0 R /H /I >> endobj 1132 0 obj << /Length 1133 0 R /Filter /FlateDecode >> stream xœÅTÁŽ›0½ósÜ=àÚc|ÜVÛª•¶Õj‘zXíÁ!NBKp^¥ýûÚ$K«\ÒäàÇàyófžñ> €í?t òm°ïb8…(éB,#Ê` fPº]#@{d¿É‚ |ªÃ§àùž\¶ ‡ŸÒµÉOÁ㨾{ƒ¯^Ã:xŸï>2 ²ÕqDŒ£8Ž…‰€ET¸…l Ï7¾=<|În_ ûÜg“6"BÿC ÖJN9:1¸ÍŽ|ÌF<‘{Uv³ïVÏê¡ç×YQø¨ %M½½jñy[¹K$¥C ‹gݼòÔÎŒtµ‡~" ÖØcL&mµæò®)ßÓý¯\íL¡+i© ó*n|›o &N!'‰¥N;Чbm³¸…PÀ¬: êZ×Ö«˜ß;ÕÁf_†KiäB6*o.úͽ «áD¥öc³íá³sA=ël”'È !å\œ§»ê)rBšVÚ X¨/4ôâ‡Ê žïtuUTëãÎÕû™´n*^÷x挜hìé¬Ä¦©–`g6ªV.Zi0µ¬™;C¡¨`Wëu­šõc™?%\ fK Nz‹•‚»²ÑÃñ?ž>«N0ûØž>q:n|v56FÖ& |ó»²ÔóK¹k]– ™ÿœ¥$âRÊ¢k w³Ô¹”Z.—î\o·… 7ZÏ7GÏ[™P¾íÙg‰ÙÅF ³™ññ_7‘ öBcÇiê¹¾j£þzóP’ q!âhH©Õ| þ@Ùò0 endstream endobj 1126 0 obj [ 1125 0 R 1127 0 R 1128 0 R 1129 0 R 1130 0 R 1131 0 R ] endobj 1124 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 1126 0 R /Contents 1132 0 R >> endobj 1133 0 obj 591 endobj 1135 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 614.028 222.0 623.028 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1077 0 R /H /I >> endobj 1137 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 602.028 156.0 611.028 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1080 0 R /H /I >> endobj 1138 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 590.028 216.0 599.028 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1085 0 R /H /I >> endobj 1139 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 578.028 294.0 587.028 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1090 0 R /H /I >> endobj 1140 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 566.028 204.0 575.028 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1093 0 R /H /I >> endobj 1141 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 554.028 216.0 563.028 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1120 0 R /H /I >> endobj 1142 0 obj << /Length 1143 0 R /Filter /FlateDecode >> stream xœÅUÁr›0½ó{L¨’@NÚ™6ÓŽÏôÉAƲMƒ‘ ʸýûJ`°C3¾¸öA¡}ûö­$vlÿ¡¸ m‚]3G€Sˆ’fŠ%@bDl Á ·ªh‹ìàY°†ŸA`ø<=Û— À6`àSºCðc0íåwoðÕócXw³àÃ'Ãly´ˆ„ÃGRQá~fxºùñýáánòñëí3̾÷³A!¡ÿ¡é@ƒm&§´øù9;ã‰Ü«¢q¿=«‡^œGEá£&Ü—4ìîU“7–»@‚Q:h© íæ•];k¤ËÝÕ±MíÆ$ƒ²ÍåMQ¾¦ûߙښ\—ÒRçæU:\û2ß0&N!'‰¥NŠÇ|e£k¸…PÀ, ªJW Ö˘?[ÕÀzW„ iä\Ö*ì/ÎÛÅ­ «áD¥ö¸awð0;Ô²ŽVAy‚œ )çâ<ÜeO‘Rw°Ô¦Ã²Cm¢nBϩ̠îyÒ¡½¬Ê¼\W.;Øzrxp®xÝ}ÏÝE3ÐØÒY‰õÁþB-ÀgÖªRn¶Ô`*YÖ2s …¼„m¥W•ªkÔÚ2¾K¸@̦œ´-V &E­»íÜ}V`(ö;ð°ûÄ©Ýøìr¬¬LØøæ¹²ÔóK¹3½Ùäf”ˆK ó²¯4ÜŽRGäRj¹X ¸+]s™½„k­_FóÄÑÅ~+ÊW£ßñ†]ÜÈ}nÖ#}|ï&Ô^höã§©çú¦úçÍCI‚XÄ…ˆ£.¤T¨—sü}ò… endstream endobj 1136 0 obj [ 1135 0 R 1137 0 R 1138 0 R 1139 0 R 1140 0 R 1141 0 R ] endobj 1134 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 1136 0 R /Contents 1142 0 R >> endobj 1143 0 obj 595 endobj 1145 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 709.5 294.0 718.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1090 0 R /H /I >> endobj 1147 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 697.5 216.0 706.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1120 0 R /H /I >> endobj 1148 0 obj << /Length 1149 0 R /Filter /FlateDecode >> stream xœÅTKo‚@¾ï¯˜c{`;»<ŽVû°U •¤㪭F¨$öçwè¢òC/BvØÙïûæ[&é6òEyf1Û{”Ó)¶l¤Å¥ 1¶ :U6äÑ¢E"c ï,aOl2%ç†uº_ð˜%ý܃W×Gøb÷!»{´A „ŸçYEQ —›ÒË/ a “›N¯g„oѸÓ5n§¾œaRqe ²±† ûþÈèúÃa?4ž}ÿUcÂJ!L!ÿ¡A%E™ÔF„‹›zv4QîÚÝ+VͪMœ^[ƒÂsLX©:Wo •r·ÒZá`k7¯\µF#«]´\=^§ ½z†Øøh>7²]”ì£Y¶Jc—n6Ñlm,Ót}1oRò¯2‡U¶,딘O4&L—¾0Qc³\®\“ž­éFi¶ØkŽ ò¡29:1¹Þå> endobj 1149 0 obj 417 endobj 1151 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 678.764 222.0 687.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1077 0 R /H /I >> endobj 1153 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 666.764 156.0 675.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1080 0 R /H /I >> endobj 1154 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 654.764 168.0 663.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 969 0 R /H /I >> endobj 1155 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 642.764 282.0 651.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 972 0 R /H /I >> endobj 1156 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 630.764 294.0 639.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1090 0 R /H /I >> endobj 1157 0 obj << /Length 1158 0 R /Filter /FlateDecode >> stream xœÅSKOÃ0 ¾çWø‡†<š&=Äc†Æ"í0íPºÂ&úÐÖJü}Ò&cm· MH#=ØrêÏþü9[D˜Ï« Äںɀ.$ >f2p¾€´þ«å°½gŒýÉ8k˜£xD‹¥¹\1 _ˆôášäš¶ê×7äâõ | [nPúý0"¦0¡ÄÆAaÎÂú0Ð,®æcýäé×Ñd6ºÓã—Éõô3º×Bœ² 4íô`D•LâžÔM6·1±@õUêTpÖ¢Z×6gí`SäÐi·ÔUù¢Å‡–u"%Xu¤¥A0¨æ…§v$d]û‡j„UfAi‡V#®t¤,§Y’À(-‹b\_'XÚ—ßà†ý9‘£õ/«hWyÕ.ÊË(®6E~rbÚgçBÇE–mª!<់·+Òô-Š?‡ƒà\ÄhµjS÷lÇÞº(‹Hõ×"{ý2¿mXP†’ºU˜URZ€OÂôJyˆa+û”<Á­šSô NÉVà endstream endobj 1152 0 obj [ 1151 0 R 1153 0 R 1154 0 R 1155 0 R 1156 0 R ] endobj 1150 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 1152 0 R /Contents 1157 0 R >> endobj 1158 0 obj 391 endobj 1160 0 obj << /Length 1161 0 R /Filter /FlateDecode >> stream xœÅTMs›0½ó+öhÏU ¡£»f9 (þ]»(Í!Ù8Oâ dãò%0p6ÐØ>äöTÏà{ —úk¸u¶…ïÎÝ=~L"àÙ¡‡á^ÁK窗ß~¡Ÿž¿Ï@0þ_\½UAqE´yE‹Ú‡ž:ý”7mkÖ:jmÖäêõ]R´ãD‡›ÒÐý¼ä~;ÓÐùúÍF!\u—VY £$àÚþ8„¸1Œï!†è˜ÇÕÔRh’ZÌð¾2RŸ!sÅt?w&1©Ù&YY’J PŽ‘µ_G(«x›Æ»ÔMÜâáIª/ÐúöŽêcjŒs¼{rãMä™)“]öXeÅö#fÕJkO4m ×Y µ–hTke§n±:-. °µ;+¸ˆýº Á¾½dÔë{¢'Ê#Úʬë땚*ÎòVo=Ô­‰  švF£Ô¬ê <¯h£!—ñÇÌð}ì”6Á—yQ•íÜêÆ†}Üž 2°£cx Rˆx3K cp•&F7?æ·îlN¦“å¼s£²­š¶võïÑt»htyÝí.~-Ýn3w¾çu–¬»mY;ÓKdïR»ÁNIW&í|i\ÅqÙ;…Óä`a÷èAÅ6n¶µÏ&1¤7þíÿ± ÷† endstream endobj 1159 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Contents 1160 0 R >> endobj 1161 0 obj 677 endobj 1163 0 obj << /Length 1164 0 R /Filter /FlateDecode >> stream xœÅVÛnã6}÷W Ї&ÁJåMÝÇɦ‚&V·qd›Ž…Ê’WRœÅþûEú[rò”Ê€E‰<3gÎ GüÞ¡@ðçè[ Œçïö…€÷í+Ï*\æÁìØƒT¯Ú°ÕoffðO'ë¸èÜÝãäž:d×\ tn¶üëòáþ·pÊþ7¯³°ÀÝÉMææ¾1†ôTje³wcÕ 9so%E6œH³(–îÇ9'ðÐ9:¿{@ DÓMÑH‰2©/Ñ/ï!ú³Óö²ùÁªí%Rû^ÇÃbbCB}VÜÀebºŽçÊÕ ƒI—øž^ÀÉYÿ¼û÷Uä ¢ÛËë çª}}=cd ¥aè†aRß32d,ØÈC8SÓø1­ UÙC5ƒ| ƒ›+(«"ÉJwAР.‘Ú°oL}‹‹$¥ë¨ÛÅò¥ëÑQ¹‚¦ ¢—ÅAÉ$Ç@š“ž'ÏÙãüm”1̱@‡Ì"/³¤JâjÇ+èqß)¾ëñ@JÁ­dÌóÞá2®ÔêœØ™*ÇE²¨’<;$•Òe ¨õw9…c`Üp¯GešW뇼iÅ8Ërý4QÓ$S“õóèe=\±‘»l¨‚>ÖŠl …e¢žœÚQkHLŒ¬I$eS4ÕLmÆX{œ÷SÆ w}%î“&‡¦°[Ùr.¡7‹÷Pñ˜ë,ϧ Æ–q1žÅE;)Á7)Ï6iäj#d¶U"³x©vƒnB”îXW \¨q2MÔä`2ýËz›b~ªæki÷;àø±Äڊ˺wîÛ{„¡Øø¥$ÄnÊþs<_¤ªl-HÍ8ð]‚„Iè ÛòŽRUÁï'ÓË“dÇ9 ‡Ç Ñc+}m ÐÎ뺆2$Úxœ²‡šH ¿×Õjx4b)kÀ"xd¡C[©­ä9ÍÆÖ‚-/n±Àw¥üü~ùcPaAÅÅÄ99½Z‚JðŸIWpzöãKƒ%W ¤Q¨¸RFÉi‘Ï­œ¿–: Á® Ÿ›…»A*]ƒŽzNʪtp‡î=Ȇp£ýu‚ìW…¾5mÁQŠáv‰GùRÁ8Ÿà_Œ;¤„¸Þ 5c¨ráD-ÓžÜszéã|>Ç$ÚÂÛÕ«wÛïF}ˆº§W},ƒ.|ëÞö¾vo‡GZñOp ÛO½×Ó+ÁmW¬WøœPfcìN§j¬ÉŸ¾Ç#x6>6{Üäsç(ÿ«²I “t³*‹¼¨ ½¥Rì‰>š"Ü÷÷ ¿ÕQV|;Ú6®êœ˜Ž8üÚ¿£•yœ»xÐ’hÐ~îJA7-óƒÊx+Blí(«=5æ™z»Ðs%æLg•jÿ£/OÝŒ†„^¸*Ql܉.ÊޕΆz®TVâñD—¦.Å–ažé©î_—îÖ ý¦óWM– endstream endobj 1162 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Contents 1163 0 R >> endobj 1164 0 obj 1129 endobj 369 0 obj << /Type /Action /S /GoTo /D [1165 0 R /XYZ 72.0 684.0 null] >> endobj 1167 0 obj << /Type /Annot /Subtype /Link /Rect [ 135.27 685.5 221.77 694.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1166 0 R /H /I >> endobj 1169 0 obj << /Length 1170 0 R /Filter /FlateDecode >> stream xœÅXÛnÛ8}÷WyÙˆUŠº§(ŠnÖÙM‘^ÒM±-:f£K"É5²_¿Ã‹DÊ¢Ý>uÓ™¡8‡Ã33ä0Oaø7å¿¢„ e1yRc.ŠòB5„Èõ )9@9Ÿe¤“à—œÂÝNÊ FN¾|…Â`°à]8a|3¹6Öç_ð/_£ûÉïóÉ‹‹¹ÍWš"8AŒ1vcÅŽGþCм@_ŽÏ«¢¨Ê›ë+4ß´UÍÒüä+š¿Ìæƒ-y.ù¶t=ð‘ÈÙ ¶°öäŒH þ)WqP¿%ª¥sò÷^§°ö ›. ãüKßâ(pø˜‚ïå/ælF¾öþÝøñ(O—U¾)Ê ßuBtÌʶê•vM{y¹fy¦µ¯¼£Ûu¥5Öhùï<ÍXÁêߌ±"-Ó{Z¿>"¤­Vy•¤å³È*j ¼­ºÒ궪´™>€î¸´­C¡«gjbs°1.ÔÑ^™·,ƒ:oÐe¹tŽ$Îkø/¨Å3âŠT¼¶¬]#O™gDzäw„Ý$ â@®Ã©å>5hwÅ×{«ŽAåÅI ‹FÝÌ®fçs´buÓþS¦*AŠèâÓ‡w¨cã)þ-þEÑ,’?·Í>ÍzG° ½êÀô˜6N¬°oÞÿ±k.ý}…Žäªb±ÃîÀ$Ž5§'#9»œÆ^âvdAÅt)êP–Ÿ¨:^l‡8ótó>Ü¦á š‚65rz€?ÏówÐ~†@á®…=Ï­h#ú¦ÒM ýMiƒ‚^é‡P?Qö˜xQâ„<!Þ*&ü(9Œ„÷Åþæ/â]-4pñ,‡»?H*‡pƒ(ò-ÆýâëjK¿Óº×·´³ª˪Õ27’TZ=g[³VWmÑl–z·òNkz}A—é¦1 µ3¼¹èÕ0i]ÜšR.RèÐS¦¬½$”Ä u×E€¡›ðëcAÛ-¥e¯›7Œ‘÷‘”eøa;§ÖÏccÁ—×”Õ½¦Î =SvŽRÞˆ6QÊ·T¯ž–&šVÒå’6–>ÀÇÞ`&¸Ÿü‰6àC ñVAk[S®6âí£TußK¥àÚøÖ¶5[lZÃZ6ê©–;ÎŒ™ÑX¨‹otÙ:zà²4-3Ó Ù=I93dh›ldAO5$ 6-/︚ ñ¾iòª•W;O\‘°]goôB'öáQáÐ8œÁ2ØÑ éØ!Cjˆn›ˆì™”x¹ê>wóÒ,S’êZ…AžW[ÞÜHo£[™o‘©Çê´«ñ¡ùŽ'Fÿ?Ø®ïl|âI+’5mÄõƒX ÷w×# ?x ñ÷_Úﺂ7_ ¹SÓf“·Î¡ûʉƒ½»8òõAþò%t®w\,”³¦µ¸øŒ»ã½MU€C‹Bg²aݲÓýnlÇÈÓ„œñt³Øyx¯5‚ßÂR¾Ñö7†o#NB­!Û§ðÌF:À “vá¥ì¾ü¡m8æïŒ?£K–ßܺ[xã¹!4ö¡g4Ü–^"^îò-•¿R<ä<’”¡ïÙwq¶*Umäµy#_(Rٚ˳fÏêË,£ek_µü­a§jÙ‚8¨h9ÄsÜÂ6¼‡Œ *:¡DÕ¼Å*RÖg”ÔÕ­>Š ë4yJyk ¤¥‰¬~t²¼û¤,އNé^Ú7ýˆ:¸ÆkÊ?àŒ·P³ûµþòGJÈÿd“. \³2ô¡Ò±ràL áía¹ÓyhüõôzòòLãP endstream endobj 1168 0 obj [ 1167 0 R ] endobj 1165 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 1168 0 R /Contents 1169 0 R >> endobj 1170 0 obj 1788 endobj 372 0 obj << /Type /Action /S /GoTo /D [1171 0 R /XYZ 72.0 674.262 null] >> endobj 1172 0 obj << /Type /Annot /Subtype /Link /Rect [ 136.94 675.762 220.94 684.762 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1166 0 R /H /I >> endobj 1174 0 obj << /Length 1175 0 R /Filter /FlateDecode >> stream xœÅËrÛ6ð®¯Àø{&b@|éÔÔ±3é¸q©Í!Î&! H($Õýú.> d›t&µÚ°ï]`—_f.Âð?W?Qâ¡4Ÿ}i×\yÈÛ¥ D.q¼å¨…$Ô)ð:~ô!6èý¬˜aôzöá#lfÁ~†Ù5ÄËÙ!_íà.£ÇÙϫًë¹­Öƒ‹|Ï bŒ±û(v|/QZåèÃù¥ÌsY,ïnÐjWË’Sqñ­~™]­Lò]ï0éî@käEÎQ°j_¯ÁŠf¤¶D‡öWsÕ VNÿŽ*…°©Òaœ¨ðñG>¬8ñAh]<Ê첓(*ÙãÆø$Må¶æ²@Èó/ YæTð¿X¶íS:x`=¸«XÖ#µìÁŒWôA çêÍglMw¢6ØmèW.we¿B‹)ì ¤Úç/®Ã“*$PP‡®F”á ”`GzZÀ†Q’ønxBÚKî}b7‰ÖôVL 1}íá#ŽUºa9­\#^lXÉkð`*hU±Ê9¥'žƒCu¿D‰¦_2ÛÚ’Û'!pØ#ä”ü>ÿÊÙ~ÞHõ‡Kâ &h-K”Ë’ökå•:NÇÌWöFð>˜ áñÏ%IúDs¹}øÄÒ]–¬¡ÕÄñ"¸_“@Ó¾•{ð;I , ´î‘=ëÁ6i4¢3Kù̘è1Ayf«ŸÛxU¹ñTélìÊÜÔ˜åôø ´ÛU=ÞßTÿÊÚCã¹æÂ-uè«T…rtŠì¶ˆ P>{rÐ{†Ö¼¬jT0È>¨ÛÖ*åªZnáE*Ã;i ‹8xúÜ ޅ¦f Ptîâž’¶D:lÍ…‰Ž&±‹C' A’D¡gÂþ¤ù4|‘Šê‹˜×íËê^mGÉSEAŒeñ¨m 3Q'+qQä(QI†ZÜýyãÓ…Î}Y¬K™ë=càxùÄØý…Eù8ùFn©Ì·´xê˜ÙËßs]'$.Æ!‰4ÛÕ†ÊdÏ…0óV_Õ$w» ù—£O;pšàŸ™ò!Ú7Å b‘„Ý]ÞÜ.[ÒÅ”³<8Cú„AÜ™ÿJKÔÚá¢ûóœ~fsHžš)ë-´¼ AtÄ u‹–n&×B&£„Û’UõY—I§u[~î¨×ÐB‘Ù ‡¤'k®Á¹¶ÿA3žóò̃Œ:- ;7¬à…>õ›Rr΄¢ý©’P(µ#ËG›ðØ£#qìÁóãcGœÄÃû–x<á”6ž…Ìð…_dÅÖ/o F0–5tl¶h2‘šhT ñt8™È¬É:&á„ërZÐGè i¿Iì;® O>ñÛ'ãêÓcè:¡i†kºs BpYY÷(5Hô%jœ4Èôs®á®/èö¸3–MšÑûÕS}käÃÛŒ=‹I¿ÿöêåêjþîêòöÝ«åüúÝí¯ó7o—«—o/¯ÆüÏ^©õ®H‡ôÀ·IpDmûZ !÷Õä[x±ÇÆI>…»m¦žÂ’¥›J¿†}¥õw¢­v‚ÿ OÏÊ3ð¾‡g÷ÞMgf :®ÄÇnÔeøËuݤ£ª‘I÷CV7N¨·¹ƒÓ -YÕãM2vÇzP'ís+붉>!¯¶,åkžR!q5¢GÆgM81äDB\b1ó¦Íˆ!˜ØO\ ±MUŒag3ÀêÓRwi"ƒ8<’³ÒLÔ<1>L†VS[éÊỊÒóÉÏN¥œÕ™uXÓèu°š—;„ë0M·P=XfdBÛ´0F+-Œf=¬½Þ²±ø†ÑCuêéÝ—,AÕ§ƒéa;-¹*§f(˜Ê7˜ž£\G6&Óéæb N`~ljg!î…÷¾Æi9(Ö4Т¿ƒôhÓ>1yÞ/ì&úû‘†á}ãÛÐI­—Àw¼ì±JHC—ùM#ßkÙ\­pÕÎ[¼ÏÀ¡ÍÃ>'¡“ ókYHwË=–«ŸUZѧig÷kº¿ò¯]Pc[è>£GXJõÃÙ6à=5¡G¯9ÌxƒRH¾Ócg«ì–æ¦îq‹‹`ì> endobj 1175 0 obj 1742 endobj 1177 0 obj << /Type /Action /S /GoTo /D [1162 0 R /XYZ 72.0 720.0 null] >> endobj 1178 0 obj << /Type /Annot /Subtype /Link /Rect [ 326.23 675.5 418.44 684.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1177 0 R /H /I >> endobj 1180 0 obj << /Type /Annot /Subtype /Link /Rect [ 332.23 651.5 424.44 660.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1177 0 R /H /I >> endobj 1181 0 obj << /Length 1182 0 R /Filter /FlateDecode >> stream xœÅZ[wÛ6~÷¯ÀcÜc±¼‹ò[ÚMºÞãfOÖîö!Î$Q6¨ðbWýõ;€E´¹ÍÉ&9Ñ ˆß ƒ!¿^ć¿ üY®B²9\|UmY†$JUS’’ ö„ˆ¢R`¯vüÈN@ìÉïüÂ'¿\|ú ·Äç 8œ¾»øØ›Ÿøß}~Ÿ<^ütñãû„>¹ßˆ¢ÔKƒÄ÷ƒ4#™…+ü’ûùôæoïÞ/þ}óî÷ÅÏ·oïî.?“û\¼»?[N„ÿ‡å|<ÓLº —ÞÀÐB:’mÐ"ÂG…²ú•£JR*'JùF'¿¯Ò¹¿ëänó.Q0ð½ḭ̀Á2rZó;£62$Îí^O2öÒætÌkrIbt³7»²Òt³Ï5½)‹öÀ5[ò¦ÔÌóžmöV©º(Íè±ö4w¿gfÖu¾§O¬l«^çSï©™÷)¯*¶ÝæF•¶füÑ:»´Ñïƒ qèp¸Þ®ˆE'eÃ.ôBbå±a%÷È=ÌýD ¶Åÿ[•Vùµvc'(ŠÑNÂFcíÆºÕM‹tjy(A„‚£ë"'EΛ=ÙìiE7M^‘Ë‹-iÍ(†Õƒ«Ô q¬d†ýa›ïh[4 ©ÑBüÃ`ˆ0˼8ö}?Œã±fZ‹Ú³î"€'NgÁó "üáÒ R:– íØùÖ…Û…‚,ñ–ŒCŽæN-‚UàëACŠ’?:ñsð?À‘JÅá7ôŸÐÿ²ÿ¬â¿æ?K¦ÿ(„¦èì2›>a8±áÜžF8÷=‰q¥™®,œפ/…‹!J¥£8.Vóâ#ãMþ˜Ïuðš=rØúJ˜Ðp¢uC¢p±fMMžÙ6w)øsCT7v1Ë Á¼}½+JÚ8‹æn1ܤ~ñqH^êöx,«öÁúDhQ-mèšÖ9YÓÍ—œoëÏ®E@¤Ÿ—Å`üÉUŒ³Së*‚ô›.#˜çƒkö8µ{26^DÓE„ó\¿å Réš‹†Ü9of‰æ—dû^@Þ, I¹¡»uê•JulÝîvlÃrÞ'ÓŠ0NÜ.ºþMYõQCž/Â3þÙSçPÖá:Dë«AÎá“{8´Dz¿# ^Vðr@h­N Jî>ÞÊ6è0‘'¦pµ —I—ÁxŠŸn~¹ùpï4j2/J<ƒÏLÛ3±Ûò­PÙS’Ô꧸î®×=DÛÔV9@:ï=à[Ã Š†cÜ*ðžIÔ =M“ÜFžièŽvdÏK? F«ÿùæ™ØË Å«,‰’ àŽUùîÛÇáeïRÇzÂq œÛ‚âU’ìZ¾A¢ÆÌQER®ÿ“o ` º¶¶3¯ —ó"šlVb‡ÛÊD³;ŶU~#í6±Þѵfå]Ò׿¢B³/[3å'#¦¼H0¸õ¦Ln‚P>\êFépu{î$x·7Å‘çûKÈ»ç»ÓDƒÌ÷“hé³ó¦×¨W:Ñžb•"¯\x"@–5 ·ï¬æå=Û¶ÓÎ:Ü/IàEÒ}¡Cp´#º±M·ªÝ4m%B¾hqZ+€œÅXËâ¿ÓÖ `+gIÖr*ÞÛø‚¯ÀW7¼¬¦ RïV½:­ëƒa7y]/^ö6Q$ˆÂyéÙº,áþ3a@û%JšŒê#p5Ê!ÀéQ&‹ÇNïί&´Ù8LWÞÒ}ȫƦrûT¸LÜbzÖ²z…Yæ8h‹/SNù©[PÏ+œÍàV#ãnÛÚ5:ªM…Ž.G^˜`Áüïås õ•iQç­dnY}4œLG ¿‘wɈ’½¢µÎŠg½~êèwßÓî­«g‡V'¸3´Ó€Q yÚ*†œ2»6“Là ÉÞ2k7´v*æCÜö" CAÉ1ß¿½½{7áQc ¬ù!´¯²ÛL`'!•f´vÔ0?aNÂÑT÷ÿúÍ­[˜„¢îh:³~û%?=—Õö=¹ÎÄ-ÚÌ,֧ú,fÖ´2}i‹.3 £«Ý• {©Vk‚²Xˆx®Xƒ/WXƒ·ÐP”îåë.Ö䇺ó6!phQ .ÊX‡þ@V9Ý Gjrî~í3³¨ú¢tW}_@ZJun§é*}®¼Â±BË›~³eQ3‹º´ªèij·O­I¿zI1dJp‘±¾A,Éþ:rú8–’Yš,UîÚîI›Èµ¼}¹S ß·Ha< üØ[ª ¨¢ëc¾a;&/˜ªM3ŠãôÐgåaí©ŠŠÓ/Á»}­µ w7`Åâûïþ¬¼)¯z<ëkáÆ/ZE^œÄ ’Ûõâ ã±0¦äû õµåe3mÓÔjòΦ¥î@ˆ¯PÆbIš˜’‘¤ÕkÃZ7ˆìV‘tI+È%ƒfö4w³{„f˜™­­s£‹¼ÔG’¾"ií)fÜþÂNšÞŸŽ9^õÏe8FY¡¯Ð“V9Ù”6¬ -ßæU½ÁjéèéÙ–…‹íÜ-;¹~*Ùv!òˆ‰Ul‘„µ'fA Mõ·¬l‘ÀJºËïÔ“Òˆ©Ê°äD^9–V¹b×§n(ßô„vV!iKÛôÌèøá·[ÓKz«¤;o›5ôÿ Xd›+%˜vA¾,ýÕ+­4Áp>G6e¼©Ý–²Nˆ^u•aIÉMuµZI©Jó2‡Ñl•átÊy#?ÔQÒ\“jãDçG±îº)ÿG«e¹D6É 9PÊ`gÅþ`‘"úcPÄ7ò;&ɈEÈ/–Dý¼a zWEù¬><-æ)ÅjÐu­òÞTêUϵnº†»àmQ\™¦cÅ´:-á^kËÙ×6?kÖŠp©I8Xªzuñðæ×b®vÝæáòŠ\ÿ™W厅å)Aß¾¦mS.ßTùLiéfóáe<Û‡G"/~˜…ÉX wcd鉈•4[¢c‰@§®YFúÀ‰ Ž§hq®$½ ¶½ÒÃÈ`1œU}Ä–×/Ng1j–Ö©^KÁQp8¶xìªò ŽŠébOC²­,#^O£½š’•çS¿XÖ÷‡ÔŸÓÆ"èx¥˜øÞ?¤ b:G^Ú½¯äÍÎÐÔÒ`W¦å†{>ãPi^Õ ¾ÿÓ¼0I(Ø+ºý¹öœnfÜ£š[÷zª$¥›²¬z ;R!H¨,èdg ‹/b:º+Úd˜ÄÊw¸H›2L†Š)­g:X}Î+SYy ¡NÖÞØ©¦DGªÐQˆŒh± B¢^2 i•"F&ð4+ÜG’TSÝ›—þh†af0¥®êD¿˜9KnhZ=¶s¯¬Úuˆª©%¤ãn}?‹z‹¤«¼i«3}-xÅÃÛMÒm…÷H¦Þ—­xé/ÙµévlM/&?#îäM'„ÜÓœY’ÔtçóU_œÛÇ=£Èör7Ñ]³ÊD£e Oõ /þ Çs endstream endobj 1179 0 obj [ 1178 0 R 1180 0 R ] endobj 1176 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 1179 0 R /Contents 1181 0 R >> endobj 1182 0 obj 2795 endobj 1184 0 obj << /Length 1185 0 R /Filter /FlateDecode >> stream xœÅWmSÛFþî_±C?`äê]²“0“€é¸ñ@‰E28Ó9[¨È’‘d­ûß»:I'ùt†ÐI¨`¸Ýî>÷ìí£ã¶£Š?JÞ8}æ‹Îm9§£ƒa—S– šÙÓ-X@Ù· ÌW5:zÕæX„køÔ‰:*üÒùü_ú ¢Á}GÝ1ãIç¼?£¾x|®:ï¼ÎÏ'h*x—5E†Ý³5KU5Û·gèýüÑÁ[ÀçîñðDù8~RŽÆo'“½/àýÚzÛ14ýØÎùL©£;=!ÑÌÚ(æp¦p”¿ Ë”máµèàŠv+(µÆ¤6!mæøEƒoO¯“jjÏÝH¬æX[³ù¬µ™Çæûé‹û1Ù)µò½Øv±`O± h¡÷…ƒ}‘Ñ ¢8Y0ø‹úKð`g×pÐ{e’4¥)D”ú@`™ ’<À }€,†?ã ‚ìš. ŽU\R[ï¶Š­q§]Ÿ^*uˆbŸÂ´;Ý+Ü4S0†|a7·Pd>§i'Àg‚(ÈHÂöÅfÚ>]»å³~ÙÃ’BeôŠ&0ðgÊM¡[ÜuÛSß}ÌÚÎã(Í‚îRÄ2%Z…átO¶W OhËÝ´›YH;-Ç|Ÿå˜ážvïH2¿& 覚GÙÉiœ!#3ttzv<HLL‘µ}¥zê^s¸/¼«zûç–HäNúHÀ¼|gÕ³†S$›÷x ×pL/É*̰7üŠDÃZâÜiýžÈ]ñt¯ƒŒŽæ}ÚÕ´éÇ~Æšß>Œðo½¥²•¸ï‹‰B:FÞxÈÌÊ\O»,Ù8ñûpR¹ÃXãñîuõ&U7DÞ[…¿J±ÆŠj–SÝÉ-ª?7Û¬~>뢜‘8µÚ’òMåÿü‚Öm›©´kV£ £`~ÓT.6¬e‹ …j¶Ím¥¬;n+V‹z&·4T]°¬Eàb2ü #ÿ,n˜l;/Ï?.†.’µMž/†!’ôq[j wNŸLž/†-& }ŒŽÞæäçã?Ô¿áüÀ|º’ÃÿÄÅTvGqmË)lFì­õúÐÍ®ƒ”RŠ•èóᜤô€ž¾0Œ³Ú,¾l¸£¼ß¤jj—]J¸Ç¤ÑӸܑ d%SÍÑ£ns]j ÝØCm9«ý¡A½†¤m¢M­/G¹9N;нW¡ÏGôë’γŸ þÔïÈb2KÓo‚Õ  «è“Y|Wj©áS×Çj²b´ôÕË9)íW¹$q ™ãU€¡ d«$BÔþ9lÛYš(9œ•ÕÒ'U,¾ÄO•Ë$^ÔœÔl p™aI‚?“!³ ‘‰W¯ ×ƒ7‡0:E„6Þ»GaÐò:uÀî=(sߎ/PçPVv%lìJ#š"EÄ×oÀ“¬¶EI—âcdN»¥Øä²,Àã”ÈA9"Ñ‚rÅêµÙºˆœç®:«“ ’mˆ´Æ¿Èç[²@ê endstream endobj 1183 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Contents 1184 0 R >> endobj 1185 0 obj 1221 endobj 1187 0 obj << /Length 1188 0 R /Filter /FlateDecode >> stream xœÅXÝoÛ6÷_AìÉ)*M_–?lmZt( V uh‰¶¹H¤#Qq½¿~GR"i™Šè캣îówÇ#§IŒ"øò1_&¨¨'OýZŒæ Jó~i–£8 “ªQOÏP%¥"(xh! öèÓ„M"ô~òù ¼,Q ÇI46§”ï'wŽù&úáþ#´›üö0ùùÝ ÅzØZˆÒ<ÌãYÅù-Â4YÊO‚jôyúöö]ðç‡ÛOÁ›¿Þßß|A¿OnÎÒIãäHçî,(é<™‡£B+íT¯ÁŠ6$_U} ú§¶ªIœ~^ *²1EnHç5þ¡Î¯—w.ã(\œ6žçW«ùƒQ»(¤ômòYŽóÉT—Îd.y®“yóñþîã/h=TT ÒŠ kI³¾Ñ9ººI¦yŸ<ÖÊ?=ìi‹à+E$ºÔ˲‘žqÊhñø²ÏY>öiÄ=žòÅH©ôT–Qg “ÎûòþÁÁºAÉ"œ£é¶áµa°¡²Å…àYà[C ÊÀ¼$¡áö¤!ÖœCט싶íꃠœµŽU, Ã)ínÈcXñ­(ãM+úc ¨À!i/ጣdŽò¤K˜Ó#o-÷Ê’¥e.ö–S0õ´pÅúìB»ç]UZ~Ÿq*Q~dŽe»Ê‘|$'Ç ¯ºÚ^Ÿ„-YÒíJÅ„]b¸&ë7|ì¼=ÒªòóàÀ‚3© !–»{Šš–à‘¸²KϸêTõüíû•e4—åö¸uÌžK´|mWZ"ÀdŽ{ª«ÔÇqÝÐ7»s3,½‚} ë.ÉGÀ !Â@ݺk…aT×k’ƃJžŒP9;<–nõcföÒôŽ‚ƒ f[cÕdWÃn‚pÔ°SkzN(²cò”·âk˜ƒ'ì˜È·”k0÷j †sVÛuÈØ’£µVOîól”û‹}‹ÔÔÿ[NÕ“|BòäÆBÈÑ AC:( ÇÙ­PI*"HЂ7eÀ¡PÖ Ì 2\PRð& ¸ÀÄg÷”î^P§8[.áG†Žçö+®Õplû/7 ŒÑYœEÑ|6·óaË«Šå@zHb¤®:ª{‹ùØb¼\†‘Šn‘zl«kÝÕp’D*Ë«gšy”õ ²í¨ á`ÃwMòH]a³t¦5×Ó’lƒgJŽîFh­*±–3Ží¼7Ùy22‚@|=ÝºÛ ´*7Á#…v\m0lú. Ò¶p‰Þ‹Óðª8Û‹ì¶ù¬(£7;´Ò¦¼Á-óKk¸!6 …–ºœPÑm8¯f—æÓhq=>'ÀÞœ/Â4×@E¸¡Ø—°#tEÕ>U«#Lø@ÀVwL‚^Ûéei¤í2è´ÇvÇè3Ô_:襽2O} ô|3ׂû 1Â]­˜–<ìÝ1Z­oä×ã#c|Ѥ6?®u¿zí,.–}*•}צtéÏIÊ{øe‘¯a¥’œÛ¢ë*A+¸<¬óÝr³ØÓ°}¡@—ì|‡K–øÚТ­Sô’eÞîÛ5¼;ø@ÉfßJþ_A™(‹—AésôþP޼¨li?—åoJìÆ ”u/>*=yZ7Å70k¼¡¦^hL–Ö¯W;ó`´žÂ¦ºëÅ‘qžçKªžƒâ›Óô6MãÖ«ì?H©§ÙrïL·Ã&¸¦ïèiÆ‘7ÏÜ7±Ïv2–“Ò£èŸÄp?ªp©ö²ú7ÛÝä_›t endstream endobj 1186 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Contents 1187 0 R >> endobj 1188 0 obj 1585 endobj 1190 0 obj << /Length 1191 0 R /Filter /FlateDecode >> stream xœÅWËr›0ÝówI¸’@{×GÒi§›L<Í"d¡Ù¡áIÆ_a°Í;îLŠh@ç>Î9\Ÿ- ÄüœêæÌRë¹yFÁgàŠæ@½ãB³æT»Z ¶Y™[½É,áÖÒïÖݽy1€7‹†[ƒo¬ëVþê ùðüÖ—©õéŠ%0ï(rÅHPN#—«‹Á4…;ûÛå•óûÇå­óõ×ç››‹{˜þ´.§{í¸”ý‡v®÷j0’ú̽F»õ3ó¤T½J š{µ^ÖÅÕ÷ޢȮ&Ò.i_ãMÞ/¯_){ÂRßïUóƒYëYåÞö3>ìÇ[»”W½Q7æš”«¥‚X—j¡òºµ6„‘‘+ˆ¹mab—2_Àd–¥K©Wq^t±.ëbC»t·{–JÎfª(²TºL²•RNo.°Ñƒóë&²XwA"èÅzž™r×0g–È¢€ÞÌÆL³T9OjjËS;FX2Øy–«x¡×ð4%k0)T :N LJ¦B;•Z iJÓ°w¨7lžm>´FŽº§Á ûʼnöéàŸã¼Ã@›"°ï숅Äaô¸…ªÌ(–áæ¢þ‘Q”²U <”¥®:C1Yϯ€»üt}˜ÏzPúlÊ@®ý©÷=(°-’ì»$@ÁÕw¤J§H²zKvÆ[-qY ŒÎn·K›áêAÊ)åC¢¶\õàùa»¡©¹ó«·ýij¢D·e³Ó˜…n0lC1÷ùc–é¢Ì¥oLtV:ú%Ic‹`Ž82=йáÄsÕcˆB{‘g/KŒÏ;ƒÿ+/â^üa^šQV”-SdÜr‚R²..´_e>{”¹9\ –‰S”šm‘UJÇFB{i>Û8RºÄ´ã.JÈ0‹ÜÃÆÅ®ÀVF´NlжêDøÍ•ŒTC@tœ›é¥ï>sEÏTÝÎòAeDÏX=åÔÈt=zê µÏ¦¿¢õ¿äÚú øºü endstream endobj 1189 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Contents 1190 0 R >> endobj 1191 0 obj 793 endobj 1193 0 obj << /Length 1194 0 R /Filter /FlateDecode >> stream xœÅWKo›@¾ó+F>‘î²° vN}$U«^¢XÍ!Ž¢µY;Ûðp»r}—‡m ƒã*RŠ-ï›™ofvÖ/† D¬âä(Ì#㥾gƒGÁáõ-ÆÁv‡”Aõ5ƒ°x«qAwWúT½¤/žàΈ _ûý0¢¿ Ò¦+Á·ÆMÃ~ñ„¼»}KãÓÄøpÍÀ&0Y$røÛŒ›ûà:* “îÍ/W×ÖÏoWwÖçoo/`òݸš…ãØô?„ssäƒN©G½a+Ñ%Ú©îé;Qñ(¬sPŸ+Öê²r®:÷:E>‘¦KÇ9~Wãýéõ  M†þQbmÏïÍæ;«ÖIda{Ϩ[V)+bá¼ ô1N¥d ó$Z‰xkÉh&[)³*Ì&œ’¡Ã‰>¸ÝÀ3ëYÅŒ%*î‚ÚRñ"©Y¬y(² v¶»,®‹°Àø)‰¤õ,·š§ö_°L“õJÓ‹. ã(Í"I¥ZÆ5“<‹Šû(U&sȧÕ§‹µÕ˜š\X%׈ H¥>OM o“®úM³F©ØXЇ´é ÅÂ+@ó$ÎòT¨8Ï`'¹¯Ã!pÑbÉ·+ +—2E@ -«\¤Kï£D¥áHLMí¬”…—Ñ 5é¡ê¼â§ª³÷óÈ&æ+%ˆ:_E„´µQqJO§æF¤ó'‘‚CP{ëŸñ&QµáZÂ`€ T›N˜Ú]Ô¨‹¨¤UåHÁQNÊÅÉgkØš'á:ŠaP€J†æ§G1l3º8‚û.>OÖǰ{ “Î!~75WI–‹PwX€¤ß¡§ú£VÄAu9]ÛŽ‹êÑ“ vZˆFdøºèð®"z6ÌD&­\ÌBY®‹=ØQ;ÌËKˆô¾Ÿ'ÌE zéP&Ê«‡õb¢¿È¸!m:ëôŽÛ:½`»vW™rÁ.ðzÂe£¡Xõe¤hñˆýâØËyrùt]¤¾tÈTé¾Û‘Î’$”ZËé!¸V¯n\Ž•bßæ¡fEh<¬8›»qb|º>"w{ÓpÏÖ·å¾+O•Ô-¥ÅŒ"(‘˾m³»B·Ç@ŠÇBŒAÓÖ SÐú§LSXgV6s±–}Ke3l¼½²6ÞXÙ ›çW6CÇ?W6ÇæÈÙ•Íщr~est¼Wö®¨4:gêt¬Âf+”ÿµnŒ¿“‡ endstream endobj 1192 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Contents 1193 0 R >> endobj 1194 0 obj 924 endobj 1196 0 obj << /Type /Annot /Subtype /Link /Rect [ 453.5 593.782 537.5 602.782 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1166 0 R /H /I >> endobj 1199 0 obj << /Type /Annot /Subtype /Link /Rect [ 232.727 581.782 364.727 590.782 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1198 0 R /H /I >> endobj 1201 0 obj << /Type /Annot /Subtype /Link /Rect [ 510.001 581.782 540.001 590.782 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1200 0 R /H /I >> endobj 1202 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 569.782 210.0 578.782 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1200 0 R /H /I >> endobj 1203 0 obj << /Length 1204 0 R /Filter /FlateDecode >> stream xœÅVKs›0¾ó+tLV%\§v<õxâiId› p<ý÷•ÐŒqÚ^ÒäÀ~Ë>¾]í ÿô0@ò¦,& -½ŸF‡#À§FR€HBP#‡ PVXI>´‘öàÑ«<>{O/òet8yh®s~ðVƒüê z÷üC>&ÿ…Áêüapt6·¯uR£©W…i›yê¨ZÔäôó*)ÔsBÓM1tß/9;ïãÚûð)õ¶Z¦1‚‰Õë<Ý`Ên_Àú«w¿¾8ÍwîÚÅAªÜ®Fù³²°ßMÁD !D©.l¹ùÁÓ,ëœW-ÏÀ`DFHEq,«l¸l0T$ƒ¦2‘Ø´c¡“É ŗh†å:šúTð^³áí‰ój 1Ý2¨o—Q$U6@¶)ºb4ùdj0ùÐßvÍf±Mk1ÀvsâñæørÉâe¾ÙkÎO³´HšæúâÑpÒ}ªÁ>•Fríj#3ÿl8þÌŽ•’Òš'fQ™+X‰WËÁAù%B(œÈ§Ãé²¶µ(ÿP‰‰ŒEã(fSÑ,ÛÊò»RNšTFÚØº2^ð«+ðåõ†0B Mu2«Åa6Ñò þmíØŸò†Öž©_ C{yûcæÃqì“X›-¿šAyÄF*;Û8¹ùª¯ñÚ£í±JÕåÙ8MÍ·¼v¨»mŒ8b.D ,zqÐC?¤‘_’R-»>#$†4’® .]]jyMÑÓcôjf ƒë}ÞL—¡ø8ÐìűȬDëäMŸ'ÕöØðl4!òŠÎ)wÃØñººbˆAJå;’{áÿýËýãS…ßpM+׳”ßf8øi´ò~V9´ endstream endobj 1197 0 obj [ 1196 0 R 1199 0 R 1201 0 R 1202 0 R ] endobj 1195 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 1197 0 R /Contents 1203 0 R >> endobj 1204 0 obj 870 endobj 1206 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 709.5 240.0 718.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1200 0 R /H /I >> endobj 1208 0 obj << /Length 1209 0 R /Filter /FlateDecode >> stream xœÅTÉnÛ0½ë+æ˜CIÑvL§h‘´u,4‡ Z¢c’¨r\ÿ}‡¦¬Í6zK­g!gÞ¼GúÝr€âgë%Œ]HKë½9ºàmÈÀ¹!®%´¶…Þ50܃…‹Ù„Æž­Ê¢ðÕzyÅdl-:-·?¼°æƒþ:C?½?…7ëKb]ßûàPHV=E%aã/ô "ž«Mä,)áåâîiv›ÌìßßfÏöýÓÏGûîáv±¸|…ä»5KFcyŽûÆš0 ´¡’‰àûÓž‰aÄÒ©¢Õ¢]MUcpf= Šö˜èÒXëOm~^æPD­£‘ÀNèœUó“Y;r¬âMd®W7a<]ßLŠÚþÈùÖ^IQÚiÁ”ŒÛ•òÀÁ[QJIE/ aäa"öMÉ¢ám$#ÈÀ!4°R·oh#%¯šbw—¸Ç'\ˆªØõÞãn1è]µ©k!ÕGÉ*ÅÒ&Çs\ l‰ÒÈ‚)27ôHãDî ŒˆàìTõHL£8üóõÍk)>òŒñ­yï°e^äÍ`îFôv*9kø„t=Ó’CÁ¬„V×Ež2Í–‚í:ÇB[±)2XòНòôe€S —°¯ ,M5¯¬Ê P‰$ßä’Àzh…!Ç8b‚#1ƒûø_t‘2Õ;bÕ™Í`qð*VöN®:3ã¹Ì+žu¡åît½]ýÏžîˆt‘ýE¼ê\MæÁæXY¼OÁÔ¨š}ÌŒCà 5º¥‚¼d“K{Ϫ„ãÿªy“\?†ÞSˆ-—:Ovný’"Ëô endstream endobj 1207 0 obj [ 1206 0 R ] endobj 1205 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 1207 0 R /Contents 1208 0 R >> endobj 1209 0 obj 623 endobj 1211 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 486.556 252.0 495.556 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1198 0 R /H /I >> endobj 1213 0 obj << /Type /Action /S /GoTo /D [1159 0 R /XYZ 72.0 720.0 null] >> endobj 1214 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 474.556 228.0 483.556 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1213 0 R /H /I >> endobj 1215 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 462.556 240.0 471.556 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1200 0 R /H /I >> endobj 1216 0 obj << /Length 1217 0 R /Filter /FlateDecode >> stream xœÅW[s›8~çWhòä̬U]AÞ¼Ùd·;ÙvR{Ú‡º³#ƒ\ÓÁàŽë¿GŽ1i_²ngÐ:×ïœOä»CSý!CÑÖùÞìQ$â~³åùˆº˜yh‹šµ‡R}ª·`í æ,6è““9ýé|þ/cD@áàçæjå¹óØó¯ßW÷OÐWç÷…óæÞC” ÅÚ–ˆûا!ÔP€9 õ¡Å}žüqw?ýøöîÓôöa6Ÿ_A‹¿»ÅI:œ²ÿ!Ç“RÁ~t­ÍÍìCúUÚ`Ðáó|ܺK=‹ï›dZNnV²TÓJ®R…®”ü÷[ždWËëåµI³¯Îæ>ŸO[}ý3ßÜsD¡•xOOÐÅ"àð"ôŒâ<‰º[¯UT•­úàQpL|pIƒÐ(ÞJVªDeê€nÞÏQ”ʲÄ/A Å mŒÍêTŒVDZ (óp@Xl×W›$ûú3N=={@nÝ»‘ÚUIžIÀ1©öR¯G‹@E€=.ÂÐåAë?S?ᜇ!ŒyØ\)4K˼kaÛA_Æp躺†[ˆœñ\Tã1}JÔaº.òí´FcpB´îž8 äee%³Xñ4^MóÕ7ì¢u×ÿÕðã"ß_›©oÀ±`~„Â6†Å’“ª'A£²Ø(t¦ÐA;¤­4|h—Õq×ZçEw¾]Dyºßf­«Êâ²÷»ÎŒuK˜xü!Igé°I¢Í€v?´š8ZÍÎiYå…Šq+ÎÊs6á@'§¥µcßÃMԹݥê7»Óø7‚ÆÌJ5n½“M2Fjá8o6PL<˜7á,'O²ˆ6²®7°/vÑ´Ì80ó |¸0sŒ´1•;%ëDõ‚–vÙ”·É­Ãö×’ãg¸3ôØ@,gnÿš}X¾‘ë‰1+6$@˜³gçÿ9êÜ` À›ÄL>—1òBÌõði=7ؤÁ^ʃq1fAÏ¿/d”ª,€Â‡F6²ìͬÓ¤ÜuB•ÌÜ6JݪLóª¶òØ­WV3Nàž*TfV›zTZÁ}’éÞJm—ÅÖêqPm¤‹€Sƒ $Dxb 7:Å‹EçbTÙ–£ªŠdµ¯î¶î{Õj©`ßN! åš3•5B¬€"ŠºfãT›N¸i?€ú#ŸÁÅrî­sŒQB&ÙW»ÃÇ›èÂ…‹Ý0}Õ…gZ,=ÚÔTUv‚ÁÑælß<˜^tû´ÑX´‡F û¾Ð—¥ˆo9©!jòÌöij%S…1ZÒð´=A†PÄP‹ó‹®ø_媓€RZg7?¥šEôÅÏÃSïÞ>\ •ÖÌqQ™‘ƒZHÔ€_nò¢Rª§”ßxp…†ª¨c…Á6—£æ ž ÷>:ÿÈëy; endstream endobj 1212 0 obj [ 1211 0 R 1214 0 R 1215 0 R ] endobj 1210 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 1212 0 R /Contents 1216 0 R >> endobj 1217 0 obj 1141 endobj 1219 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 678.764 204.0 687.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1166 0 R /H /I >> endobj 1221 0 obj << /Length 1222 0 R /Filter /FlateDecode >> stream xœÅSMOÃ0 ½çWø‡'i›ä8Ð@  ©j$Óhë©Ý4±¿OÒdëÇVq+ÍÁ–Ûïù5Â퉜‘šÃº"‡c 9ˆ4„’XLy?ÒÝê8üäYã/YçÞÈŽ <‘åÊ&7€¶àHpØ®)ÎIÖ™ï28ù|„roÈÝc ÁlÛÅ1*ÖZ Š ®ÝÇÁT°¼Y<ç&zXÌò|žß®À¼¹é‘Œÿ™¬‡Á *¹¤™›jác6â¹TÖwõ®çí((l1aR_áI‡‹+]!Cªz²2ÅGÕœxkBºÙg>˜V!"ëÑjÄ•”ç”ÌÊz&Öö¤Ò¿ú¦¯î /~ýM±~¾Šc´.ß뺳®?€¥’&Li-Yöºÿ.Býµ×§@3ªÛN:9Uì Ú™˜‘_Wü§ endstream endobj 1220 0 obj [ 1219 0 R ] endobj 1218 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 1220 0 R /Contents 1221 0 R >> endobj 1222 0 obj 330 endobj 1224 0 obj << /Type /Annot /Subtype /Link /Rect [ 406.39 518.556 442.39 527.556 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 909 0 R /H /I >> endobj 1226 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 276.348 156.0 285.348 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 909 0 R /H /I >> endobj 1227 0 obj << /Length 1228 0 R /Filter /FlateDecode >> stream xœÅVKsÚ0¾ûWì­ 3Qõ°%«9òh:™L™Ðörp@Om+ÁÎëßwm 0` §Ôfôíî·/ñä1 ø•ƒÒF©÷äÖ(Bº¥@ó  7 )O5&|>á>„“)üñ2Â…w{‡›c xõ躸 |ãõúËúéú›Æÿ‹ýÕ((®ÈZl*´¨×p¥Tn%Îmn¬¥ÖÓÚ¸zÜj]ÚDÛâÌý<弓÷õ<Fa0Y&­*Œ’ëòá0Háö€…òð?¼³ÁF4?Ùk,u/ø`ØRÊVhUÁUŽTÍé:JMMªÅ ~\*ƒò|X:§gçÝ_Wƒ£^·÷ýòú¢5|bOt©‚Ëøsµ»Ð³Y1³IÅÔÀØL¢ç¤€Q4šÆÙÜ›iôÛ™sP-|F¨¦(RÖ"G³8ºO¼·»Kj°PkÅôš<¼?îtš$¤Åé †X›˜(Û¯qŽaöQ#wÐË,.â(Jó\€nQÊ|I¡´ö…sÝàúú¾ô¬š|4‹‹Øf»(2­ W>EšsmÓ8‡çZÈ ;3«1{©|g'ÕâV&œ  ï¨ÏU‹—u[Mã2Àaöhäº ‡¿æýÕÎÆ0±³Ýv­Ñc¾ Zå&1£b«;È4Ù¬‚ý™R—goQú˜˜|W p¬$ŠzhøŽïð 1~:.G®v:ÅÉð°|× ²”¤äº$@)5kø2±¶'(]Ç&†yzŽ1LV@a[p¼Åò†6ø6¯øÊè¢Å`|ö;Z Ó|)(Ã|«€ÝÉÕš1œ¼ïª†Dù£ê®‡k›™ÖÇ Ì ,5ðÆè&¹]\.ËÞ^v/! ª_5÷ÀS‰X¹¨šÉYÝU{nûœe× äœK±Lµ6ö¾Æ?LéPQÙ¨üDлºé_y+L–cÁ€W¥Ö³ij³r«ûó’4~N£|ÑÐñxT@”$PÄ©ÉIƒDßûRMP} endstream endobj 1225 0 obj [ 1224 0 R 1226 0 R ] endobj 1223 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 1225 0 R /Contents 1227 0 R >> endobj 1228 0 obj 791 endobj 1230 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 198.3 150.0 207.3 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 882 0 R /H /I >> endobj 1232 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 186.3 186.0 195.3 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 920 0 R /H /I >> endobj 1233 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 174.3 168.0 183.3 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 911 0 R /H /I >> endobj 1234 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 162.3 174.0 171.3 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 913 0 R /H /I >> endobj 1235 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 150.3 144.0 159.3 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 915 0 R /H /I >> endobj 1237 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 138.3 228.0 147.3 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1236 0 R /H /I >> endobj 1238 0 obj << /Length 1239 0 R /Filter /FlateDecode >> stream xœÅWKoÛ8¾ûW |ØM€Z%õV€] -ÒbÛl±AŒ-Š8Å¢""²äPTS÷×ïPÔË6•&—®|5ô|óü¨ÑÃŒÁßB݂ȆõföÐÊ(68~+ò| ®e{°víA®þ5ZØÝ oúO¸Èàˬ˜ø0»¾ÁÍ*<ÎÈ!\£|5»ÙW;ä—Û'p7{»œ½~ï%°L‡y‘åû!ZŽ©Ë†å®O®Î/Îß-Oo`ùqv¾Ü áöÿÆåžXÊÀ¬ƒ7ÚŽ–¡D©­¼Í}{רz©Ó÷I§Èà»´_Û_j|º¬R¤Ä ÷ J]2YÍ_œµ£B*Û}<ÑašT(9Œk(GÊE%'oà:ûõ3ÊCésC7)Û“Á÷Åý}…ŽîyxWëÕ)Æ»çj”Tý v\c¾V'ó·¥àÕæ_Y.+^ÌÜùDzb)J¯dœ÷ÂOeQɸ(€ù»Œ‰‚÷åÜhÏ3õb\°Ri/E)«û] ¬„ž?é@]ßëx$Ù“Ýï«©[u@Úî_b§ŸÂÂÇ/Œ“NóÈoä U}„¾B¿¢'ÍRb?¥Ý[OëbÝð¯ {ºe¼FnçùnØÃw?Û°B6½¬8ŠÄ?tÆv#‹ú!ëœyw¬ŸŒÄP9@e™”{ë\fƒëý _'wùíß°Þ²ÚÆßÍÏñN²:yÌø:3¥£ªoñŒ1|°¨¤=Ÿ°õ ©óæ:Jgq)jL§` Ζ½Ç®L×Ï2‹‹ñîÙîÇ£AÐû^d]_-BüJZŠ üm-¶8<ŒÀðˆí×ì;nrÕ(Öˆ*—³ÿ¾$jü endstream endobj 1231 0 obj [ 1230 0 R 1232 0 R 1233 0 R 1234 0 R 1235 0 R 1237 0 R ] endobj 1229 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 1231 0 R /Contents 1238 0 R >> endobj 1239 0 obj 1316 endobj 1241 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 626.028 156.0 635.028 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 909 0 R /H /I >> endobj 1243 0 obj << /Length 1244 0 R /Filter /FlateDecode >> stream xœÅS=oÂ0Ýý+nlܳÄöHÛÐ ©b@4m‘‘ªýù=ÇhÚ&ÃÎ~w÷Þ“7LÒßsA[ ó%Û„š-A%¡' ".cXBÈc(Ý­F"w‰’7xb+†pÇ&S:|$À'Ããv58c£Æ|w‚gŸðÊ®sv5ˆA ä/‰¤Õ´î“/arñ0Ìòþð&íÓÁ8ÍîÓÛË)ä,Í[L”ÿÀdÔÚÜÔRó#k´ò5ªøFî¨ ò‡è»úÔ/çcçRxØ ›+µí=ëðngµ ä¦e®0¶ÓÍ3«vb¤›½ç£@±E‹Vm®¤<§ôk^¼W‹õjF­ÕÇÌå[Oóa"ÊrLjmB‹ázUð¢{t¢yL«EÀeEýr»Þkz DcŒâ‘§US²Ç›àÉÛÛe1¯ý¥…t’F´ ˜TůÜEDRik#eNÈ×3G삞ý endstream endobj 1242 0 obj [ 1241 0 R ] endobj 1240 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 1242 0 R /Contents 1243 0 R >> endobj 1244 0 obj 364 endobj 1246 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 678.764 204.0 687.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 861 0 R /H /I >> endobj 1248 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 666.764 204.0 675.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 864 0 R /H /I >> endobj 1250 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 654.764 288.0 663.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1249 0 R /H /I >> endobj 1251 0 obj << /Length 1252 0 R /Filter /FlateDecode >> stream xœÅTQo›0~÷¯¸ÇTÌ6!Àcײ)Ó”) Rª>8ÁYÐX1]Ô?ƒ]l¢hš”%¾;û¾»û>›D«¿×.QBa³G/&F ¢ÌL(œ™ú4„=;Ñžr ún©ERÆQ‰0|AOÏj3¬ÃuÉ+´tê·;øêõ1ü@Ÿ2ôñsC¶µÅ>Æ!Ƙ´f@“öG!ÛÃÓä>ý–f©7_¬²ÛÅ]ê=¤wßîW7Ï}Ei6+ ô?Œµô ¤hä Þe:¦"¨ÝF ³jTmêæôz¶)l{ÂnKC­¯Zü¼ÌQ›H°& 9«æ•Y;²­ÝÏQÂÆí=ŒÕ‰™¡ôL+ÎáVȪÌâNc°é÷ßá&Ç<á“Wðú+g ÷j¾©ê\ŽÒ¥p§ôoqs.øeÜpúoýzÛºÚ{E)Vn¸Så­ ñC'ID ­‹ªá¦Ë‘ë¥:%$ôcLTꔹ©*á(QïrÂjÞÛ5ßòš«í¼eo6;{RÍÃÖLÚÀú­73ñêMU_üÉ-€U#ýÞo{ó}Ø΃Ñi‡zjÞ5Ä€%õæ µá6™d©.½Yû¦&…´ö† ÑoüCÑì¬ÇJ'ËTµ‘jëœt “N…fÇëåwöÊÊÙÚTeÊҭþf¥€üà¢r÷¤Ö1|º»á8HŽØR÷Gp8 xÍA+•ûÎkX¢?ù¤ÎE endstream endobj 1247 0 obj [ 1246 0 R 1248 0 R 1250 0 R ] endobj 1245 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 1247 0 R /Contents 1251 0 R >> endobj 1252 0 obj 559 endobj 1255 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 709.5 258.0 718.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1254 0 R /H /I >> endobj 1258 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 697.5 264.0 706.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1257 0 R /H /I >> endobj 1259 0 obj << /Length 1260 0 R /Filter /FlateDecode >> stream xœÅSMoÂ0 ½çWø¸!5sÒ¤G`Ú„Ø*:M† $Ú ÚiûùKI¶Àmbm%[vüüœç® ´¯Wp˜&d]Æ(Â/CÒÖ¦\B¥/aUœª8|çYãYgo$%d4¶É -ø&Ø„ÛIXé_dðâý>H7"7÷B4?\‘T¢Dd¨@SÁƒâá%0ºjÝv½Îkôì ß½Öõ¢'rÕÆŒÿÃ8aƒ•TqEBo«…‹Ùˆ*R«RƒÒ:Tç:rΞ%…NX¥T×ø¢ÍÏË«ŠB†TׄeZžUó·v$d]Ŷv뵟0hNˆGkûõ9›ä±·‰§f3óæ“xÙÊä''¶øŒÿQƒ¬Òa'€ÙÕÔhÿ°j[S¥…MÒÁL—'”´L• èûI®"Z,3°ßzýa؇ø'ÓliRÈ ä‹z&ILZ¤:/´Â/$¿[à÷ endstream endobj 1256 0 obj [ 1255 0 R 1258 0 R ] endobj 1253 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 1256 0 R /Contents 1259 0 R >> endobj 1260 0 obj 361 endobj 1262 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 678.764 258.0 687.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1254 0 R /H /I >> endobj 1264 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 666.764 264.0 675.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1257 0 R /H /I >> endobj 1265 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 654.764 204.0 663.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 861 0 R /H /I >> endobj 1266 0 obj << /Length 1267 0 R /Filter /FlateDecode >> stream xœÅTMOÂ@½ï¯˜£ºÎ~±Ý#B1šBk<Š •ãßwË.ÐlÓÌdwß¼™7³]hß 0Úp˜.Èʯ1ÐDË/©pI¹‚x_AfO•¾÷¬q‡¬ó/dIîÈxb7g€ðE°nŽÉ°Ä_ìàÅùÞÈmBnz B2?J$r®Q„RÁMñpH0¾z~ê¶“(EÁ¨×HJHM¥”ötËÇ´7<÷ý8i÷;‘FIEÁø?1¬ä`‡AsMk#b?I…[³+.P±•ùîyë¢:×%çlcRxÌ Ë)U§ã¢ä̓¡ CVúÊŒhìæ…U;idÁ}¨G³ í`³JY»æj_”«)NShg›üPØ1® ‹ ¢Ýc×Ôu“kóù1{ݦÁ:æëY0_ç‹`“åÛ³ºYÉÿˆ`ÓÄ ä¯ÊqÐÖ0ªXhŒf^Û~¾M=þÌŒÙÜS4DnCµ‡,SZ¢’oˆÇ:ž endstream endobj 1263 0 obj [ 1262 0 R 1264 0 R 1265 0 R ] endobj 1261 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 1263 0 R /Contents 1266 0 R >> endobj 1267 0 obj 386 endobj 1269 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 678.764 264.0 687.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1257 0 R /H /I >> endobj 1271 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 666.764 288.0 675.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1249 0 R /H /I >> endobj 1272 0 obj << /Length 1273 0 R /Filter /FlateDecode >> stream xœÅSMO1½÷WÌQ[§í–n(`bTÖx0,j²®ñïÛn ìò&Øf2íÌ›7¯]hv`ÒæYùÅAt|Hv€…”KÈÀûR{«áðgŒ»dœwx!9A¸%¯Ss¸4 ß÷ËÕÉ2jàÛ<;>¹ŽÉÕ@Cˆ—»u¨Í !¢‚k»8ļ^˜62Ï”µhÕâ*OÊqš$ tÓ²ØÛÕ #H•ûÿu]½?'<ø_Ÿ‹Y•ëd^¬Ár]dA™Uytp!äB(ÄG^V³|ž4P~„ÒT²HkÅü ‹*ñ]y¦S†‚FÈM)-7)yB#ò!RŽ endstream endobj 1270 0 obj [ 1269 0 R 1271 0 R ] endobj 1268 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 1270 0 R /Contents 1272 0 R >> endobj 1273 0 obj 369 endobj 1275 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 626.028 258.0 635.028 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1254 0 R /H /I >> endobj 1277 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 614.028 288.0 623.028 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1249 0 R /H /I >> endobj 1278 0 obj << /Length 1279 0 R /Filter /FlateDecode >> stream xœÅTMSÂ0½çWìQùhšæ¨Î8*u<0*eZhËèÏwK*´|èÁLÙÙtßÛ·/í’p`øx妀ќ,«-@UJÀ}*Ì¡ŠÌÊ·jøŽps/aðÏ$! nÈðÇÀ°àƒ°]¸uñ€ôjüå ;9?ƒ7r‘‹ŽÎ šlG$©RŠáÒR)L¹Dsž==¶.£¶×o_wû-¯ÓïÞ{ƒ»n48è–´£†.ÉÅ?èê5z@oµÐtÇñuµt9Ì8 òhV™QíÕ…®9·mŠm{bõ–šfŸ”ü¸Ïº,䌆 ‹¹ÑGÝ<ñÔöŒ,¹7z$p46Ä{Ê²ÖæêJ”ÓÔþÙE1M“¡§Å*.ãÜÉ<0?i( „+ˆV\įqnÁfYšåô»øx¦ ËæÄÀZ¸œåéf¼[uÈJê;…kuf·)¶÷1®㸰^fGi6ö&Y:÷òYZt ŒúAî¦I^ÄÉÈÖX~sC 4(~:܇´°?NoURãËMIbi³G¾»ö?ß endstream endobj 1276 0 obj [ 1275 0 R 1277 0 R ] endobj 1274 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 1276 0 R /Contents 1278 0 R >> endobj 1279 0 obj 421 endobj 1281 0 obj << /Type /Action /S /GoTo /D [1195 0 R /XYZ 72.0 720.0 null] >> endobj 1282 0 obj << /Type /Annot /Subtype /Link /Rect [ 368.663 627.782 403.653 636.782 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1281 0 R /H /I >> endobj 1284 0 obj << /Type /Annot /Subtype /Link /Rect [ 360.414 593.782 396.414 602.782 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 909 0 R /H /I >> endobj 1286 0 obj << /Type /Annot /Subtype /Link /Rect [ 521.999 547.782 539.999 556.782 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1285 0 R /H /I >> endobj 1287 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 535.782 246.0 544.782 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1285 0 R /H /I >> endobj 1289 0 obj << /Type /Annot /Subtype /Link /Rect [ 265.44 535.782 433.44 544.782 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1288 0 R /H /I >> endobj 1290 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 501.782 288.0 510.782 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1249 0 R /H /I >> endobj 1291 0 obj << /Type /Annot /Subtype /Link /Rect [ 294.019 501.782 432.019 510.782 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1254 0 R /H /I >> endobj 1292 0 obj << /Type /Annot /Subtype /Link /Rect [ 455.998 501.782 539.998 510.782 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1257 0 R /H /I >> endobj 1293 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 489.782 180.0 498.782 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1257 0 R /H /I >> endobj 1295 0 obj << /Type /Annot /Subtype /Link /Rect [ 172.929 467.782 310.929 476.782 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1294 0 R /H /I >> endobj 1296 0 obj << /Length 1297 0 R /Filter /FlateDecode >> stream xœÅWKÛ6¾ëWð¸ Ä,_z]›mZŒÅé!ÉkѶ [r$yüûòmZ¦ìö²Ý=hfÄ™ùæIùG‚’ÿ3õÈKVû䇕a@3+J3€$)ØK§`§Nq”|˜C’Ø‚¿’&Aà÷äëwù²H*œ46§•_’çÀ¿zƒÞ݈€bò¿ x¾¬BNr8ªÖ¦F&%Æzµ³i³OcÕœyN‚BgL(ž ÷ýœ#°I~]&¿|JF`¹>7m®1‚)ÕË=øú€ úø,ÿL~[^Uó³vUHåÛÇCa°Ðà/ÂÂTwÁ9B(ËL`‹×¿Åj‹®Í *ðÄn"õª†eY9H1Ä,U‰ÁFÿ3oêÃqLJºmÀœ7›#ßðía±xú<ÿöhLEÒÌ ±¼,³”\`yToxð˜œ@aóÌ…c'ôœÀñ’C×¾Õ•è½àlòc»ß‡Æêþps‰íåg?ˆ}àæã|ñâ ƒ,Ñ(ÈZ†Ô­ùJaTó0´Žzyž;²’¡¾ò^ôÐI¾ÔâäèÕŽ÷½A³¼óÆ*±®2Ížêaëýlý©LRf0ËdË0,ø4iPŠa–R„S¹Ž®4œ›«Py㑵:Ÿ±:Á«@á:¥‘‘ÃSWƒh€WÅ©‹#ªr8.U—:+3,‡îaÏëÆ3ëc³²½emçi…±n6ž¯LgÆ&Ý0C`_£ò\ÝG¹‰)ÇCŠ2ÌÂ,‹Ò‹Lèä¼Q©pCû*lè%ËŽR†¢Œüwp —·´c)㻾õ̱±>¡™4T ÄpêfO©P? šü¤ZÅ1´'ñ&ºŽ?m…×™ çF¤#ZF¼Þ ž ò–¶ónbWÔ¦~;ƒâŽx3ûAÓz?8¦á{áã©Gub8vMegW÷þL»özM?ðf%úëWÊq$ù¬b—Vl*s4:k—Ý çæA<–¿@ãÎð&à^EÀr>õRt’¡ ˜N¬wf·; o~†–·òV—þC[ÛЗ[ÜÈïƒØy7o¡ùÉFc¬„ò–_%ò»ä:kÇÃ,’Ü‚ŒŽ©dÌú];ÌÖ]»ŸubÕvÕd{âœEl½Ê'¢¤É]ƒ‹)›zÌ\Cýô“Ÿ!7lFÚŠ 6:´Ôe§RN\W· ÒÕƒ®±’ O¬dÏ«Iýˉ22;T†ñm­›ñùFÐOÃ÷}5ÝL2Cx¼mlil1LeÒé †³ˆ)# Ë[—‘…IJ£s\ÞƒcШƽÑ$r&p‰ä’Þd¾EîT›DWiÁîŒô ¯AÄt«cSŒux:^æ²fùè Æ¦ç!(wŠ®"­äÎë½Q%´¸eÎã1v{ÏxëÃó’ëDhûÝe5ZOòsœ¨è¹²Ç<¿·H6Þ,zð`ðëï9ùN^×s endstream endobj 1283 0 obj [ 1282 0 R 1284 0 R 1286 0 R 1287 0 R 1289 0 R 1290 0 R 1291 0 R 1292 0 R 1293 0 R 1295 0 R ] endobj 1280 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 1283 0 R /Contents 1296 0 R >> endobj 1297 0 obj 1108 endobj 1300 0 obj << /Type /Annot /Subtype /Link /Rect [ 480.001 506.556 540.001 515.556 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1299 0 R /H /I >> endobj 1302 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 494.556 180.0 503.556 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1299 0 R /H /I >> endobj 1303 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 312.348 234.0 321.348 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1299 0 R /H /I >> endobj 1304 0 obj << /Length 1305 0 R /Filter /FlateDecode >> stream xœÅUMSÛ0½ûW蘱º’,Ë>†:e(-ƒû1L¢wü›–ß•-Ç!N'š,É~»oß[I#€×hǧ“³ñ÷‹ÈýþítMܯ'ç“ѵûeü˽˜\“#ârŽbŒÚ°ë`Üó(à)ö–sµ ‡}žh¡ûÉLÏã:­ú…,þ›duÖ/äuv¯Ë~^Ì7Æ÷¿õ´Zõ :ž.úÙc­Ëç-–¨‘Ç›bVÔª K]΋2#1ù]$y§°Ú¡°BÀÂüü#.“ø>]»²ßÌ€Q‰9CÅš֚DÏ˃–24ŽñBiÅ%Éë4%I^é]Þ½ž s´H´'°–|Γ*‰SÒÐ脻ȀJ¡ÂÐzùùâ Ÿ†F*%X ;Õ«i™,«¤È61c”+°h›/Z$ÆeOâ>­–zjxwó'ëÀzaYOÉL÷ˆjÑ¿ì;®Cº6ÁNTGÉnñå¾G7¶î"Žíì¦zµüèuú¸|¨3÷¬›]0¤9¯ó©QwÀ{h+-P°+s½œÅ•v‹{w¸8[_›]èš³Ú[(ƒ]@úzqÉ(^|¶ù'ãl™êÕ¡†å‡y žUòv´ÒÕ#9¶ö»ë›ĵ>c0èvÓfD<Ö¶#6¿×ù PÏÀ¸jãùSê9y>´ „äTyxLq{]¹~ƒ^†Û$-ðZk2NWÅú2ìï"“'T”ÉæBj.£žxpQñâb}¡Ý¦ïÍEûÊ•æ ACáaÇK¿+¬ÒûÇØxþp¦Â@?ТÉyåüvO^ endstream endobj 1301 0 obj [ 1300 0 R 1302 0 R 1303 0 R ] endobj 1298 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 1301 0 R /Contents 1304 0 R >> endobj 1305 0 obj 822 endobj 1307 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 678.764 258.0 687.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1285 0 R /H /I >> endobj 1309 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 666.764 240.0 675.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1299 0 R /H /I >> endobj 1310 0 obj << /Length 1311 0 R /Filter /FlateDecode >> stream xœÅTKOÂ@¾ï¯˜£vÝ>¶{D(FQhÂA¡¨¤¥BküûnÙ…¶œjÀ7ÁýppD† þêÏÎðF®crÕ÷€#ÄóºE®Ïå!¢ëCÀ¡ªG@œÁøâé±×‰Cz;ˆèåâ»%IéjO_TzwÝöG÷tvF½È Ã¸Õ ‡‹èİ•ƒÞ)$ÛÛý¹Ì16m1ª£ÔŽÏJÕ¨&9#O&…uNØL©½g%?½²rdAk¸\©“Ó> endobj 1311 0 obj 392 endobj 1313 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 678.764 288.0 687.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1288 0 R /H /I >> endobj 1315 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 666.764 240.0 675.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1299 0 R /H /I >> endobj 1316 0 obj << /Length 1317 0 R /Filter /FlateDecode >> stream xœÅSMSÂ0½çWìQ‰›¤%íœqTêx`8` *C[¡uüû¦M€–qÆ&‡ÝÙd÷íÛ—¬4›–F…ℬ\Œƒ [.ä·€{Lø€ó}X–·jŽØxÆØKÆy‡’„[2ž˜Ã Iø&¸_®J‘A ¿<Á³ã#¼‘ëˆ\õ|àÑ|7¢“ÒG³<˜a¹D Œ/žŸ:í¨KG÷ýˆö†ý:ìÞô‡Ë Dw¤5hI.þ֠у‘V Åö¯²¥™ˆ-T-ÎÚªÖµÍY{²)Üõ„õ–šZŸü´ÌªLäÈ‚†ÂùI5Ï<µ!Kì- ܘgÊ´*q•#e9´†ö2϶Ävu½$2eÿU7ÜŸü‚¯ÏÙ´Ðô#Í‹ik:_g ]ë8[Ïò£Ã3(žø#JöºÐq‘ÓEfðjÕ‚ ™Ïƒ0TÜ á1+´Ë?òL‡% P˜R¡¿II5«AÈyú endstream endobj 1314 0 obj [ 1313 0 R 1315 0 R ] endobj 1312 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 1314 0 R /Contents 1316 0 R >> endobj 1317 0 obj 373 endobj 1319 0 obj << /Type /Action /S /GoTo /D [1298 0 R /XYZ 72.0 720.0 null] >> endobj 1320 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 626.028 312.0 635.028 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1319 0 R /H /I >> endobj 1322 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 520.556 312.0 529.556 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1319 0 R /H /I >> endobj 1323 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 508.556 288.0 517.556 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1288 0 R /H /I >> endobj 1324 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 496.556 258.0 505.556 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1285 0 R /H /I >> endobj 1325 0 obj << /Length 1326 0 R /Filter /FlateDecode >> stream xœÅTMs›0¼ó+Þ±Í ê“HÆíÔ‡¤“é!“6¢¡ÃG¸Mÿ}%cðWÓÎÔµz#x»ow…ž ¨ÿ®YDÈ`U8Ov‚`À»å@=Â|(ÀÖ>äæ­AÁ6•^ú—tñ_œÒAøèÜÝë‡  nøáà.\×¼pæ~óÏÎðÕ¹Œœw| Qºµˆ!aÌGD.AÎBócp÷æöóÕ$šº7—³éûháÎn>]/ÞÞC4s¦ÑH§ì?ˆšfÐÁ &ÈNÜ]7ï÷ôNdå6 »ö¨}ÙׯG‡ÂíL8iœôYɇ,L#E"Gñ2äGÓ<³k{Aî=¨VêCJG²ºp…ÕkZd‰‚išªUÛôâØáIà!Á ЀÒ6F š¼já{œ¯UU ›~ݽ@%RhR¡5ìAUËo'éiÀ‰4j™õôUµýž¾³:Œ«¸—q£@ÕuU7¯p FÂõœÚ“£Lò¦:ì•’„ž÷LQ1Ä?¥² YÙ´q¹RnZW…[«UU'ÍQÊþ’Æ|&CŠ×§Ï¼èKÑf]µêdÔLx©F …Ø´”Š çÎ/k…Á9 endstream endobj 1321 0 obj [ 1320 0 R 1322 0 R 1323 0 R 1324 0 R ] endobj 1318 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 1321 0 R /Contents 1325 0 R >> endobj 1326 0 obj 557 endobj 1328 0 obj << /Length 1329 0 R /Filter /FlateDecode >> stream xœÅTMoÛ0 ½ûWð˜¢H²c+×në°¡Ã&@E®­$ü‘ú£Aÿý(K²xÙ1Kè‘ÉGê)ïŠß¹^¢‡$÷Þ­AÄÁ­k _B/!Ó§F€;„‹9„àÏ^áQøî½¼âf N½L×o¼õ¨¾Þ¡7¯?fà3þ_¬Ïo!⹸›.Ú7>ô˜Dz+³c³«Éj !gÖ«¤èÀ‰þ}(–îíŠSØ{÷[oñ°Fa»Dé@F‰à+ýá°ÍáeÆip÷ ÛŸÞ·íä6o<µÉEêÚ}?>ð€ˆŽüY[,ˆˆ/¥4Xg„‹qšö6ëGø±ø O2)«T{Óìâ!¼O ðG˜X€ ýåã]Ät ‚P†µ8*w w ˆ€Ù±*?T*kgÇìâDeªùìí²r°rdCwaaRæy\¤}¾ZÃMÙW)ÒÅ8_ÝfM=˜M[2í+WeÞ§8HÛ"•Uö97ýçÒ‹f Õ9_‘fO_ïm³#eq[Ëj°ê#6ªvªcâ|M%ã¼&ƒg{Põ`1fÛµÙ`› Z#/ Õ”Õ³«wïsA”£(®IwÿV¿Ô±xœr;“F}˜ûvž"½B>•oí~ß«u<ûˆc…ŠN?]!>3•Ä*‹šLϯ‚‹ónžË@‹'ÑqÎLˤÍQOý¾QCwmÑí÷¬°Óþ€i@CYÄo™¼¶m£] UŸïiwp,{×;É,›z±ä´aFËŽñ½¨c›áˆ0µnÉŠ °sTçé ’hýÛÒ„Ý£‰+ †™LÉè¯ríýÕÉ endstream endobj 1327 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Contents 1328 0 R >> endobj 1329 0 obj 626 endobj 1332 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 626.028 234.0 635.028 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1331 0 R /H /I >> endobj 1335 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 614.028 210.0 623.028 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1334 0 R /H /I >> endobj 1336 0 obj << /Length 1337 0 R /Filter /FlateDecode >> stream xœÅS=oÂ0Ýý+nl‡¸g;‰í±µªhC"u@ RŠ ©ÚŸ_'iÕ…ÆÃξw÷ÞSÖ„šã”AjÓ%Y×5’ƒðë’çs)÷` uîAR¾j$|›™`™ä^IJúd46—3@ÓðIð®jIИ_ÞàÙç#ÌÉMD®î=`ÑÛ^".¨®Ö(*¸.?ÑFaôüâ„Á“3ìÝ>ïýË1D¤µ( ÆÿRÐÚÁØ*¹¤fWÝÂÖLÅ•WIíC-ªMír6v.…û°¹RÛç³ï¶X– ©j™ËQuºyfÕŽŒ,gïø`ÆX…ˆ¬E«2WÖ¤,§Þ×4^‹,èEñ1)óÜÒ> endobj 1337 0 obj 395 endobj 1339 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 678.764 234.0 687.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1331 0 R /H /I >> endobj 1342 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 666.764 228.0 675.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1341 0 R /H /I >> endobj 1343 0 obj << /Length 1344 0 R /Filter /FlateDecode >> stream xœÅTMs›0½ëWì±= ®$c¡ÜÚÔñ¤“Ik‡™<>8±ü1Å`išß)±Á¦\\8ì²Ò¾}»OhÇ ½Ae´‘ð¸a; %¨¾…}=.CØ€÷CHª]Ž|õȸMä¬àž¥ aÈ&SZœRÂ3Ã6\|ÇFõ«<{}„%û³OW!„x±‘R\jcL¤#ˆ¸’¦z$Ę|¸ÝãÁå÷ñ×ëÛaðããâol7úQBþ‡~F ¤©–š·”®³•‹QÄUK‰Á[‡ê\GÎÙNR¸ç„‡”š"Ÿµx·¾ºJÈ£†²R`§šgžÚ‘Uí·~6BDÑh«Wû¦üiµ>'EöÖØ·B®Ý_ãšöœðèôå,/ƒb—¹}Ìòù:]žœ÷äûÁ³m'ö?:׆‡"2F ßùmVÚÂåŸ8ÄO âJ‚2¡K‰W.²r³tv]®l¿fÉ“-`‘å@ßð I€-LaGé¯côòek;ùHþ-~Ú—g ÌòåÓÆ¦%9{*ý£û«&×¹¼¡»«“ê!GA“5ZŸb`—6-ÖYZðUFìD|\Q endstream endobj 1340 0 obj [ 1339 0 R 1342 0 R ] endobj 1338 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 1340 0 R /Contents 1343 0 R >> endobj 1344 0 obj 454 endobj 1346 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 678.764 228.0 687.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1341 0 R /H /I >> endobj 1348 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 666.764 210.0 675.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1334 0 R /H /I >> endobj 1350 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 654.764 180.0 663.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1349 0 R /H /I >> endobj 1352 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 642.764 204.0 651.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1351 0 R /H /I >> endobj 1354 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 630.764 222.0 639.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1353 0 R /H /I >> endobj 1356 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 618.764 216.0 627.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1355 0 R /H /I >> endobj 1357 0 obj << /Length 1358 0 R /Filter /FlateDecode >> stream xœÅ”Qo‚0Çßû)îq{ »JáÑmÎlY\P’=éœ ˆ ɾþ ­ *qîÁÁÃ]Zîwwý_Y¨_§22ä0ËÈÚ®1\ß. ˜G¹€ ¬/ ­¾j8|ëic>Òμ“%AÉTo&€:à›à!®“¨‘¿ÚÁ«çG˜“û˜Ü= `ñçþˆ8RÎ"ºÔåaõpˆ3˜ÜŒãÞ(vÆÑ«3ê?¼Ÿ‡ƒÛ)Ä/¤·zrÿ‡ž¢V ZWÉ%=P»ŽvÍš^1 j+µBXk¨Æ5ÅÛYîkÂfIm¡¯š¼[cY2¤AK]Ž~§šW>µ#!«Ü»~\`ZØ@Ï(kµU‹+mSvb•‚^Z仯ö\/©4—¿æ†‡ç„G7 (ó•S¬Sg£fù&Y,ç'L³=~1»‰uV]`áý\”õ‘u1}ÿRæG’8ç¹2¸”›¨T•êèðbíÒEQ6ÀEƒ|n¬ôD° %³s5ÌKe'î—. F䚊mÈRÑFΈüíGg? endstream endobj 1347 0 obj [ 1346 0 R 1348 0 R 1350 0 R 1352 0 R 1354 0 R 1356 0 R ] endobj 1345 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 1347 0 R /Contents 1357 0 R >> endobj 1358 0 obj 398 endobj 1360 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 709.5 204.0 718.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1351 0 R /H /I >> endobj 1362 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 697.5 222.0 706.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1353 0 R /H /I >> endobj 1363 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 685.5 216.0 694.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1355 0 R /H /I >> endobj 1364 0 obj << /Length 1365 0 R /Filter /FlateDecode >> stream xœÅ“Moƒ0 †ïù>n2'@ÇMê&MÛ$F¤ªª‘}HЉ´¿?§¡-Ð"­±lüØÎ›ÔLÒ¸-I%¼V¬î| ¡ê\±qCCéþêrgÑæ"ã^؆!ܱ劂 %ü0ã¶É9Ëzõ]g¯ðÎn »ºA ˜·ÃEŠ+´”ÍC™º%ÁT°¼È³‡ 7Ï‹ëǢ{¶0ƒQB!ÿa”lÐəȄDÞf‡ÞGr¡²;ÿn÷Toúæü>ÙzÂ~KC}g->-mâr=U 9©æÌ§v$äPÅHû뵟0OˆGWv]AS—AÓ~ÛuurP y.·°¥míÐ2:]~6mÜôÈ{L‚.¹¦g*F4…<Ñ!ÒØãž¾ZÛ1N=w :樑tºËØXÞ«š±_\ò endstream endobj 1361 0 obj [ 1360 0 R 1362 0 R 1363 0 R ] endobj 1359 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 1361 0 R /Contents 1364 0 R >> endobj 1365 0 obj 332 endobj 1367 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 520.556 234.0 529.556 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1331 0 R /H /I >> endobj 1369 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 508.556 180.0 517.556 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1349 0 R /H /I >> endobj 1370 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 496.556 222.0 505.556 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1353 0 R /H /I >> endobj 1371 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 484.556 216.0 493.556 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1355 0 R /H /I >> endobj 1372 0 obj << /Length 1373 0 R /Filter /FlateDecode >> stream xœÅTËnÛ0¼ë+ö˜Ä’ÔƒäÑEÜE[Àµ€’‰ŽÈV"²Hû÷]ŠrüŠÜøâJ.HîÌîÎHÏŠoì¡8”«èyØc 8$ù°•åÀRÂ3XÁgÐø[;ßD¸„K,ág´Ž(|Žnïñ°Š /=„ë“çÑl‡ßŸÐ‹óSxŒ>чO0 Åb;¢$%Œe”²\‚$ WþáP¬àöjrsÏg_ãyñc:ùv}Å—hZ쵓0þÚ™íÕ€’ .ÈÐ}vöp'ù£fÐ`XjCqa-Šnk¢»%ík|Qòqy…Od”È=a9KGÕ¼ðÔŽ„ôܯý$ÀPXIÑŸ{mõ⊡©ÐÓ¼® L S:š{c©„Dšç(‡ÄbiÀ>™²^Ô¦‚‡®ÕU©­ë:£WwWöî´µmYk‡^j·„ Â0ðñ3¬J`§G\•vúA[3Z WâD:èÎÀª­úRÉd|H¹ &+Á€I?ßæŸS3RŒHÊOe!ï{»6ïàcÜk›"!§¿Kóäêv­QðÚýÒ>>©Kñw‘¥ÒDžG.8QŠ"yÂK“ƶ¯^ßZÍIITšz¿õ^S‡ÅУ¢uºs±}nâΔmWÕëÇ7¿#DÇ鎸Át£ ŒŸ Z™Æ8¿›§çb7µu;Èvú_/Ï> endobj 1373 0 obj 554 endobj 1375 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 678.764 234.0 687.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1331 0 R /H /I >> endobj 1377 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 666.764 228.0 675.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1341 0 R /H /I >> endobj 1378 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 654.764 210.0 663.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1334 0 R /H /I >> endobj 1379 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 642.764 180.0 651.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1349 0 R /H /I >> endobj 1380 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 630.764 204.0 639.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1351 0 R /H /I >> endobj 1381 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 618.764 222.0 627.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1353 0 R /H /I >> endobj 1382 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 606.764 216.0 615.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1355 0 R /H /I >> endobj 1383 0 obj << /Length 1384 0 R /Filter /FlateDecode >> stream xœÅ“Ïo‚0Çïý+Þq;н–¥G—±%‹[Â$ÙÁx0Ò9’ýû+T¢ìààЗ׾Ïûñm·„êߪ!9,R²m| Ûk\®̡܅Û…¤:Õ2øÎÒ‹9¤oø$k‚ðB¦3½ê€‚Ǹ:xBÂVþjožaI#òðìCˆ¾#âEWêÏàS›W¦žY”Âôî)Q`M±5‰>‚ÑÛý ¢WDŽlÆÿ¡£°SƒVUpA´®£mãÓª¶’F†f5TcšâÌÚ[jÂvI]™oš¼_aQ2¤~G[μ^5o<µ!«Üû~l`ZXY§­Z\Ñ4ezš(£¤Èö¸Ž6Raž~Í•Çs“û_”ó¼´Šmbåj‘åñj½<;3 wøpx¶¹Ží:ƒÙm¬µé{Þ_ÀE™«yÚÇþPæ<Ž­Ë\9X½X%ªTW /Ye‹\´Ð—.­-©Ë|)kní{VªpæõVõy6õ‘k–tw!kE[9Cò ¼»}U endstream endobj 1376 0 obj [ 1375 0 R 1377 0 R 1378 0 R 1379 0 R 1380 0 R 1381 0 R 1382 0 R ] endobj 1374 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 1376 0 R /Contents 1383 0 R >> endobj 1384 0 obj 402 endobj 1386 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 678.764 180.0 687.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1349 0 R /H /I >> endobj 1388 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 666.764 204.0 675.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1351 0 R /H /I >> endobj 1389 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 654.764 222.0 663.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1353 0 R /H /I >> endobj 1390 0 obj << /Length 1391 0 R /Filter /FlateDecode >> stream xœÅSMOÃ0 ½çWø‡†8išô8¤@©4‡i‡‰8´›F'ñ÷Išlk÷¡i—‘lÙñ³Ÿ_º"Ì}‰7*çðÑUŒ!("‹!™¦”Kh új«çðçL¸äœox' Âà‘Lg.Ys¿„íÃuÅ%)zý}†]½?ƒ/roÈ݃d`>w+H3dîdš žûÃÁ40½™<•&)‹IRš·ñ襼y&c3 $ÿ¡b0ƒUqE÷¤îªEˆ¹Hò©:ªm@ n.Ø“C±ÝL¬?ÒPå«6?-°ò…ȨHËQŸTóÊ[;Ò÷Þò€NXí(huâªH*p*­…QÝ.·Äv¸©Á¨ ~‡›ïï‰<ÿvU'íúÇΛ£«r˜)¿s^UÉy\™^Š[ÙÚ®íqè3{Ì‘JÔy®0îñu¹¶m¨?òžÜxˆ’jÆT.7% K{- òd&J endstream endobj 1387 0 obj [ 1386 0 R 1388 0 R 1389 0 R ] endobj 1385 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 1387 0 R /Contents 1390 0 R >> endobj 1391 0 obj 354 endobj 1393 0 obj << /Length 1394 0 R /Filter /FlateDecode >> stream xœÅVMsÓ0½ûWì‘vˆÐ—%‹[Ò(Ð0m3åÔDi=8v±Bþ=«X‰Câ„r)If$¯ôöã퓜Šßž´á0žE?‚æ T0Å ˜$<†„y ™ßµ1á«Í&œÜÃç((¼¾|ÃÅ PüŒè¶»%ø:ºÜˆïWè³ÇßÌ@0þ_2¸ü³ šk²Õ›%Z46´4ŽüRh cãµ™6É5ãÞ¤h›í&%¤û|Á)ÜEƒQôêM ŒÂhÚŠV{ £$áÆ8ŒfðåçôèŒÞGg£n>3k;ô±×õ`ØØ„RÊþ(kÙ\ŠjjÚ™kŠê A&À ¡*öû“p<èŸ|8žö>÷¯†ç÷½ÁÙ»þÍù§«chü¬ÑœÅDjŸç»~¾r®·üNм.‹¬‚[woÓb^B‘ÃO[æi~WÁ´,f0Ï'®Ìh€«ÓÁÅ5YÕ¦;j“ŒPC1‚j"ÜØ2µ·Ùšý4*Cb–£™YA³¹ƒÑâá ™F„rtgâvá¬O~:ÏàÑ{¨À–^ûš^ÂkW–E‰cz—h¶ùVÞͶw.9QʳÅônœáùǽyqE‰BÖ™bIþNv ¥)‘ @çyZ§6ƒ%+‡aR‘Xhc¤]^Öþ„˜Zã{§k€§®—éCùÁˆÆ®%Å"CÄþØcàz1' ¼¨‹vþàÊiQÎZÃæÆ ¼Ö0sUeï°‰kËR“ë§[;þîò i-§njçYÝÒª;‘%-À »hlVml½uí¼rõKmm®mEôÛ¢ªB%b[m +qzgû´ÉPa:îðwH–L'Ý À:ª4sy- D¯ïÝê"x‚`¹0_}”¹žý²³‡ÌU{ ðdhE(¦A“X†> endobj 1394 0 obj 837 endobj 1396 0 obj << /Type /Action /S /GoTo /D [1395 0 R /XYZ 72.0 720.0 null] >> endobj 1397 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 624.028 172.78 633.028 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1396 0 R /H /I >> endobj 1399 0 obj << /Length 1400 0 R /Filter /FlateDecode >> stream xœÅUMSÛ0½ûWì­0CT}Ù’®…¶C‡¡Íà™(ã(Ä3Ž,3-ýõ]Årl'´J†ÑFÖÛ}ûöYyŒPüLü¢ ‡|=†=ŠƒHÂVœ“„ǰ„ÇPúSƒ€w.í! ð=ª" Ÿ£Û;|8Š€ŸÝM·ßDÓA}ÿ„¾yý!Áøa0}9ÅÙ™Í-Ú=ÜiùGe-¬mÖ6lɵëAR´çDÇE tß®8…‡èC½ÿ£Î{Ó*d”hnü‡t ·'œ³Ó;H¿DÓ½i¾±j{ƒôµ·ý`8XM)e/ÚÚ W…¦Úž®³¥m›‘Ajà†Ð$öçu ¸™^Mο^_\¦—_¯¡…nŒkd‰‡eÌö¡?8W»q Í‚{ZÛzÒ<¯-¬æ•%t|“]¾œ sl[rµŸíü ¹ì•ÇëO«‘®'nmób^䯪YÑ«Êu©Ôˆl’j(â“P»CAŠtÈÃsJ ‰™6F±0§ó2s¾Õ6·3[å® ×œDSÔ‚™¸ÍàËÉ–üî(%J…æ÷g}ÓgмNžqŽC•Èž‡ Öåu±î+sf2!±@RÝÓEáàšN¡7F Òm¡Qºpc˜4‹5 Ç#Žû†iM$E¤JFÀ½q:½¶[3;/*;Û~¿~²`‚pƒêëXþ3i!=Ø[™ðY/dÝ Y=é[4ïdMvŸ9»ízÇg~Æ(õËjEÕØzžåÖH¶¶áµ‚N–¢B½²²ømÞ ¬~xZÚªqx¦O+ËìVµ#aNã_M%X¸WuGï@ÆW’âK¡GÞ%@_f‡/%Æ Úß%ÂŒ¤zÅ]Á±`5¶rÈ ~˜¦Ñ™g endstream endobj 1398 0 obj [ 1397 0 R ] endobj 1395 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 1398 0 R /Contents 1399 0 R >> endobj 1400 0 obj 688 endobj 1402 0 obj << /Type /Annot /Subtype /Link /Rect [ 484.72 669.641 537.5 678.641 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1396 0 R /H /I >> endobj 1404 0 obj << /Type /Annot /Subtype /Link /Rect [ 308.745 657.641 361.525 666.641 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1396 0 R /H /I >> endobj 1405 0 obj << /Length 1406 0 R /Filter /FlateDecode >> stream xœÅUMOã0½çWøX¤Åø#q’ë²ËJ+.•ö€8´‰K-¥1Īÿ~Çu°Ý8B©ägæÍ›™òœQDàïÒeÍP³Ïž§;ŠJ†¸˜® hŽYöh’ ÔÙW‘ÀÞ$8Ü#vè_ÖgýÉîÀØ"‡ŒÌÜï²e”ßZÈ—çpʾÁò¼ %+ñ¬7'oîîàÆ²¦n¢m:]T':pîü ˜Èû¤Lp¿.9AÙÏUvuS JÐj†¶´Ž”àŠÕöÃÐjîŒÖhõ7û½JºùŬ%´¹}=±W'ðgeQ"° e] Æ£˜U%!DWÞõíÝò]ë¾U£Ò=º;šQî]ÅW7bÎQ^ÁÓª‚,´ŠB¼y¤¬V˜PHÈ`|Wt.™Oƒ~U­4áfÝ·Ay1g¦ 6¹¿2§‚®"Ûa§š]¨ë‚"‡A8¬‡^õ±yAÑÛ Ç§È∠R†K|PèF‡yî.}EsOQÀ|$.xþ¬B‚ÌÞ¬vÊ/8,þÂÈfâËé@z3¨ /ÆôòëzPú%ò~Ù4ÝÚ˜èù©v'ΰ0.p™çu]À²$¨>+–U5.xò:uŒ oU/[¯oŽ3$ïL0çÎi À‹4ôç³Ì¡9@«`3Wìsÿ’ãZu 7)“Üí•ièÛ´…%ƒè’Ùe¶Ñ·z7NpŽ;}ð2ôêè—Èɰ1­WN+àĉ¡9ÌW]¸ÉLòN - ,ˆmtÉS߀¯!²o#Œ£öâ&”aÔc[ú~-Pc`¥Ñ­Ä^»QÖíø#êô€44Æm»»‰ù5z/Ó–Tù¬,˜{»)áÈ.¾A¶ o;ÕâèÇ2û/ö endstream endobj 1403 0 obj [ 1402 0 R 1404 0 R ] endobj 1401 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 1403 0 R /Contents 1405 0 R >> endobj 1406 0 obj 664 endobj 1408 0 obj << /Type /Action /S /GoTo /D [1407 0 R /XYZ 72.0 720.0 null] >> endobj 1409 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 624.028 154.43 633.028 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1408 0 R /H /I >> endobj 1411 0 obj << /Type /Annot /Subtype /Link /Rect [ 385.51 624.028 438.29 633.028 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1396 0 R /H /I >> endobj 1412 0 obj << /Length 1413 0 R /Filter /FlateDecode >> stream xœÅUMoÛ0 ½ûWð¶h4}X–u]× Šmi ôÐõà:JcÀ±SËÅÖýúQ‘»Ž“n—.A`ZÒ#)æ1`@ñ;s¥9dëà±]c 8ˆ¨]’°p khm …;50xgáÃBc7APøÜÞáæ(~tìn ¾æƒøn‡¾yü!Áøa0YÅÕf‹~ W¼#·U´²µOïÕ›žœ$E{NtZ”–îÛ§ð|H‚÷Ÿ$0 ɲoZ倌’˜k÷á¬áö„s~zÉ—à"Ù«æ«¶WH{—†…)¥ìEZÛâª6)ŸÓ×tm|R2„1pMh$Ýùخ痳‹««oWàa»ÃŒF„º“ ÉîÁ~p®Æv ÍÊ€}Ú˜zÖvf7&Ë—y¦®«ÚvnÔ„\!#TSÄFmܪ\äM^•`òp}"M$‹QÖÖç¼H­…ïµÉÌ”™ËÜ6Ç ¦‰)êÀ´ôìc1ÛÉsºœ©`û 3°ùzSܽe]:gÐm˜:¯žìpgG09a­Ô4»vŒŒ"Â5"cNQÄl^—–qŽ7(DmyëᣱYoúÈÓŠ²0"R(­CÑvD²Ê-œNÏN¦kÙδn·„-Ü™ÛVníƒ-ÍdLd$´–"š`q¼§YŒ`R*™˜÷MÝÑØ©9Ì'mv/µÙÔÆš²_ñ×á¬OªG.Ì2/Íb÷~ÿüzº! 4e<”ÿœ.#\áÍajÛs¬êžnù> endobj 1413 0 obj 759 endobj 1415 0 obj << /Type /Action /S /GoTo /D [1414 0 R /XYZ 72.0 720.0 null] >> endobj 1416 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 624.028 167.77 633.028 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1415 0 R /H /I >> endobj 1418 0 obj << /Type /Annot /Subtype /Link /Rect [ 210.54 624.028 263.32 633.028 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1396 0 R /H /I >> endobj 1419 0 obj << /Length 1420 0 R /Filter /FlateDecode >> stream xœÅUMoÛ0 ½ûWð¶h4}X–uܺ­ØPËj ‡®ÕQ‰“Z.ºî׊e'µv»t 32ÉG>Ó÷Šß‰¿(Í!_E÷áŒâ ’p$`1áVl KïµgðÖÂKã„Æ®¢2¢p]ßàÍPwÇGÃÁ¦”RöŒÖv¸*j8]˜•mH´!NkBéýÓp9=Ÿ\}øqñõâ `çÎ8#4Ƭ;6þä\õ]×CÔ îac«Iý´±°žƒY.¡­6éWËYB„Ï.¨F;=ÇÊ2å±Ç¢·ÂN°·±y1/rx4UY”w® ¤FZ#)íc%!óºœu±.!C-òðŒM$K±ftº4ÎÁ÷ÊævfËÜÂyáê—†¦I)ÇÈZ6ÜýrJï@K¢_ka'-ß“Á¨EJd;¹Ñty˺Ԍt¦Jð±Œîê×{Å8ÇÇ"Æfñá“uyUlv™Ç[ÄpàR(­c†œ- Ç q#í,¯Á`îI1œ "ƒµfcÔ'“š¤ZRs5’ÿe¢ ˆ¦H4UcÅïªèÚ¸ÇÄÔ­]ÙMe-»ƒV×'¡7³ó¢´³öïíÓ«DcŽ[† jžü3ÑX"˜{iQ>î \W=aù¡Ê´çnÊ'¿7Šúƒ™©Í­qv׫¢¬m57¹u²…­,ü•kh9%öÐ,‹ßfûüšêîa…]sèSmr»uåÈ_h5Mˆö‹A –ﺶîÅíËá W*§éàIT©9¼™%)Ý<Ã@¯È-FpêW Ð#`°¿j[:ì Ù{#N£?tÒ>. endstream endobj 1417 0 obj [ 1416 0 R 1418 0 R ] endobj 1414 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 1417 0 R /Contents 1419 0 R >> endobj 1420 0 obj 743 endobj 1422 0 obj << /Type /Action /S /GoTo /D [1421 0 R /XYZ 72.0 720.0 null] >> endobj 1423 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 624.028 205.53 633.028 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1422 0 R /H /I >> endobj 1425 0 obj << /Type /Annot /Subtype /Link /Rect [ 210.53 624.028 258.3 633.028 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1415 0 R /H /I >> endobj 1426 0 obj << /Type /Annot /Subtype /Link /Rect [ 301.07 624.028 353.85 633.028 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1396 0 R /H /I >> endobj 1427 0 obj << /Length 1428 0 R /Filter /FlateDecode >> stream xœÅUMs›0½ó+öØÎĪ>I¹9ͤ“ÉÔ ÒVl:‹Öm}WFØƤ§Ô>H#ôÞÛÝ·,ÏŠÿ‘[¤æ-‚gÆ@r±?Šb`!á,Àï#(Ü­ ow¸4—p3‡Û  (\w÷øp «€véÖà›`²£ïžÐ7×ß@0þ_"˜¼tArI:ެѢ9Ó†È=*|ÙüÚ°6Û&¸f=ÝÆDû‹âÃ};q ³à$ >|Œ€QH·M+Q¢¸v?ÉîÞq¾¿‡äSpžì¹ùÆUÛ3ÒioòÀÐXE)e/ÒZ›+}RMN×éÂ4Iõ”!TÀ5¡qäî«p3¹“ñÉøæ|t;þr}y} ÃǤ$±ÃÄ:ÚgøÆ¹ìÔ¾Z3…º‚Uº,a5Ï i–kór)´ñÇÝøS¤‡ïô “8˜´İvZÊžX¦i>¤Ö–@öT-d„jêòñŠU9Íë¼*!ùý´©÷a›b!(­%ó6©µðyi235efà*·õoZE92cA× ö¹µ±\!±v]„ ‘k%{Žö\jàºÓ; £b"0i*hÔ'ãQ{zÜ™!'ï×ËÚ2w‘Š!2f}‚ØÔ¯{Ã8Ç71Ds¸g836[æO[á~KX“HH­Cá›)™çv«Kó´4Ö”µmk`Áæ³2- ìÿý¾ï´â ­Xíix¬Š¢Z9p^¢dZäÒµrºœýX¬…Órê5ª¥ó Ûìx¨Ó™¢¡K¤F¾c8X …¸`JôàÛ´e5ïÀÆ>è­®îâ4#‘r/¥{vvô/!pvvú` {FánØÅqØCâ|jå¡zøn²êyZcKX´ígUüÄfÈK<4¸d9΃š¼Þ¶\p¢ÝL’‚ùÑ_ÕÆÎþ¹¤Ð*VüðìáÌ"N˜pTèÆáYÌ‚ÃCXlÏÚ”ËMv¾Ë“à/Âkû endstream endobj 1424 0 obj [ 1423 0 R 1425 0 R 1426 0 R ] endobj 1421 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 1424 0 R /Contents 1427 0 R >> endobj 1428 0 obj 752 endobj 1430 0 obj << /Type /Annot /Subtype /Link /Rect [ 178.993 624.028 213.423 633.028 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1408 0 R /H /I >> endobj 1432 0 obj << /Type /Annot /Subtype /Link /Rect [ 442.368 624.028 495.148 633.028 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1396 0 R /H /I >> endobj 1433 0 obj << /Length 1434 0 R /Filter /FlateDecode >> stream xœÅVKsÛ6¾óWà˜ÌT( øÖºn§OÛêää€PÅ>d’jìþú.ˆøJO®t Ä~»û}X€ÏEþ+ûHCY=û9ŠR†xâ§D‚hŒ™@%òc »êlÀN#x¸E0Ø¡Qô[ôé ¼Ü ß"2„;:?F÷gñíòæñÏ3à”ý/Ü_ª²´9zs73Ⱦ*4&3SeÝæm·$›âXÈJ8„ö¹XÙ¼WGŠ~€Jb†Ó±r$Á°ß!sƦAŽþ#ù(Ž'$¦b삵y¹/Ì0?ÛËÞ š&¯íÔÊAB˜'’P§ÓeôO(Ó< [,%ä0@¢øuß×Üö 8”~ÛÿbÚ¬É÷!Éi©©XðT©˜{Çõ.·»™Q,/»ÆÍô}õ}ãÌn§»Þ¨³ìÐôVhªÓÒ0¶û«7ÚÃ~_ä&€†¾söFw:ÀÔýðTk2¬jÄ’B¡œ&U_ßÂÑ4OgKáUBpýd£²áÿÉçÂŽÄS io-¸äÆ—7Èê¿$U<;Òʧ„c–ØD’xÄ å¶´Ïÿte‰„{ ®ä”SÿáSw§¾žûò,R®d"YÜu×ë?O%¥ Ã%ÇM*&–¹eÃ…ë ð¥9FCpbi4{n•X)ÊŸð^>7áSœ!4a|*tßdøìÓø>ú l8Å endstream endobj 1431 0 obj [ 1430 0 R 1432 0 R ] endobj 1429 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 1431 0 R /Contents 1433 0 R >> endobj 1434 0 obj 993 endobj 1436 0 obj << /Type /Action /S /GoTo /D [1429 0 R /XYZ 72.0 720.0 null] >> endobj 1437 0 obj << /Type /Annot /Subtype /Link /Rect [ 186.914 678.764 270.914 687.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1436 0 R /H /I >> endobj 1439 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 602.028 204.0 611.028 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 563 0 R /H /I >> endobj 1440 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 590.028 198.0 599.028 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 565 0 R /H /I >> endobj 1441 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 578.028 192.0 587.028 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 994 0 R /H /I >> endobj 1442 0 obj << /Length 1443 0 R /Filter /FlateDecode >> stream xœÅUÉnÛ0½ë+æh5KŠZÈc ¤Š¢€a=$9(ã(Y”Ûøï;µY²\ ×>p¸Ì›7o8ÔÁa@ñ¿ª†Pº°KC³Æ tÍ’óˆëC íCRnká`¡ñ¿íPøæ<<áæ PtøãÐ1\í¼qÖƒøÕ½y| {çËÖùüÕFaûÚKâû>¥”3„»²ú¹°Máa±YÿX>Áö»s¿=Ë3÷?ä°>ã€u ÝŒª[{s»†+¨ÚJá›Ñ¢ZÓ’³ã,)Ús¢CJç…½iðùš†Wˆ8«eÌ–òÆ’MªXÅî’AêXU’åTW6lr²)Ý¿ïT^Æ™Ž:.Qe›æU<\-ˆ; K ƒ…*Ьh'Ùkk•§\µv‹,ÇÈ ©Iæ!®Lc˜C²:U¬ê³ô˜W@Z±i-ï1ñD½t[éHŸº´•*]vgô8d1"™ à”q¼;"Q±Ÿ—˜{î×i:+/HþÖ)nŽyžeŸcUŽÎûqY&Ãûl,ÿ)}Î’Oè´BvAË"ÖûÁ‚>¦ÏªèçÙÀ¶Þñ®_ÁG±Ÿ¨÷¼PÆà½{\^ˆz3‰MyùÐoµ+‡ó]¦Ë(ÖHsp^'§~†"5 Ù 5$à#Aj I[Ãù~“Œøè$CÖ8n”‚»ÄdÝCÒ÷1Æa4$žm溑']B'ß—ª3z/¾O0“ÎrUÔ/Â,.gÇm¹†ý×Ã…ßX·úÆzBXœŸY©®>TLºÄç¡”ï\´"ƒ˜kç/,:ò‹ endstream endobj 1438 0 obj [ 1437 0 R 1439 0 R 1440 0 R 1441 0 R ] endobj 1435 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 1438 0 R /Contents 1442 0 R >> endobj 1443 0 obj 610 endobj 1445 0 obj << /Type /Annot /Subtype /Link /Rect [ 188.292 573.292 272.292 582.292 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1436 0 R /H /I >> endobj 1447 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 508.556 138.0 517.556 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 560 0 R /H /I >> endobj 1448 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 496.556 198.0 505.556 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 565 0 R /H /I >> endobj 1449 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 484.556 192.0 493.556 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 994 0 R /H /I >> endobj 1450 0 obj << /Length 1451 0 R /Filter /FlateDecode >> stream xœÅUM›0½ó+æ¸{Àõøã¸•ÒªUµmšH­´ÚC6qRÔm÷ßw N€$¤íRð`{æÍ¼çmÀ€âºAóM°õs !ýT,E„ǰoǰv»:ß[84›Ðøß‚4 ð>xxÄÅPtxèq¸ÚyŒ;øn…^ŸÂ*x; Þ¼‹Q˜.[Š„$’Q¼$M7îâ0ÝÀÃÍdü)}ÿòu4™|ø|ûÓÁhÚ+G0þÊ÷r@IWäHèÚ[4s8ÓrKk¯›¨Ù$׌ƒIÑ6'ÚM©¯ñUÁ‡åUgˆîÉ*õ ”W¦ìDE‡}(SGU5žMÖ«©VVùšüIMFË¥WeSÜ." Â*%ÔÞñ>K-Ù{ JEbô1Šy¿»Ë.àéåžaDSŽñLüOxŒ;ž"äÞqôknó*ÉÒ’—T»™³/ÖÊ"ì;¡Œ‰„öI§p !¶Š€[YѾfËÖ®^rÛ¾í!Ì1c’pÃPÍÏ€•Ûu¸+mÖHƒ‰"9Ÿ*ŠÏDióHÊÖ.“ò°FúÛåN³N»´ÜåyVTÝÍóló”¤5…ç)øi_ž³¢ã1+V»M÷§«Çs,’ÆTËÜΓeb#¶Žˆ1ÅÌgkán]f‡>mÛe&Š\¯Ô}r¢ =ù’£g{ÞEcüÑÂ,·EMà`\½>îþÀÔaÿð1à’Å¥ÑFš¬²[ƒkI¨ûë¥Nú²Æ¿ŽËo endstream endobj 1446 0 obj [ 1445 0 R 1447 0 R 1448 0 R 1449 0 R ] endobj 1444 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 1446 0 R /Contents 1450 0 R >> endobj 1451 0 obj 579 endobj 1453 0 obj << /Type /Annot /Subtype /Link /Rect [ 186.603 678.764 270.603 687.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1436 0 R /H /I >> endobj 1455 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 614.028 138.0 623.028 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 560 0 R /H /I >> endobj 1456 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 602.028 204.0 611.028 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 563 0 R /H /I >> endobj 1457 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 590.028 192.0 599.028 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 994 0 R /H /I >> endobj 1458 0 obj << /Length 1459 0 R /Filter /FlateDecode >> stream xœÅT±nÛ0Ýù7&ƒÙ£(ŠäènÑ¢HêF@‡ ƒÓ®Y’%Mþ¾'Q–-Ër ®=ðDòÞ{ÇwäŽ @úOêAÛž·l×Î ÐȨRˆ ¶ÐÆ ’z×Qì#ü& ~ÃO–2„Ïìñ‰—€”ð‡á)\“üÀæGüõ ^aÍ>ÆìÃ'!^ŽH®"DRƒá2°õ/€x 7óo“ûï³ÓøËýÝíÄ_Ù,îU#Eðª™÷4£:ÐüÄç&[ú9šñ@õRÒZÐŽÕ‡^œGEáAKê[|Uòqwµ¤nz®jµòÊG6p±æîŠ!é䪩{³WSã¬nkò%Í^Ÿ]^m²tAЛêeQÇ¥/óÌ©„¤åQß ÓBLS¸­-ܸ¢ÈŠî+[uaõ–»îcnOÑ­GHò"#‡<å.™¼”®˜4,£…5@:›² ËÍšÊOÜò°¸ˆ%–¢@EÜXEDh‡DYîŠEuA§ÄðBú9iVuñâ þmû+KºÏÂå…+]ZmÒõ¹Ý/yž•[z]ÇÆ*q¢1Ø—Á÷uŒ÷–¶\Q®ÕbŸïL“2ë.Í¡g‰Î*ú¾mzvÐ 8xT©ÎÞ?¨ß6q¯õa•Ôò£À¾¸ï~û¯›IÝ(…ãqî²Ê]¼‰ÂÐ3!µµ¡ìRRÇ8çì/˜H®µ endstream endobj 1454 0 obj [ 1453 0 R 1455 0 R 1456 0 R 1457 0 R ] endobj 1452 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 1454 0 R /Contents 1458 0 R >> endobj 1459 0 obj 530 endobj 1461 0 obj << /Type /Action /S /GoTo /D [1460 0 R /XYZ 72.0 720.0 null] >> endobj 1462 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 624.028 192.19 633.028 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1461 0 R /H /I >> endobj 1464 0 obj << /Type /Annot /Subtype /Link /Rect [ 197.44 624.028 231.87 633.028 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1408 0 R /H /I >> endobj 1465 0 obj << /Type /Annot /Subtype /Link /Rect [ 464.2 624.028 516.98 633.028 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1396 0 R /H /I >> endobj 1466 0 obj << /Length 1467 0 R /Filter /FlateDecode >> stream xœÅXKsã6 ¾ûWð¸;±"©§oÙlÚi'ÓnÏô°Ý-3‰ZYrH9‰ûë ŠÔ#”¬§49ˆ ù ð¢ü¸ ȇO?┢l»x´sűÈN…"¦!Ú";Q¡w ´ÁÃl‚Áú}Q.|ôÓâë7XÜ Ï ßU×€o×ûzÅwûC¡ÿ‹ׯ³Ó;¹iÐÌÌÁŒQ¤— 6û4ZÍÐ8gžGò{Ÿüé XwßϸîŸV‹~ ñÑê®'m¬ÄÇ MõE«-úúÒèã7´úeq¹eó£6J¤¶Ý‡!‰M|ß'¯ŽÕ$7¶‡2gú•o…9ÔD‚ÑûQ¨÷'p{}å}>_:¿½ô.on~»Aß¡HDqLµqJÇø?(]@<@YUnò:¯J$ÅN %Ê:/’ möRK{!¨’°{»å剑í5ª=]œ¤¡Ñ  oÃk¾æJxÍÝhQ“œ¡A0†Ÿ¡È¢|¡BÇPÚ褭0ÅIñ âÇm©|»+¬·îd—½nÁÙ&d^íÕÄ>Ç–RlIB¦OЩpAàÒG Ó3§¸ç"HYèZ7ëïóƒ0Ý~CßËæÏBe2ß ‰9E &8dqšÌW¹ÒžÈcã«%j7ÕÇ`›­‘N®xÝKU–íe/>?ä…`MAmuSPû½ j^‹­¶w6åõƒèäã;.‡Æïú±)Þ~i'äT&tW~®# &«þ YWÄˮȳ¼.šî 9i¤3¾e|¯ ð=Fëj3’ºaÁºk&qœNøñ ¦¼ZòRñl>³a<§OXïA »ª(ªg›¼ð"ÿ»‰âò~ßäéhð,JiˆèC˹VHýÀ1ô3¨}Ktô8 ÔÓ´OØ~Ù¶±Y³$r`çÖéåñt¤‡‰îÚ,˜PÐ53ïMP·Ò%:svâ3LukŒ¢`B‰ÎRkUë?EV£¦úžvyùTO@¼¼„I,‡×Eg \ºœ˜ ~i¢”of͆.OMÐHAŸ 79¹Äz äuïŠ#ibD_'¢tB•N“ÑPBÝÈ<³R%í@¶ëªèæ‡Û¥Èò»<ãmu®÷²„Ìq}°ƒº³Ó‘ÂîàÙ_ž(7ØÊ½CO¼Ø 5î4v ¯K] èužA7¼NÁ»‚KM¬ZÈ;÷ÖÙyŠ%.O¤Ø¿TB¿ª¸<¼)× èß‘m¬ 'Û‰®—¶.íùïÂÄÆe¬Ë¦Y«èÜj'LÔ¢á[³sÀE-wdl]6êÉ!µ¼îŒÔ½CF6›ZJ޹ÇèT¦¢ÿŒ†Œ¹ ?†cür $â÷³/¸ä=•{#ã7‘÷G"—Ã.óH¢¯I³Ü B¸ìS6¥í¼W¡jÙ^ðyÓZ¿š³L1ÂNVëBl‡«öF™t7J)6gD¥T¾.ƒMå@á¡ff}8b{ÈS»U3u‚¥±[n=›çnë1œêÏÁÊÀ|WuÛ‚§ïé|Vј¥I”о TQÕÝåë8yI1‹õ7YNh:~yßÔ˜µßicMH×açG4B!NcŽÙúâ îýÇMÇÖ%l›2-^jQ*`.üvr½øD˜Óò endstream endobj 1463 0 obj [ 1462 0 R 1464 0 R 1465 0 R ] endobj 1460 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 1463 0 R /Contents 1466 0 R >> endobj 1467 0 obj 1316 endobj 1469 0 obj << /Type /Action /S /GoTo /D [1468 0 R /XYZ 72.0 720.0 null] >> endobj 1470 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 624.028 201.64 633.028 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1469 0 R /H /I >> endobj 1472 0 obj << /Type /Annot /Subtype /Link /Rect [ 207.955 624.028 280.145 633.028 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1461 0 R /H /I >> endobj 1473 0 obj << /Type /Annot /Subtype /Link /Rect [ 286.46 624.028 320.89 633.028 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1408 0 R /H /I >> endobj 1474 0 obj << /Type /Annot /Subtype /Link /Rect [ 140.56 612.028 193.34 621.028 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1396 0 R /H /I >> endobj 1475 0 obj << /Length 1476 0 R /Filter /FlateDecode >> stream xœÅXKsÛ6¾ëWà˜ÌX,|º¥nÚIÇcǶfzHs (ØfK‘ AÙQ}_(ZJ:©}b¿ý°û-ðËŒ ÿsý Š’ÍìK3FPD ›¡ DÄ÷h€6¨i(Ó³ Ú¶àÇL‚Æúc–Ï0úmöé3<\# /3lÃÕÆ÷³ÛýÿpÿCŒÐÿ…Áía"yVnjkfÆ`ÄéGY¶æ× š¦!g~’Â='<”†îsŽÑãìçåì§_D0Z>ô¢´!Á§BÿQ´Ü Oo(Þ~FËßgï—N6pÔœDjßÝz"XŽ1&˪“5‹2kºŽ7Ò,j$ >GTx8 ô|n îo¯æ—7××ï/—n®çïïînîAèìHÑÐî}>‚ðgÇÞ€O ¤È×i•9*å¶”JæUš?"Y–E©ÐzWêLÊe¢gµë‰FÖã Ø¡Á¾ì —ûm‰ã ….DDš^f±Rèc)¹–y"ÑUªª©ˆ æqLYA}Éæ=ùy½*;>“é0á\ ·0‰ÐÌÛž˜ÌÙ¸çu\Å«XÉQ¿sø`îÓè,¿„懿0"ã~GÝùÜãü”eªt³ÍÎ#ã`†ÏÜɲL‹2³çÈÁE¡<œr/Ðrôþå˜4Ù5tœ´é´†Ì1½@ƒuT¯k“0½Ù¦Šj„_¤JÊt;,Š1I’–À"!|Ö.ŸR5Vvª-ºê)®P‘$»½<¥™DU¹×UXm!êfŒZyy#áåØñ*ÑC‘eÅ‹†Jspgé?qÍ!.w›šBœ¯Qœ$R)ÍD~…‚[LÕ<Ôrô oŽF…ƒú6uãÚ/ºª©»Æ˜oŠ}Ëö]üw.l;òä,\€®zæ§³ ¡2PÆDf 5“Ðiü#í2W‚,ä`#FqUÉͶš¤Fmí—×~1ØLÕV&“Þ}[ƒç¦ÇèÓsÀ–Ø·$ÈY¦C³HÒÄÔNÉ5Ù‘œy“tC[”g&ͱï*jÒmd+ðÜl9n1Mà¶Ø¾%MˆNSë«¿êÝSo°/±‚ =ÙsŸª4OR8iL'ý] rí&JézÒ-±xf‚\€>A' ¶°„æÝYåHšÑçPŒ@é4„ÞDeš4=Ø÷LCí7«"ëÆkÂí£ƒÒ3c¥¬ve™5ÝÕ¾iTŸNÍŒ8ù{.óµ×ô{BÏq¶“Ê}Ç2f ^¿<•ÜÄp„N*@SðªK-¬J–1a[²Óó¿oãvíJê#G\îOËuø{· ЋíL*Ñôö挼¢»€·qq°š4kˆŽV;0P¢î½Õ3ZÔýNŒõC[zp(GÝ_uNªžÀP‘õ¤V’#Úãcd”Šþ; [ágÊб_l@Dñãä‹ÀǶxÏÔž à^Ɔw¤#4¨­`[w„{þ+ÊócÊÆÐÞõªªoÙ]];ZŒ5:1mY¬2¹>…7Z׫ï¥\_ , ¥ÒU¶LÊ€C}š‘Õþˆï¡J›©Z§®F}f[¯å©«Üm=¡¿#DPæCJQµðø%ËçG#&xÈéáû„qA€³¢tû N?vTY„ Ï'À“…ሣ㇇(õ£)¤‹SØÐ ò"¡¿2Ñè$6÷‡ÁÜ0fùú~> yP‰TУüÆÄ""kêÄ)ß-µŽ Ô[^k:6‘ð(i>£¸Æ—W÷·WÇS‰Á˜jñÒQÏòk%s¼•7ø¬y;û_³Á endstream endobj 1471 0 obj [ 1470 0 R 1472 0 R 1473 0 R 1474 0 R ] endobj 1468 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 1471 0 R /Contents 1475 0 R >> endobj 1476 0 obj 1373 endobj 1478 0 obj << /Type /Annot /Subtype /Link /Rect [ 216.739 624.028 288.929 633.028 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1461 0 R /H /I >> endobj 1480 0 obj << /Type /Annot /Subtype /Link /Rect [ 293.488 624.028 327.918 633.028 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1408 0 R /H /I >> endobj 1481 0 obj << /Type /Annot /Subtype /Link /Rect [ 140.56 612.028 193.34 621.028 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1396 0 R /H /I >> endobj 1482 0 obj << /Length 1483 0 R /Filter /FlateDecode >> stream xœÅXKsÛ6¾ëWà˜ÌX,|êæ8n§O[ÛêôæQÅ–"e’²ìþú.!¢­¦ã&Kìî·»€'aø?•?QBQº™<AE,4¢ DÄ÷h€6ÈŒ”ËUÖ€¶#øÑ‹`°F¿OŠ F?L¾|…K„Aa?Á®9¥|?¹µüË/øÝýÛ¡ÿ ‚Ûã*D4òœÚ(m¦e цä§Ü¤Íüj«z¨Áéß“ p‡ 'ÅÀ}?ç=L>Í'ß} ‚Ñ|Õ‘6’Š{1Mä?Šæôå¥ñǯhþÓäzÞ«æ;g­WHéûC cŒÉQXª¸‘ JÇô3ßÔ@üÑÄÃa ×ÇZáþöfúùr~ùéòþZ ¦×ww¿Ü!mä JÙ£}#P9 ) ßj±DM‰êì¡à9âUUVhŸ5kÔ¬\hÉ޶¼6k¹,x-¼6Äh DŸx8Áà+Ô¾®Êb™5YY ùËöœÓ9 / q’DÄäô*è×J¤b)ŠT ›¬nÆ’,s…!v’ÚBý˜O[ìj0UÑ^ È÷=‚>¸ÙiÄCì“W¬)CnîIè%4Øâ ¯~Ò+¥ÄócH ”jØë ³ ðÉm9«³Í6nàFš¶5꾸 E••»Z¯œ: çŽkcîxe{$b$›SOEÆx€âֲؤóT/Có:Ë“<À2®-|uZeÛÎõ0¹H!0È·ÏŒâ|Õ§)ÁċЇKV‰m%jQ4öB•a[ЬycMË4ÝUÖ|¿Îraë?‹t×dŃ%“Û¶›Õ oÄFº½°¥[‘f«,åyþb‰¹ …¯wù°Õ@ýe?Jˆ竲Ú@ï Ä³Ì@ i©½í„ö’*ЪÌór/Ì È(ϳ¿¹J,¯v*,h\KÄÓ,ËTŠgè ³±æD±ï8úLƒ½:Yô6“ŠÙ€þ¬‹lÔ1ô„cÅK»óœ¸z ñ‚ØP¾oàЦo„@]æZ”‰ŸÀQBC #ôŒÌÍiÑ@ûuY dø ó”ïÔ+àÑóƒú.“Î,QOÖvëQ·KÁs Ô3ÐèMB—Zÿ¦<=#²<­{T.þiƒT£ÙÆϊ§2‚Òd…ªNV¤œ±Íx"—‰g¨§?ÓYÊ–£nc—yç¨gÀÚAoøG „¦A{¦Ÿ(#ò&¦d™´…Z[•¥fVVfP¿le~ëëšùÔ6ôöÔ dÓnvU•ÕÓÅ‹4?R˜<ýk*Š¥gæ 'žïDÝoÚpOw‚ݸ^4YZ£rœ‚£‘W’X¨V.o-ØQŠ1úmmº¯?«…<˜yõò¶Z³ol×}Ù΄â·m4eäÞq›—ž-Sf¦®xV+°˜(§šoj¥ÅEF,2ª.¥Ð¦£œ/Nš€ÍHµ¨¥ä÷¡ ¤™Šþ;F.ÃϤaO¶ñ‡Ñƒ€Å.yÏå^Ï@ÿ$š¾HârØe‰=ÿîù1eCÖ.;uSµY5_*G‹#™aŠžl«r‘‹ýÕ\žÕLÝ+±¼°4J¸œ,Ì•W/*,ƒ6Cµdñr·ÍS³T2µÏR»Û­cóØãćæ‘È7tÛ@ÿ]¡lÚ<ü,ñCâш%qÓnCÔyÙX÷ã“ì!TÞ! %þ€©Ó™Ê@Y¾ðü€ XR{ó$ `/ÔGd0 £áíað ‰dnáY=ÚA«ö”ãÕ ÍÂp@ùê.¼§«eMäÛ”ùlȳxnDa¿„Ôß¿n'ÿ·ù?7 endstream endobj 1479 0 obj [ 1478 0 R 1480 0 R 1481 0 R ] endobj 1477 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 1479 0 R /Contents 1482 0 R >> endobj 1483 0 obj 1384 endobj 1485 0 obj << /Type /Annot /Subtype /Link /Rect [ 203.184 624.028 275.374 633.028 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1461 0 R /H /I >> endobj 1487 0 obj << /Type /Annot /Subtype /Link /Rect [ 279.698 624.028 314.128 633.028 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1408 0 R /H /I >> endobj 1488 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 612.028 172.78 621.028 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1396 0 R /H /I >> endobj 1489 0 obj << /Length 1490 0 R /Filter /FlateDecode >> stream xœÅX[sã4~ϯÐcw¦1’lù’·R SØm7 Ã,û Ûjkð%µ”¶á×sä{d%m¦´–ŽtŽò¸ ÃÿR‚ˆ¢¤XÞ^Üþ¾¼º½ýx‹Z ˆƒ5OfÏüAi`2„ÇЯR¤HUHf÷%ÏGJ›ªæõ‰º®j”•H=”rÅc.Šyò—(S§w,°8æÊƒ¿ÕrY•i¦²ªDëÝfÉáHú‘ÃH&“.’—9—}ªE"RQ&]gR mä:!¦ 9b­ù˜/×–kçèòÇGgfÈ\âÐØž]RVÁN±ë¸ ÐpÏØj¥¨Q©Á̮ժ̣ÑAd‘ÅëQ™ÌŠM.LÇ;jÒçg\17Š:«¶r²Ó°bN0³=p˜AÆØ ÄÀÆzŽ&F©×!C\]ŒÆ^ØAû;!“:ÛŒªíH!,t˜ †xnǸ~È$8¾$ÄñÐÙ`ÆHªÅ¦R”j²­‰×d^%ɶ®³ò~$=?ˆ‰}¨†ÉpºFµ¼,+5™ƒ4ИïFÒ¦®!':ù8|ây–ŽÓ¬T¢æ‰% :º"ïE  ßJqŽî ˆ®ArŽ2… 0ReyD‘l•vƒ™¢†t/S´©¤Ìb°3“r µ%Þ [@díXôGt–ªó¼zÖ²âþüÍ›4ðú~[4Á×êx¢c C/^ &¬Ž•%Š=CÑ ä­ÐA„„p¤\·Ðµð¯úÄUK|ƒí¢3zÔ™|qX¨+¨ëY Õ`ù&¨ ñÉÙ8â;BF}m„ïY„¬§×Bÿ)WWè™KHÚS•?Aþ»û#+“ J·:zoPÏD≠šñ¯Ú(eéQµÌà© š ô&|Xû BKÖ_Òä}©û‘EÔº-4 ¡„sSgI7ƒ£Ý䮈«| ·×~·´Iv—%¼/€LW?µ­K‘vÓx× Ô gZÍôè–ºeèæ£AP¥¶BÎ+ LÀë£.•%Uw€)¨E¼ÖÀ‚ÒvÇ¡'è=±Ð„ñ‰›ñ¯¤ÐwÄÐV¼’kôïÀ60‚íDSˆ [v.yw,ìâ2—Õ¥Y‹Ìê $êi‹·fç‹z>€±Y4Ѩ‰S8êy<(Q£SD6›zHαçRÛj‘Šþ3º®‰ðÓ`8ç_"~ô"p=¼§bo&`~-ßbˆobØD ußr{ƒº6i£©†.¬™§¢xÖ÷ba×VŹ(¦«\³¶±éù„£oyÆMåDà¡-%Þн×¶[5R-( Ìã6}“n“!bN¤Ÿfƒö‘Z©¾Ûd2‡Âs&ôC:™CwÚ7_‡ÁCHo!0„Ì"ép3³^¶Ž«›F¨E’nMù`‡?ãö˜£ßV \ ÷å5<½«€Y@›MµxQ¢”€\gòÆÍâ›`¾ž endstream endobj 1486 0 obj [ 1485 0 R 1487 0 R 1488 0 R ] endobj 1484 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 1486 0 R /Contents 1489 0 R >> endobj 1490 0 obj 1320 endobj 1492 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 624.028 201.64 633.028 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1469 0 R /H /I >> endobj 1494 0 obj << /Type /Annot /Subtype /Link /Rect [ 207.955 624.028 280.145 633.028 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1461 0 R /H /I >> endobj 1495 0 obj << /Type /Annot /Subtype /Link /Rect [ 286.46 624.028 320.89 633.028 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1408 0 R /H /I >> endobj 1496 0 obj << /Type /Annot /Subtype /Link /Rect [ 140.56 612.028 193.34 621.028 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1396 0 R /H /I >> endobj 1497 0 obj << /Length 1498 0 R /Filter /FlateDecode >> stream xœÅXIsÛ6¾ëWàèÌX,nÐ-uÝN:nSÛêôæ@Q°Í–"e‚²ãþú>à"€¢¥¤ãÚayÞ÷=,|œ„á®~"NQº™=š1‚"ŠXh†‚ߣÚ ÓP®¤ Ú¶àG Aãý1+fý4ûô&׃Âó ÛæåÛÙõÀ¿šÁoî#ô‰àz…ˆFž…M£ÍôŒhCj*7i3¿ÚªnêàôïÁ pOŠ ÷íœct?û~9ûîÇŒ–w=i#¥H°S®þ(ZnЧ3Êð»Ïhùóìré ùÆYs€T¾»õ0DØcLö–Õ€™Eé5ýšl„^ÔHüQîá0Pò±V¸½¾š/?ürùñ÷åüòææã Òê Ê·¨ÿIid+„S (-‹uVge*±­„E÷HTUYIôü ”(¡B¤Tm„Då®öÚuE#ëò‰‡97¡vsÑyY¾l»ŒNdȽ€ÄœGÄ$ò"O¤D¿U"kQ¤]e²žÊ,g^Œ)Xæ¶ óy¿Žy³@;Už©ì0î8Gï@ˆàΙ­ÈÇlÜó:©“U"Ũ_Šcø îÓè$¿燿0"ã~GÝù±ÇÇ,Sf›mnbï¸3œs…E••;©¥çV,€Á‚1¹/Æ^ ˜©}ÌQ1èêpX‰Ç¬!óGTÏÑ`õëÜ$Lmú.¨ÆÂB¦U¶í]S’°qî3£¸|È$d*ð|tÖ¢èê±1EizõCR·í2MwUÛiжm³¥`7ÕTrk`W÷êYÞ m«2Rª-ÁŒÈrÓÍ–[Q%*foVµË[«è®ÌóòY™Ë Xm’gÿ4PRÝï6Íb“b’TyU‹_ ÐS{ ‰©åè˜{ tXϰ®WWÑUk=Ø­F}sßÒ}o"ïs[CYÄ-]ÕÎŽ‚âÐ22`äDf U$¡?f¤%ŒòÈUH±ip$u-6Ûz24bsþ4p\ýÅ`—[‘Nzg6O„Ç5ÐÃsJ¾M±¯È1²Ü‡CE‘Ýe©.¨k(²˜MžÞ4°Iy"hŽ~WQ“nC›§¢åp‹i2€È&Û×ÀäQ0u›o¹ú @ÍæýœH@è©ÌŸz¨²"Íà†ó @ܦå‰9ú ¥l=å–a›'äè:*bk 4ïîH`bDÝ{B>bjÙ•ÊB'Q•¥¦WV¦!_6«2ïÆ›€Û©½ÒÓc•¨wUÈêîêÅ4êÎÏàDn$’ôï¹(Öžé÷=%ùNH÷ŒeÔ&¼:<¥Ø$p‹Oáš~œ‚+FR)bÕ¢ºKàêÜ;I1ƾmãvõR¨;NR½‡uð{·k 'Û‰¡„ÓÛ7š3ò ͋cËÀ¬Ltaµ&ª®æ[#9à¢êwdl&m6ªÁ!UÕ9©û†Œl„ZJŽp/+ ÍTôßÑ0¶~" ýÜzer?y0n“÷Tî9F®uGâ›Ã6óà~ä¿Â=?ð1¦lÌÚûÞ„¬+}Ë7ýuãhµ7f˜¢;ð4Xåb3œm$¦×h”ð’Xå/¡b`pÈP=²z9à{ÈS#ª˜ê²Ô§v¹õlžzäÁkÜãê Fe ?å”u»?ïü(ðhȇ1Ý?Q`+d༬Ýþ‰ÓäaÜô0fa8âèð5Ç ”úÑ”¥óc¢¡AäE\}ç¢ÑQÑì½`œ¦Ì sV¬‰Ï§€µH9=ßYâÈ¸ç»¥Ò ͦ×ꄎNÄ=JÌWùâêöúê0””©"/õ,¾Ô¢·ôV¯gÿæ§Ð/ endstream endobj 1493 0 obj [ 1492 0 R 1494 0 R 1495 0 R 1496 0 R ] endobj 1491 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 1493 0 R /Contents 1497 0 R >> endobj 1498 0 obj 1417 endobj 1500 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 624.028 201.64 633.028 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1469 0 R /H /I >> endobj 1502 0 obj << /Type /Annot /Subtype /Link /Rect [ 207.955 624.028 280.145 633.028 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1461 0 R /H /I >> endobj 1503 0 obj << /Type /Annot /Subtype /Link /Rect [ 286.46 624.028 320.89 633.028 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1408 0 R /H /I >> endobj 1504 0 obj << /Type /Annot /Subtype /Link /Rect [ 140.56 612.028 193.34 621.028 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1396 0 R /H /I >> endobj 1505 0 obj << /Length 1506 0 R /Filter /FlateDecode >> stream xœÅXMsÛ6½ëWà˜ÌX,>øèæ¦I§OÛšé!Í¢`›-E*Gýõ]I-%Ô>±»ûÞ ?ÍÂð?×?‰ (ÛÌ>uc%±¸ŠbD€Fhƒºv„ =kÔ ‡ü˜IÐxBÌÊF?Ï>|„‡k„Áày†mw­ñýìv_?Áß=þ#ôAp{ÌBB“À⦵ff FŒ#ý¨èÒÖý¯¦iÀ™ß“ ð€ û“ÒÁý~Á1zœý¸œýð.B£åà ÚDp*ôEË úðŠ2òú#Zþ:{»tØüÎYsˆÔ±ûõ0D€XŽ1&GËjÉMºE™5ý–n¤Y”' !GT8Žô|n îooæï®—×7ó·ww¿ß!cÜ›1È8&®ñŸ”&¶A4e€²ª\çM^•¨–ÛZ*Y6yùˆRô6id]W5ÊKXÃÀ*UR›”2Ó6‡…%ž…N,0DŠM¤7} å~Û§ät&cD„ ‘.“oŠT)ô¾–™\Ë2“è&WÍTj 8¦àYDƃúTÌðóvmv¶ C1Ó bÂup…^Ã$F@<¯lC"Š`2gþȇüyãRÌ‚yH“‹âRP\kvâë ò€ós–©òͶè0{Æ{ùŒŸ¹“eW;efÏ-,ÀÁ‘¡sy<3æA¤Å›èÌ1éØ5pZIÀ4­1 =¦Wh´Žæem¦w}Íïêè'©²:ߎ‹Â'IÁX"DÈ:ÃåS®|E¨Lé)TeÙ®®uM>?É5OÒW‰¼”*ªòQÖh§ÒU!O¢9vâKôPEõ¬Cä%ÀH‹üŸ´ušÖ»M &-×(Í2©”Æ$¿@é-¦ªŸjú\ƒ¿:™:dØTk¿èë§í¾Ø‡–íu‡|.l;Bå@\}ÍÏGAbËÉH#Y ˜4ÖHâÐçäÀ½ŽÌÕ­"FBH›Fn¶Í$4j«ð2r\ûÅh[U[™MFm ^Jã` ç‘-±¯!Èq²<¦C£ÈòÌÔNɵ>Mýœ“pc[”’æØ÷56±x)[Ž·˜&p[l_C“ãd9ÞG«Õ_À°’6è9UÀÐçªø_H# j‘ zŸO,"±¦NÜóÝR‹©ÇC»élbÇ&%Ý'×øÍÍýíÍi*1S-^ê,¿4²T€[£o·³\Ø»2 endstream endobj 1501 0 obj [ 1500 0 R 1502 0 R 1503 0 R 1504 0 R ] endobj 1499 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 1501 0 R /Contents 1505 0 R >> endobj 1506 0 obj 1374 endobj 1508 0 obj << /Length 1509 0 R /Filter /FlateDecode >> stream xœÅR=Â0 Ýý+Þx7sÒ´ëI‚­ºH ˆ‰¯(ü|’&@c-Éà';Ï~¶s w«ˆÙ§á¦È.[@•X4ÈØb_u€\P0éQ˜Ñžcš/Bp„#ñcº–üKu§~Œpïõ» Œ–·(¨ï·àÄ©‡Ý´l“|Á“ÅÐ.-Û”5Á$.Ù—¢ø¦‰ÿJ–Û_qÆ–¾=},4ÃonŸÖE¢fUJÀ7˜ˆ‘Ïü”~üÓ6{žÚÓ"cík?2Te+þ®-«,›ªr%D+)3Eên²_­Oþj:nJÁ endstream endobj 1507 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Contents 1508 0 R >> endobj 1509 0 obj 240 endobj 1511 0 obj << /Type /Action /S /GoTo /D [1392 0 R /XYZ 72.0 720.0 null] >> endobj 1512 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 654.764 284.97 663.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1511 0 R /H /I >> endobj 1514 0 obj << /Type /Annot /Subtype /Link /Rect [ 330.0 654.764 412.22 663.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 750 0 R /H /I >> endobj 1515 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 642.764 293.87 651.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 854 0 R /H /I >> endobj 1516 0 obj << /Type /Annot /Subtype /Link /Rect [ 330.0 642.764 422.78 651.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1355 0 R /H /I >> endobj 1517 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 630.764 226.66 639.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 90 0 R /H /I >> endobj 1518 0 obj << /Type /Annot /Subtype /Link /Rect [ 330.0 630.764 392.22 639.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 589 0 R /H /I >> endobj 1520 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 618.764 204.99 627.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1519 0 R /H /I >> endobj 1521 0 obj << /Type /Annot /Subtype /Link /Rect [ 330.0 618.764 386.1 627.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 634 0 R /H /I >> endobj 1522 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 606.764 232.21 615.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 139 0 R /H /I >> endobj 1523 0 obj << /Type /Annot /Subtype /Link /Rect [ 330.0 606.764 531.64 615.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 484 0 R /H /I >> endobj 1524 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 594.764 260.54 603.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 87 0 R /H /I >> endobj 1525 0 obj << /Type /Annot /Subtype /Link /Rect [ 330.0 594.764 528.86 603.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 481 0 R /H /I >> endobj 1526 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 582.764 313.31 591.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1319 0 R /H /I >> endobj 1527 0 obj << /Type /Annot /Subtype /Link /Rect [ 330.0 582.764 435.0 591.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 915 0 R /H /I >> endobj 1528 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 570.764 258.31 579.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1177 0 R /H /I >> endobj 1529 0 obj << /Type /Annot /Subtype /Link /Rect [ 330.0 570.764 389.44 579.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 913 0 R /H /I >> endobj 1530 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 558.764 279.97 567.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 166 0 R /H /I >> endobj 1531 0 obj << /Type /Annot /Subtype /Link /Rect [ 330.0 558.764 418.89 567.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 259 0 R /H /I >> endobj 1532 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 546.764 207.77 555.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1351 0 R /H /I >> endobj 1533 0 obj << /Type /Annot /Subtype /Link /Rect [ 330.0 546.764 364.44 555.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 882 0 R /H /I >> endobj 1534 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 534.764 292.19 543.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 972 0 R /H /I >> endobj 1535 0 obj << /Type /Annot /Subtype /Link /Rect [ 330.0 534.764 390.0 543.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 189 0 R /H /I >> endobj 1536 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 522.764 304.97 531.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1090 0 R /H /I >> endobj 1537 0 obj << /Type /Annot /Subtype /Link /Rect [ 330.0 522.764 518.32 531.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 471 0 R /H /I >> endobj 1538 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 510.764 203.88 519.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 713 0 R /H /I >> endobj 1539 0 obj << /Type /Annot /Subtype /Link /Rect [ 330.0 510.764 383.89 519.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 969 0 R /H /I >> endobj 1540 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 498.764 234.99 507.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 848 0 R /H /I >> endobj 1541 0 obj << /Type /Annot /Subtype /Link /Rect [ 330.0 498.764 366.67 507.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 909 0 R /H /I >> endobj 1542 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 486.764 161.11 495.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1080 0 R /H /I >> endobj 1543 0 obj << /Type /Annot /Subtype /Link /Rect [ 330.0 486.764 428.33 495.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 768 0 R /H /I >> endobj 1544 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 474.764 167.22 483.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 79 0 R /H /I >> endobj 1545 0 obj << /Type /Annot /Subtype /Link /Rect [ 330.0 474.764 410.55 483.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 752 0 R /H /I >> endobj 1546 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 462.764 242.77 471.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 109 0 R /H /I >> endobj 1547 0 obj << /Type /Annot /Subtype /Link /Rect [ 330.0 462.764 412.21 471.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 771 0 R /H /I >> endobj 1548 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 450.764 215.55 459.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 254 0 R /H /I >> endobj 1549 0 obj << /Type /Annot /Subtype /Link /Rect [ 330.0 450.764 419.99 459.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1093 0 R /H /I >> endobj 1550 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 438.764 193.32 447.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 672 0 R /H /I >> endobj 1551 0 obj << /Type /Annot /Subtype /Link /Rect [ 330.0 438.764 452.21 447.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 788 0 R /H /I >> endobj 1552 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 426.764 214.44 435.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 740 0 R /H /I >> endobj 1553 0 obj << /Type /Annot /Subtype /Link /Rect [ 330.0 426.764 348.89 435.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 560 0 R /H /I >> endobj 1554 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 414.764 194.44 423.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 576 0 R /H /I >> endobj 1555 0 obj << /Type /Annot /Subtype /Link /Rect [ 330.0 414.764 407.76 423.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1396 0 R /H /I >> endobj 1556 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 402.764 188.32 411.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 621 0 R /H /I >> endobj 1557 0 obj << /Type /Annot /Subtype /Link /Rect [ 330.0 402.764 453.88 411.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1469 0 R /H /I >> endobj 1558 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 390.764 254.44 399.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1198 0 R /H /I >> endobj 1559 0 obj << /Type /Action /S /GoTo /D [1477 0 R /XYZ 72.0 720.0 null] >> endobj 1560 0 obj << /Type /Annot /Subtype /Link /Rect [ 330.0 390.764 473.32 399.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1559 0 R /H /I >> endobj 1561 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 378.764 173.33 387.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 387 0 R /H /I >> endobj 1562 0 obj << /Type /Annot /Subtype /Link /Rect [ 330.0 378.764 442.22 387.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1461 0 R /H /I >> endobj 1563 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 366.764 206.1 375.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 229 0 R /H /I >> endobj 1564 0 obj << /Type /Annot /Subtype /Link /Rect [ 330.0 366.764 457.2 375.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1422 0 R /H /I >> endobj 1565 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 354.764 265.0 363.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 207 0 R /H /I >> endobj 1566 0 obj << /Type /Annot /Subtype /Link /Rect [ 330.0 354.764 385.56 363.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1408 0 R /H /I >> endobj 1567 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 342.764 201.66 351.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 408 0 R /H /I >> endobj 1568 0 obj << /Type /Annot /Subtype /Link /Rect [ 330.0 342.764 412.78 351.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 563 0 R /H /I >> endobj 1569 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 330.764 202.77 339.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1166 0 R /H /I >> endobj 1570 0 obj << /Type /Action /S /GoTo /D [1499 0 R /XYZ 72.0 720.0 null] >> endobj 1571 0 obj << /Type /Annot /Subtype /Link /Rect [ 330.0 330.764 421.11 339.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1570 0 R /H /I >> endobj 1572 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 318.764 259.99 327.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1294 0 R /H /I >> endobj 1573 0 obj << /Type /Annot /Subtype /Link /Rect [ 330.0 318.764 408.88 327.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 565 0 R /H /I >> endobj 1574 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 306.764 207.22 315.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 864 0 R /H /I >> endobj 1575 0 obj << /Type /Annot /Subtype /Link /Rect [ 330.0 306.764 405.0 315.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 994 0 R /H /I >> endobj 1576 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 294.764 223.88 303.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1353 0 R /H /I >> endobj 1577 0 obj << /Type /Annot /Subtype /Link /Rect [ 330.0 294.764 419.44 303.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1334 0 R /H /I >> endobj 1578 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 282.764 222.77 291.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 257 0 R /H /I >> endobj 1579 0 obj << /Type /Annot /Subtype /Link /Rect [ 330.0 282.764 392.78 291.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1349 0 R /H /I >> endobj 1580 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 270.764 271.65 279.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 452 0 R /H /I >> endobj 1581 0 obj << /Type /Action /S /GoTo /D [1484 0 R /XYZ 72.0 720.0 null] >> endobj 1582 0 obj << /Type /Annot /Subtype /Link /Rect [ 330.0 270.764 450.56 279.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1581 0 R /H /I >> endobj 1583 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 258.764 183.33 267.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 120 0 R /H /I >> endobj 1584 0 obj << /Type /Action /S /GoTo /D [1491 0 R /XYZ 72.0 720.0 null] >> endobj 1585 0 obj << /Type /Annot /Subtype /Link /Rect [ 330.0 258.764 433.88 267.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1584 0 R /H /I >> endobj 1586 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 246.764 226.1 255.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 144 0 R /H /I >> endobj 1587 0 obj << /Type /Annot /Subtype /Link /Rect [ 330.0 246.764 414.45 255.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1436 0 R /H /I >> endobj 1588 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 234.764 172.21 243.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 911 0 R /H /I >> endobj 1589 0 obj << /Type /Annot /Subtype /Link /Rect [ 330.0 234.764 400.54 243.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1415 0 R /H /I >> endobj 1590 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 222.764 181.1 231.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 675 0 R /H /I >> endobj 1591 0 obj << /Type /Annot /Subtype /Link /Rect [ 330.0 222.764 445.55 231.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1331 0 R /H /I >> endobj 1592 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 210.764 202.22 219.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 748 0 R /H /I >> endobj 1593 0 obj << /Type /Annot /Subtype /Link /Rect [ 330.0 210.764 435.55 219.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1077 0 R /H /I >> endobj 1594 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 198.764 182.22 207.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 587 0 R /H /I >> endobj 1595 0 obj << /Type /Annot /Subtype /Link /Rect [ 330.0 198.764 367.78 207.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 194 0 R /H /I >> endobj 1596 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 186.764 176.1 195.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 632 0 R /H /I >> endobj 1597 0 obj << /Type /Annot /Subtype /Link /Rect [ 330.0 186.764 438.33 195.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1341 0 R /H /I >> endobj 1598 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 174.764 242.22 183.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1200 0 R /H /I >> endobj 1599 0 obj << /Type /Annot /Subtype /Link /Rect [ 330.0 174.764 408.33 183.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 597 0 R /H /I >> endobj 1600 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 162.764 268.87 171.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 438 0 R /H /I >> endobj 1601 0 obj << /Type /Annot /Subtype /Link /Rect [ 330.0 162.764 439.99 171.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1044 0 R /H /I >> endobj 1602 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 150.764 222.21 159.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 888 0 R /H /I >> endobj 1603 0 obj << /Type /Annot /Subtype /Link /Rect [ 330.0 150.764 503.33 159.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1288 0 R /H /I >> endobj 1604 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 138.764 199.99 147.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 192 0 R /H /I >> endobj 1605 0 obj << /Type /Annot /Subtype /Link /Rect [ 330.0 138.764 445.55 147.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1299 0 R /H /I >> endobj 1606 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 126.764 213.32 135.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1085 0 R /H /I >> endobj 1607 0 obj << /Type /Annot /Subtype /Link /Rect [ 330.0 126.764 473.33 135.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1254 0 R /H /I >> endobj 1608 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 114.764 197.21 123.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 685 0 R /H /I >> endobj 1609 0 obj << /Type /Annot /Subtype /Link /Rect [ 330.0 114.764 478.89 123.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1257 0 R /H /I >> endobj 1610 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 102.764 257.19 111.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 155 0 R /H /I >> endobj 1611 0 obj << /Type /Annot /Subtype /Link /Rect [ 330.0 102.764 418.89 111.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 861 0 R /H /I >> endobj 1612 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 90.764 204.45 99.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 869 0 R /H /I >> endobj 1613 0 obj << /Type /Annot /Subtype /Link /Rect [ 330.0 90.764 503.33 99.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1249 0 R /H /I >> endobj 1614 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 78.764 230.0 87.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1236 0 R /H /I >> endobj 1615 0 obj << /Type /Annot /Subtype /Link /Rect [ 330.0 78.764 473.33 87.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1285 0 R /H /I >> endobj 1616 0 obj << /Length 1617 0 R /Filter /FlateDecode >> stream xœÅš]wÚ8†ïùºÜí9Jmƒ1\ [$NåH¢íö‚¤I›³¤éÇž³»ÿ¾ú0$g|‘m.ðüÎ3#Íx4ôû DúÃú%™Fèöqð½~/DI„†ãú­xŒÂÑY£GT_Çh«¿upí®Ô‹ý’ºø‚®_:|ø¨>ü„uÃ?ƒàXÎÜ,Wöõ'Á«Û?$†ÑÿBpÕ^…$JÎŽÖÆÜ=´ï©w¬þh[‡­~µªöÒÂÙW'T°g N¥Æ}=ãú<˜ÉÁÛyŒÂÉûý¦Môap6‰¦ú_„ä#úð[4þþÉË•ÏVó•£öl!µíÆŸ! ÕÂN‚ [n™ÅMj§¬OåæñÎ:u" £ ЦgÁ8ÖߟØÈöÛ—ÍÍÝß·›-Ê¿~ºûÝ?ý@ß6·m>ß¡´W²ŠN¤B9+œq>Wü3Š’ã"ß (Ý>(k7Û;ô`žîÑf»E?ÿ{¼yÚþlÖh"åH¬<·Uçô’hr6l-÷›IßÑ2Ãׄ—yyŽgô‚¼ÏsrDq#E.$ôjIË”Š“Â ~<ç$½ X’YA±Rç98£s²,¤›nÇò_XHNÉÂéA2{ÀÊ’¦çsLWÊŒpsÃÕ ·‰Žy€‘³&KɰX—©›.lhßçôÚ œÖnœ"¨›¸‡zÁRRkœåÂìA½GÔÉ(×Ñ‘dåô$„gê±'X®+Ÿ;p;wh ô&‚§îΛe¥ü¡˜Í.U¼ +\ÐÒãÜVÁX…çŒc"°\Vžl‡ð Þ9¢jƒ®Ÿ þ\^xøá&¤2ÕmíÄŽáYœ—¹ÌI‘ÿA³öŽòT v*Îf´1àt` N=’e%Ù Wö‡:g•&•œ”‚¤2g%NÙb‘K|ÁØ;76Ü §õ³Ä‰>gÎ1:gE¡†x¸!N…düDÉQë«ÊƒÓ¥)8™ˆTy:[J»ÙÝ>À•wÁqÁê(y¢¿q÷´ðì—(§ŽÝÚnD¸â®k¬»#\9i‡àŒñå‹Á…K6¸îÀŽÀùQ£ÔjÏF€Ë7Ø%]¹±cpJ¤*—eGù7ÈpiA¥iC=[N3'ðœ³Ìy™ÑÓ †ëjà&鮨Nî <÷,÷΄.­ª²t O; jªš›®«Ÿ*O2o`‡<÷,¯>™8q{ÈÖ¸:­õ£•rθ“:ì›zšÏ9[àT•$wÑèaA;ÐtŽú¢Ã‡!8e:ëF͵xN”F¸$ 5\¸E]jœÜðM‹ÛnQÑÔíÜ„öÀnø\¦unqÃÂ… ìªR]©ðÕøDFmJvd#\Y#ÏU<º¢ ŸËdªK4DÕŠëg—>hðÌ7¡áYE9ñ•î|>S£w÷PÞ»c=‚O`jàl{ˆÛÕ…T8;é|Â’©ãgëîF¯‡vG,40|¤Ør¸-.é¢bœðµ?-GðÉŠr¡ëÓCÕ0ç Ê–²ƒ>XÙ«þ—4sƒÃÅ5øR¨uôSÃç*ó ß ,\SÃv<ÅGð!JÆYÕqn顪ª>—¸U;œÌð¡‰aî<³ô¶ØÃ+t Ÿ›hÿù¥‡ªžt-£é>;1˜ÞcKQ!õ‚½d7ÄðñICü’#K};Ië%Åð èû#*؆äË2í§h~ø4…®hªg¢zšBJwaî!]ÿÀÓ´fe}™ö>^™«Â×Ýô>úê’)OœÜðÙJ^¶&ì§7¥A‡k×è6Øõ±®`ÎaY Ÿ¹˜§?¡ ;\ÙÁîþßð Ìþ'0ü²“d-7Üððé‹Ú…T=ຎ6=”ÛÈ6ô»ìu:Äœ'çê }ái{¨×Nè-sXqLè¿_؆ endstream endobj 1513 0 obj [ 1512 0 R 1514 0 R 1515 0 R 1516 0 R 1517 0 R 1518 0 R 1520 0 R 1521 0 R 1522 0 R 1523 0 R 1524 0 R 1525 0 R 1526 0 R 1527 0 R 1528 0 R 1529 0 R 1530 0 R 1531 0 R 1532 0 R 1533 0 R 1534 0 R 1535 0 R 1536 0 R 1537 0 R 1538 0 R 1539 0 R 1540 0 R 1541 0 R 1542 0 R 1543 0 R 1544 0 R 1545 0 R 1546 0 R 1547 0 R 1548 0 R 1549 0 R 1550 0 R 1551 0 R 1552 0 R 1553 0 R 1554 0 R 1555 0 R 1556 0 R 1557 0 R 1558 0 R 1560 0 R 1561 0 R 1562 0 R 1563 0 R 1564 0 R 1565 0 R 1566 0 R 1567 0 R 1568 0 R 1569 0 R 1571 0 R 1572 0 R 1573 0 R 1574 0 R 1575 0 R 1576 0 R 1577 0 R 1578 0 R 1579 0 R 1580 0 R 1582 0 R 1583 0 R 1585 0 R 1586 0 R 1587 0 R 1588 0 R 1589 0 R 1590 0 R 1591 0 R 1592 0 R 1593 0 R 1594 0 R 1595 0 R 1596 0 R 1597 0 R 1598 0 R 1599 0 R 1600 0 R 1601 0 R 1602 0 R 1603 0 R 1604 0 R 1605 0 R 1606 0 R 1607 0 R 1608 0 R 1609 0 R 1610 0 R 1611 0 R 1612 0 R 1613 0 R 1614 0 R 1615 0 R ] endobj 1510 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 1513 0 R /Contents 1616 0 R >> endobj 1617 0 obj 1444 endobj 1619 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 709.5 233.88 718.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 716 0 R /H /I >> endobj 1621 0 obj << /Type /Annot /Subtype /Link /Rect [ 330.0 709.5 402.21 718.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 642 0 R /H /I >> endobj 1622 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 697.5 205.55 706.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 727 0 R /H /I >> endobj 1623 0 obj << /Type /Annot /Subtype /Link /Rect [ 330.0 697.5 412.76 706.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 289 0 R /H /I >> endobj 1625 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 685.5 187.23 694.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1624 0 R /H /I >> endobj 1626 0 obj << /Type /Annot /Subtype /Link /Rect [ 330.0 685.5 461.64 694.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 300 0 R /H /I >> endobj 1627 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 673.5 203.33 682.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 267 0 R /H /I >> endobj 1628 0 obj << /Type /Annot /Subtype /Link /Rect [ 330.0 673.5 429.98 682.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1120 0 R /H /I >> endobj 1629 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 661.5 187.21 670.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 677 0 R /H /I >> endobj 1630 0 obj << /Length 1631 0 R /Filter /FlateDecode >> stream xœÅ•[OÂ0Çßû)Σ>lö²±í±ÀЙ…Á&W# ýøvt„ (f˜à.9'íÎÿüÚsš­¬n+5^@a¸@ëlŒ€GU²!·Ô±© È|æê«¼C·ž2ú#åÌ ‹–Ã-êÔä° øBx_n,P+—?ÁÏaŠªÝ4\ äd·E,°}â_aàÛŒéEA. Åç«Yò2þ|&sˆ–£ñ÷õä}.س×Řø (Þ‹ž¼À*¾%Ó1ÔbÑŠup( ûÁý‡ýhTOxÔ³÷:E½ŽÍô˜ÑBéÔ<+bfµªv5œ¶F(¼cÂy¤b“\4¹¹?¼4`Û/Ô–2ÇXÍ ïÚA!‹Ut|Ý^æ⃾#!-.e;ªvdhÉçÇP].uÏPŠÂ®öTa=•UÌ„þ ÚÌ[^¹É;«Î%¯rš€Õ9<¸s!NЖ—Õ´aƒwbù+µþ”¦ÞÊš¹Ë o¸e›7¯Éè¡iBVÏ9ÈQ³öNkY} ~s;ƒ³ endstream endobj 1620 0 obj [ 1619 0 R 1621 0 R 1622 0 R 1623 0 R 1625 0 R 1626 0 R 1627 0 R 1628 0 R 1629 0 R ] endobj 1618 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 1620 0 R /Contents 1630 0 R >> endobj 1631 0 obj 406 endobj 1633 0 obj << /Length 1634 0 R /Filter /FlateDecode >> stream xœÅXK“Û6 ¾ûW°É!ÞLLSoio›4ídÚdíL§ç@KÔZ³²¨Õ#Žûë Š”([’7§Ô;‰H òqf  ñð…ûÙ£’È3‘å*‘ã"ÃÆ¦ƒöHÑJÅW=Âl)xȀء¿gÙŒ ÷³¯ßàe„ 8Ìȹºfðjö¹7¿xC~ùü} ,Ãü_,ø|º žéá³µiF[R©H¼Jlê)µJR'Ÿ“FmE™ûë&'è~öz=[¾sAÐ:ÖAë‰Á¾ˆŸ‰Ö{ôunZÎÕ7´þcöv=XÍ_ŒÚ`!ÅÜ?2mì7ÆŸ¸Ei`Ó÷!®+}ºÉs–EÉtƒÑï´¢[Z2ôš† —ÒÝF!ÁlÚSmŽ‹mbÁ,–%µ}àôæãêóG'0Ñ,B)§@ż`É}†Òd[Ð"aêö¶|‚]ôú†!õ¾ãºB Ûš—|Ï4µFw’꘳R³ÒžŽÝÑÞ»ŠkZØ©9ö£bEFS-i=Ð’mã Ö¢õŽõ-¡E©Ëš¦é±ç£E¸cÑÉšI2 Q˜À<¦Ú53Û °¼iiIÊCZ%<+µèdÏYd÷=%Dzb{Í×%ëÞÖ•f޼ÖLH³Þ$,M5×.µ{¾Ô–áaâûÄ0½¡kͺMF‰eÃÐÀ #°‡c{–ð>üAsIÖÇ—B³QR°°â:Pû«`ûl>S®… 4?(ß%·=jº.Ò’U+!™¸ÎB±RZÒºœ»n¸vœ€dzGlip»þôeõaññöõÝÍÝ?‹O7ëÓHÔùA@F]ÓÉàº%±J{’=Í’¼N»Èñ·ÌY˜Ðt\Ã=³à;ì2ºMÅ`ÃÀþd|;I¤¸=˜—ïþº{{ûþÏœÕÛ›»7ŒV/'Q2¿ÑmgD5îl»_utIš‘Þ«;È QÇÊœxìóù#.y'È‹X4‚•éƒ!¶Œ„Æ‘A>ñ²º/˜Èze缨PR¢&À¤I†„)m€Ã¬ShšÁ†(nàŒLµäyµŒ9_^ˆ,h> Ö¦iŒ(@íB ´§á.ɘ`^DΤIÂg×ÀŽÐjCÒz6ó0-Óë¼.w æ"§Õ=ëŒ|¶¹ÁϳÎu5¿Kµ ò 6ü€rÜŒÙ2Q`±|CVõ~ò‚j‚oñé¯ÕúýÝ[Y„xÏ£:eXq›ùŸ¼bƒ±UA“T+-SZîM·ü;ûms¥ØÛX25 ê@³ªÕÃòýb÷̹j±sH˸Õ‹ÖßÃÆQë)uQGߊnV¿¿CU,ÜeÉcÍàõk‚.æiÊbÐåõ¥u6­,Žåùzm6óˆÅ{Víx„hÅ×PÀý=º¦1lx¿™sùFØ·à¹Àfè§cŒ(êqÿØc ÿ7Sˆ&g¡ æ‹&7WòodJ‘÷,#ð}ÇêO¹iR?t‚’úö[.8I,2 í΋çÃèÅsFg™r¨™1‡vÞ³ž #Š}ï²âçùÉfÕ—¶|Šâ~ ‚ñ&ŠQ$E%2«iBÓ=/“Š-šzCX¶Ò$ƒOišüKUY•bÙ¦HzË:2â™fÚ:-¹Þ€ q"·°äš=(I¹…õG3øÄº½dU¸lÖf1Õ²ŒÓ¯…‘8MÊ|ZCLr>L”fÓoRVå«–mö¿¢• }Hd—#èm'-˜ì¡-7d§¦ûf²4Ûž¬Cû.·ƒ&”~Û‡¡Ž<“¾5™IѺÏœvR¤ á–]Oø¯Ú݆äYEǺuK4ò};D¦*¤á’Uè4lņ†óäZÑ>Â3ÜÑ öä4Z6œ8q’3†=–'†BûâXÎp,‚ Kë´BßiZÃ鿉3 Ê`Á@™¯êºî?ôPhôM_,íÙhZšYßsÔôæ€õ6xïYêl¾–éÏE= ´l«Î´ZR°Çº RKª§”¼Ñd˜&¬©¬Š×Mœl¦w¹eÁù>pd¤}iû¿éÆÊó/ß\amÆ 0íyPKxÜw?9íØPˆö)WÅ5ƒÚ<’TñÜ4·R":‚–~™KLE&+ù¢©Ð"ð_¾ê>9ì’p×q*µþ¦…‘ä4º†m4¶aX¿¬Ëb .,Ÿ„Ù†€¿ w¦èº4´§ãâ”Þ Ý9Ê#I¦QGÊŽ¿cåÅ€ú*Éd}’¼¼dt~)‘ðKúþv§5ðËOZø%׃`ìfþl‘†Å1¯žu2!Úbß{ lÈ×D¡nOjë¥ÍïšTq¹Õví_. ÍAŠ àXØíÙ¿Éëh|ú £jƒ¬±^Ʊ½3[Ç…MJÀò@u>€dsá$RN/Ó´Y #±o»»-q¥%®Ð¦>¼kmðO,¤l¸p3luø†g“w+U•N–Âwœö™úö í!Õ¬ŽP ˆSAØ)lÊ\ïêôóì?ërÅž endstream endobj 1632 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Contents 1633 0 R >> endobj 1634 0 obj 1919 endobj 1636 0 obj << /Type /Action /S /GoTo /D [1632 0 R /XYZ 72.0 720.0 null] >> endobj 1637 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 73.5 159.44 82.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1636 0 R /H /I >> endobj 1639 0 obj << /Length 1640 0 R /Filter /FlateDecode >> stream xœÅWMoœ<¾ó+|lZA1Hi¥ôS­ú¾m’•zh{ à$¨€)†Ý­Ô_6»°»ƒ:=¤ÙH6¶çñÌ<öÌø‡ãjnßȘ‘´t~lÆ|"ááfH„Ä<&HI6}AŠ~Õ¨Ãî{¶ÙÎ-ùìT%o/ßìdF¨X9tîNøÒ9íßÏÐߟ’çÅÂyúFŸ’ÅõÎEA/yœÅý#‹’|ytyþÁýøéõÅÙâãÅÉ7²xï¼^L¬à>ûVœOt°LJ&½=~ï¤ù0fG ~ªØ¸~Ó¨CwPnhA¥èN':ViJíƒn³*¹ñ¢ ©’T>°ËXœRDÃÙÚšï›GNl¥Û£ÖY,ŸaÁº*×Ç,\^µª1*5²Ì«Î@pö §Ö©ªAõB4ºÉTã^ý„%š’ª+ -B3ò‚ŠÑL<EÓð>Âh \‹£_äß ½ŸTˆ&Ðè Ñ äàµ÷#4¦»2-¬]Œæá×/0(Q4 Ï@,ÍÁ)ˆÅÐ<‡/šç°‘íýS,D{ÿ6S¢ÝŸê®£7‹Ð”ÉLUMB _*ŽÏÍÉòDçfÓ• >+_wUÚΔŸ™¯T»R FÄçæ,7m^Í#‘œ—`næøäl ݺˤèÀœÃñiº3ªQÕr„8ó$²%wQ(äæÜ²REAlÛÞ*RÕeÚÕµj’V7d>¢Š/}OD”R?âG`§Gæˆ2Ìçä½Ap¢{î-ZX…¯uQèU^Ý{ IkH£—y¦²Þ°{%ÂC%¨'«„â#ø/?Ø#l}bJqDŒ¨u«*c­·>Õwn}©ËRWœ}zçmÙš–·"îÙÿóàX¥ xÚécÀ†”n½×ÞƒWäeë ÖM£»z¦èTbàn“åŒÂG‘`Ÿgî\ /8е¶A |ÿˆÅAWÏÕ·B HÈa­B”ûŸÕ†(×Ûk"Å(¯§:)”IA¸¢ü¾ÌÕÊM‹ÄŒ]Fä3Ûê×4äÿ×­"'Äå¾çkfÒ.Gsúz¼N™ñÔ6n‡ú¨¸ý°w„ÚÕµnZ,·CW?G‚6=@{î>.^½øïò1ÁÐÀ£AÇÒ^ëCç̇ä€[a!) mz>Þmÿõ‘Q'«Ã|ÁžüY]«*Ë×{k#é}aöÉx(d3TC2Õ&ya¾žx£3qîüª¶ endstream endobj 1638 0 obj [ 1637 0 R ] endobj 1635 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 1638 0 R /Contents 1639 0 R >> endobj 1640 0 obj 950 endobj 1642 0 obj << /Length 1643 0 R /Filter /FlateDecode >> stream xœÅXKsÛ6¾ëWàÔØ3 9Æ­;é¤{¬Lq YœP¤LPvÜ_ßŃI’ΤöA»Kìî‡Åb±ÀãÂEþ—â'Œ=”îZæ¢ÐC$Ð" ×w<ŠvHÓbTðZ ~Ô ¶èïE¹Àè÷Å—¯ð1CžxlN*ß-n{þÅüÓýcô°ø°Z\^Säb´Ú˜‘Ð!n AŒ"‡x‚„˜­vèËÙ¯I“¬ÎЇ$ý¶deÆÏ¿¢Õ‹ßVƒ)×û¦t;ÀËz¡3Zl©M” $ÊøTèuпʪ"8õ; L¸i¸Î?Õùü‡BÑÅN4X\³«ù“£f-¤ðÝÍ'ÏÇD¦R™´š ÷gjB—× 0Ò‰|Kg[ñ¦U°|¸xÂɼy×µígëyë^ð&ëij†8«çíÓ·Ùlûû„óçªÎf}xÀ[>~©öM^•IqÄ›ÚàöU=¿Oxš·O°m_Áâó.¦rêˆ j/wӼ̛íߟ«áý´ö°C Ûåuk”ˆ]éÌbäûN„qQ]±Oë\NU”VeÉRÁ-ùž¥­)«B€ë pb –B—(S×UÎÑ’øNˆÎØ«_ »OêdÇÖ‘—†n¶Ì0# æK™}ý,O“†ñ¾™¤™1z{÷¡fw·ŸŒ,c›äPô4Xù”×U¹ceOø”ÔùÒŽ|¦Ÿ¬ …ENtvÆ3ìп’eUz¾1×ûsóá9/ í{f`g†UWt¾1t¥ª§•Ô}%gÍElïcZíöyÁ²¥ZSÅ©7¹jà‹Ùщñ(:W(-r×"_× ¤†À$fãÌo°ãº®Ci !×.ÂVZº°“m•»¦Î˹¢ž£³šíkÆÌ@Ú¦‹d„—2ÖHtrKúã¡“,c|ÆÎ(í¤ êð«ûpxž±ž…ªt ó™³íQ¬åŒ=2š1Ûí±û WƒâíüÛTÙî¡Nt”Ù…SŠE•&…R'yÊîç2ÿ¾üµÚ%¹QæUúÉj]ó†%YÇË”Räêêærjš„Â4C¨up6Ëi~¼9‘=4p< E”t|ÄN玥 sg2b…erfAgm× ±¼^`—"'€†Q?ŽiHìÓzª¥2U˜Rx0h¹œàŒIeñ9.Š ìæhú¨Ÿ8ÖšÅW²2­_ö ËPkùG¡znä¸T´­Qd7 “8m•9 ÂTËݡԸÐsÞlå°ÞžW™p2‰œ{»1ì=¦Q[ZS¨7‡Õ¨>/VY–è*ŸbTZ=Ì4LK£+Æ‘Mþ¸+¡*¡š–…LѲ+r§”Suäñ¦7>cëÃÃCßɪvò ë®^W»Iƒ"®D£hA«WÉú0wÔoyQE ÒëmúW=˱Ɗ`ˆYäC‹Fh«R²ž/húBŒ;ÔiìéH÷`ßÉâ{-›ŸëF°\X—ØOò¸ÎO މƒa•c?Ò¾Wº©p¡÷>R¦~­ Œ¤d,ã†mýöµÂ3û×FRV³È=都ñ¤©>â/ó­¥OÍôʺêxÝ ] ÏË´g/ï ÖÕf¢õ1AoûbJr?¯á*^:,U-£& è~%êºÅ¸ÚC¶îþ°.r¾eY' U6°¦—bqÕÚê¡uÕTiU\tpÁU«¡xÏÁNǬ¶9Ÿ˜5$ñpÖ Î`ÕF…BMtIQ$º‡ÑÒDå˜bvÉ·Fcè}Åy¾.˜‘¨UWtvØí wõççó©gp§+Œæ¡h )jûN=¾ím| ÌÜp:Œ±ðâq€'Ùgj­ÇÑó6O·pB< #ÐõõG8Â2öŠ*æC_äBs©Û¶^eÞäI‘ÿ#Ã{¬8ø!`ƒr»¾¾ÈBK;{ñ ù>Æ!Õ“¹?Kx¶y_íY-šÕw’+ª$[V{ô.-øc±Ü«Ô¤j5§®Ë:å0 qb:º³OA§p[&⌶×k™ž«Z`Ù½*FmE6‘uÕN±m±s:ɪ§ßµ“ñ—½aÔ¡ö_¼v™[Š|/Â7QZàZ1ŠÀ ƯH‘Ñivenwp¿Ï7ºƒ:únÀeÓÇÆ4ÒYt÷{éû‘G‹©Ü ÄŠ†4ú†‡@[ëäSà„£ã¶Â‰çÀ·y Þ„ÂÉ'Á·ù¦|¼êYpÂÏk'<žz|Ó¬Äã ­ðšçÁ·¹¡S)pê‰ÐÖh«ž|£¿]ü ð_L endstream endobj 1641 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Contents 1642 0 R >> endobj 1643 0 obj 1748 endobj 1645 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 709.5 243.98 718.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1120 0 R /H /I >> endobj 1647 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.998 709.5 539.998 718.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1120 0 R /H /I >> endobj 1648 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 697.5 353.54 706.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1281 0 R /H /I >> endobj 1649 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.772 697.5 539.772 706.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1281 0 R /H /I >> endobj 1650 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 685.5 255.66 694.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1213 0 R /H /I >> endobj 1651 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.997 685.5 539.997 694.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1213 0 R /H /I >> endobj 1652 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 673.5 282.31 682.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1177 0 R /H /I >> endobj 1653 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.999 673.5 539.999 682.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1177 0 R /H /I >> endobj 1654 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 661.5 278.44 670.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1198 0 R /H /I >> endobj 1655 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.998 661.5 539.998 670.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1198 0 R /H /I >> endobj 1656 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 649.5 226.77 658.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1166 0 R /H /I >> endobj 1657 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.997 649.5 539.997 658.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1166 0 R /H /I >> endobj 1658 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 637.5 266.22 646.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1200 0 R /H /I >> endobj 1659 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.998 637.5 539.998 646.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1200 0 R /H /I >> endobj 1660 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 625.5 211.23 634.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1624 0 R /H /I >> endobj 1661 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.998 625.5 539.998 634.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1624 0 R /H /I >> endobj 1662 0 obj << /Type /Action /S /GoTo /D [1280 0 R /XYZ 72.0 720.0 null] >> endobj 1663 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 613.5 370.982 622.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1662 0 R /H /I >> endobj 1664 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.773 613.5 539.773 622.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1662 0 R /H /I >> endobj 1665 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 601.5 228.99 610.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1519 0 R /H /I >> endobj 1666 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.997 601.5 539.997 610.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1519 0 R /H /I >> endobj 1667 0 obj << /Type /Action /S /GoTo /D [1223 0 R /XYZ 72.0 720.0 null] >> endobj 1668 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 589.5 248.43 598.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1667 0 R /H /I >> endobj 1669 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.997 589.5 539.997 598.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1667 0 R /H /I >> endobj 1670 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 577.5 337.31 586.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1319 0 R /H /I >> endobj 1671 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.998 577.5 539.998 586.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1319 0 R /H /I >> endobj 1672 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 565.5 254.0 574.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1236 0 R /H /I >> endobj 1673 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.997 565.5 539.997 574.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1236 0 R /H /I >> endobj 1674 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 553.5 283.99 562.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1294 0 R /H /I >> endobj 1675 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.998 553.5 539.998 562.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1294 0 R /H /I >> endobj 1676 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 541.5 317.33 550.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1249 0 R /H /I >> endobj 1677 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.998 541.5 539.998 550.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1249 0 R /H /I >> endobj 1678 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 529.5 287.33 538.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1254 0 R /H /I >> endobj 1679 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.997 529.5 539.997 538.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1254 0 R /H /I >> endobj 1680 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 517.5 292.89 526.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1257 0 R /H /I >> endobj 1681 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.997 517.5 539.997 526.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1257 0 R /H /I >> endobj 1682 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 505.5 317.33 514.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1288 0 R /H /I >> endobj 1683 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.998 505.5 539.998 514.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1288 0 R /H /I >> endobj 1684 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 493.5 287.33 502.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1285 0 R /H /I >> endobj 1685 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.997 493.5 539.997 502.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1285 0 R /H /I >> endobj 1686 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 481.5 259.55 490.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1299 0 R /H /I >> endobj 1687 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.998 481.5 539.998 490.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1299 0 R /H /I >> endobj 1688 0 obj << /Type /Action /S /GoTo /D [1327 0 R /XYZ 72.0 720.0 null] >> endobj 1689 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 469.5 223.734 478.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1688 0 R /H /I >> endobj 1690 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.884 469.5 539.884 478.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1688 0 R /H /I >> endobj 1691 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 457.5 259.55 466.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1331 0 R /H /I >> endobj 1692 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.998 457.5 539.998 466.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1331 0 R /H /I >> endobj 1693 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 445.5 252.33 454.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1341 0 R /H /I >> endobj 1694 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.998 445.5 539.998 454.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1341 0 R /H /I >> endobj 1695 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 433.5 233.44 442.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1334 0 R /H /I >> endobj 1696 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.997 433.5 539.997 442.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1334 0 R /H /I >> endobj 1697 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 421.5 206.78 430.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1349 0 R /H /I >> endobj 1698 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.998 421.5 539.998 430.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1349 0 R /H /I >> endobj 1699 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 409.5 231.77 418.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1351 0 R /H /I >> endobj 1700 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.998 409.5 539.998 418.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1351 0 R /H /I >> endobj 1701 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 397.5 247.88 406.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1353 0 R /H /I >> endobj 1702 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.997 397.5 539.997 406.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1353 0 R /H /I >> endobj 1703 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 385.5 236.78 394.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1355 0 R /H /I >> endobj 1704 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.999 385.5 539.999 394.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1355 0 R /H /I >> endobj 1705 0 obj << /Type /Action /S /GoTo /D [1401 0 R /XYZ 72.0 720.0 null] >> endobj 1706 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 373.5 244.126 382.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1705 0 R /H /I >> endobj 1707 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.884 373.5 539.884 382.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1705 0 R /H /I >> endobj 1708 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 361.5 308.97 370.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1511 0 R /H /I >> endobj 1709 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.998 361.5 539.998 370.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1511 0 R /H /I >> endobj 1710 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 349.5 221.76 358.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1396 0 R /H /I >> endobj 1711 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.997 349.5 539.997 358.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1396 0 R /H /I >> endobj 1712 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 337.5 199.56 346.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1408 0 R /H /I >> endobj 1713 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.998 337.5 539.998 346.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1408 0 R /H /I >> endobj 1714 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 325.5 214.54 334.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1415 0 R /H /I >> endobj 1715 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.997 325.5 539.997 334.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1415 0 R /H /I >> endobj 1716 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 313.5 271.2 322.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1422 0 R /H /I >> endobj 1717 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.998 313.5 539.998 322.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1422 0 R /H /I >> endobj 1718 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 301.5 228.45 310.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1436 0 R /H /I >> endobj 1719 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.997 301.5 539.997 310.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1436 0 R /H /I >> endobj 1720 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 289.5 256.22 298.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1461 0 R /H /I >> endobj 1721 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.997 289.5 539.997 298.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1461 0 R /H /I >> endobj 1722 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 277.5 267.88 286.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1469 0 R /H /I >> endobj 1723 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.997 277.5 539.997 286.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1469 0 R /H /I >> endobj 1724 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 265.5 287.32 274.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1559 0 R /H /I >> endobj 1725 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.997 265.5 539.997 274.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1559 0 R /H /I >> endobj 1726 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 253.5 264.56 262.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1581 0 R /H /I >> endobj 1727 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.998 253.5 539.998 262.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1581 0 R /H /I >> endobj 1728 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 241.5 247.88 250.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1584 0 R /H /I >> endobj 1729 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.997 241.5 539.997 250.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1584 0 R /H /I >> endobj 1730 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 229.5 235.11 238.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1570 0 R /H /I >> endobj 1731 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.997 229.5 539.997 238.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1570 0 R /H /I >> endobj 1732 0 obj << /Type /Action /S /GoTo /D [1507 0 R /XYZ 72.0 720.0 null] >> endobj 1733 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 217.5 156.09 226.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1732 0 R /H /I >> endobj 1734 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.959 217.5 539.959 226.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1732 0 R /H /I >> endobj 1735 0 obj << /Type /Action /S /GoTo /D [1510 0 R /XYZ 72.0 720.0 null] >> endobj 1736 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 205.5 306.577 214.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1735 0 R /H /I >> endobj 1737 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.838 205.5 539.838 214.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1735 0 R /H /I >> endobj 1738 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 193.5 215.397 202.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1636 0 R /H /I >> endobj 1739 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.921 193.5 539.921 202.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1636 0 R /H /I >> endobj 1740 0 obj << /Type /Action /S /GoTo /D [1632 0 R /XYZ 72.0 690.141 null] >> endobj 1741 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 181.5 330.736 190.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1740 0 R /H /I >> endobj 1742 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.761 181.5 539.761 190.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1740 0 R /H /I >> endobj 1743 0 obj << /Type /Action /S /GoTo /D [1632 0 R /XYZ 72.0 372.422 null] >> endobj 1744 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 169.5 192.89 178.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1743 0 R /H /I >> endobj 1745 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.998 169.5 539.998 178.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1743 0 R /H /I >> endobj 1746 0 obj << /Type /Action /S /GoTo /D [1632 0 R /XYZ 72.0 338.733 null] >> endobj 1747 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 157.5 204.1 166.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1746 0 R /H /I >> endobj 1748 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.998 157.5 539.998 166.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1746 0 R /H /I >> endobj 1749 0 obj << /Type /Action /S /GoTo /D [1632 0 R /XYZ 72.0 264.385 null] >> endobj 1750 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 145.5 219.11 154.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1749 0 R /H /I >> endobj 1751 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.997 145.5 539.997 154.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1749 0 R /H /I >> endobj 1752 0 obj << /Type /Action /S /GoTo /D [1632 0 R /XYZ 72.0 148.425 null] >> endobj 1753 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 133.5 270.214 142.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1752 0 R /H /I >> endobj 1754 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.952 133.5 539.952 142.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1752 0 R /H /I >> endobj 1755 0 obj << /Type /Action /S /GoTo /D [1641 0 R /XYZ 72.0 456.879 null] >> endobj 1756 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 121.5 191.33 130.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1755 0 R /H /I >> endobj 1757 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.998 121.5 539.998 130.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1755 0 R /H /I >> endobj 1758 0 obj << /Type /Action /S /GoTo /D [1641 0 R /XYZ 72.0 406.845 null] >> endobj 1759 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 109.5 223.55 118.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1758 0 R /H /I >> endobj 1760 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.957 109.5 539.957 118.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1758 0 R /H /I >> endobj 1761 0 obj << /Type /Action /S /GoTo /D [1641 0 R /XYZ 72.0 373.313 null] >> endobj 1762 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 97.5 204.1 106.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1761 0 R /H /I >> endobj 1763 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.998 97.5 539.998 106.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1761 0 R /H /I >> endobj 1764 0 obj << /Type /Action /S /GoTo /D [1641 0 R /XYZ 72.0 287.279 null] >> endobj 1765 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 85.5 219.11 94.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1764 0 R /H /I >> endobj 1766 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.997 85.5 539.997 94.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1764 0 R /H /I >> endobj 1767 0 obj << /Type /Action /S /GoTo /D [1641 0 R /XYZ 72.0 159.947 null] >> endobj 1768 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 73.5 270.214 82.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1767 0 R /H /I >> endobj 1769 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.952 73.5 539.952 82.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1767 0 R /H /I >> endobj 1770 0 obj << /Length 1771 0 R /Filter /FlateDecode >> stream xœÅÝ]“Ç™˜ésý œ­f"Ø®ª'?!’0 iÆaû€#Q2×r,qÖ»ûë·ž·A¢ß®¢U—ccÖaà.°»2++ë¿ÿd}±ìÿ÷IþOŸÛ‹ßÿËOþû‡Ÿ[_ôíE´?UÛ‹µþãã'÷ø¿?úI-?§åé§tÿwâßõÿá¯Ãµ×‡ü¹‡qçúþ¨å¿óŸÙ1íÿÉïf;üýÇ×ïùÉû/^~þîå§ï_¿ýüñwöȵ¯³ïyíqüëýw/>™ë‹ŸÆÔ‡ÙÅ<Œy8Äâ±J\$îÏEâ¸I<¯ÇÛ²I ‚Û‚Û ‚Û ‚Û ‚Û‚Û‚Û‚Û&‚!‚!‚!‚E‹¬"XE°î‚û%ÀZZ½OˆÛ&q•x@¼M‡¸HÜ!‹Ä!±œ"8Ep‚`,  Æ‚±‚`¬ +Æ ‚±`l ›†††,"XD°ˆ`Á*‚U›6l"ØE°‹`Á.‚C‡œ"8Ep‚`Y@°, X, –Ë ‚eÁ²`Ù@°l"""""XD°ˆàþżޱ¬[¿ºbPö/ésö9ê(‡1k«Ïóñ"çowÕï^?äßíþâ§oÿùÿøê÷ß=ùñ_¾þê›ï¾úÃÇŸùìËï¾|ò£¯þøõ7_÷õ·ß|ü¹7_~ó§ûòO_}ü™ÿüÓ·o?ûìÍþ»ÃäúP÷ÿŠ—QËñû8þ0¬<Ôhsô8Ž:^¥vˆç"qHÜ$ž×ãX6‰«Äâu•cÁØ@06Œ ÷ qˆ`ˆ`ˆ`Á"‚E«V¬"XE°‰`Á&‚]»v"8DpˆàÁ)‚S'–Ë‚eÁ²‚`YA°¬ XV,– Ë&‚!‚!‚!‚E‹Ì ¸^nËÇ×/ðòª¶÷mYöoýÇakëÏú¼¿_”GÞ}ñX½{ÿòóÏ^~ñÙ'Ÿýì“·?û‡WŸ¾6h/ZÛ‡DkÇáù¹í_læñÝ~=¹ì׉K›'Þÿþó†—ÔAu£zB7½¤®T©÷ëJ© Õb™·¾¤˼ù%5YYYY²,dYȲ’e%Ëš–cÎý‹×…xBÜ6‰«Äâ¾J\$îEâX‡Nœ"8A0oƒA ‚yìz¼‚`Þƒó6ØõxÁ¼ ±†††,"XD°ˆ`Á*‚U›6l"ØE°‹`Á.‚C‡œ"8Ep‚`Þƒó6Ä ˜·Á Á¼ v=Þ@0oƒA,‚!‚!‚!‚!‚E‹î_ÌÛÖç\Îæõ?:1ÿp+lYæ6ŽÃÖ6Ž‹¹Çî®úûÏ^ýüåoß¼ÿäÝû/^þ‹OÞ¼úüïù÷‡iãòËܱڎ#?Áý2vo[å:ÙØ_½”ã°ãÜ´Q=¥Î¥2¨+ÕCê\-ƒºPÝ¥Î3¨É²e!ËJ–•,ëøá†ôߎÛ*q‘¸C܉Câ&ñ„xlW‰EpŠàÁ ‚û¿”cÁý+<Ä+Æ ‚±‚`l Æ&‚!‚!‚!‚!‚E‹¬"XE°Š`Á&‚M›vì"ØEpˆàÁ!‚S§Nœ X, –Ë ‚eÁ²‚`Ù@°l X6,›†††,"˜7¬÷ à²×§~sÓ}þ»Í“YçÚæqnšÏRÝUŸ~ñêåûWŸüîõ«üäç_¼ýÕ'Ÿ¾yùîÝó ­ý §äŽÊm¿¾?|ˆÛç7ŽÛH·ýZ§Çþ»ÚÆzvœlnTWª‡ÔûõŽÔ…ê.õ~É#uPݨ&ËB–…, YV²¬dYÓr™£×z¡n ÕAu£zJÝ7ª+ÕCê±R]¨&ËI–“,'YN±Ì]ÝR‹eîë†zËÜÙ-µXæÞn©Å2wwKM–A–A–A–…, Y²¬dYɲ’e%ËF–,Yv²ìdÙÉrå ËA–ƒ,'YN²œb™Û¾¥ËÜø õ*–¹õ[j±ÌÍßPob™Û¿¥&Ë Ë Ë ËB–…,s¼ô=éÍ»çÃÖ¾'Ây@Ç]õÙ«Ÿ?΂Ï&ÀkÎ òÓ*ûlþ0ôöåé®î:¶<èd”õ8ìùo~m+Õ…ê.u_¨ªÕSê±Q]©&ËI–“,§Xn‹Xn‹XæºÔb™ËAR‹e.A½‰e.IM–A–A–A–A–…, Y²¬dYɲ¦å\Öh'ß$Ζƒ¤ªÕSê¾Q]©R•êB5YN²œd9ÉrŠe.I-–¹õ*–¹$µXærÔb™ËAR“eeee!ËB–…,+YV²¬dYɲ‘e#ËF–,;Yv²d9Èrå ËI–“,§XærÔb™ËAP¯b™ËAR‹e.A½‰e.IM–A–A–A–…, Y²ÌÎÛXÖºX¤¹Ûá¶öí¸x”'¥Þ/}ñö×cÅmŽ¿å íäÜž?ˆ‡8.!å׺_Öí_-ÃÎ&ûRÕê)unt…ºR=¤Î½®PªÉ2È2È2È2Ȳe!ËB–•,+Yæ¾×º's‰ un|…:¨nTO©só+Ô•ê!uî…ºPM–“,'YN²œby;Ñj±¼éw½^ÅòvªÔby;×j±¼ì5YYYY²,dYȲ’e%ËJ–•,Y6²ldÙɲ“e'ËA–ƒ,Y²œd9ÉrŠåíÈ?¨ÅòvèßõzËÛ±P‹åíà¿ëõ&–·£ÿ &Ë Ë Ë ËB–…, Yæãü­>ò|}:}²õóaë8Ù)2Ÿ?ôÿæõ»÷SüW‡I~ÞÍcóõ\‡ùY­ùÞ§ã,?÷Ëçï½Îq÷ü÷¾æ~y¨‡Ô¹_êBu—:÷ËCT7ª§Ô,;Yv²d9Èrå$ËI–“,§Xæ•R‹eX õ*–y`¥Ôb™VJ-–y`¥ÔddddYȲe!ËJ–•,s¿|®§-gßDõ”:÷ËC]©Rç~y¨ Õ]êÜ/uPM–ƒ,'YN²œb™çWJ-–y‚%Ô«Xæ–R‹ežb õ&–yŽ¥ÔddddYȲe!ËB–•,+YV²ldÙȲ‘e'ËN–,;Y²d9Èr’å$Ë)–yÀ¥Ôb™G\J-–yÈ¥Ôb™Ç\B½‰et)5YYYYY²,d¹µ/½.K[e)ên…ì0nëó~¼X—çgüîõ‡×¿•|ZëÉëßüôõo·Ÿùáõo·ýêËo¾þ×ûó—?¼îö³w/€»ýÌíp¿:yÜ~Õ7Ç>Ó/-N>¹àäúon{»ÿGs2îìòNù~ HyXÞ,Ÿ”ï—”WËåaªaªaªÅT‹©S-¦ZMµšj5ÕfªÍT›©vSí¦ÚMµ›ê0ÕaªÃT§©NS¤šˆ”“j^"RNªy‘H9©æe¢ä©æ…"妦¦¦¦ZLµ˜êþí`DnQîtÙôø^µýâiÙÎ~™ýž د^×õùSúÿÙÏ>yùÛ÷o?y÷?ÿôùÙèkÝÿXçž×2OÆ~ØÛ}üÔòb©ëþ'°Äɸçy‘òfù¤¼o–WËåcµ¼XÞ)Ÿ¦:Mušê$Õ¼£H9©æ=EÉWRÍ»Š”“jÞW¤œTóÎ"妦¦¦ZLµ˜j1ÕjªÕTkª.sŒÞ/å“ò¶Y^-”÷Õòby§|,–‡å¦:Lušê4ÕIª¹äD9©æ’“ä+©æ’多KN’o¤šKN”›j˜j˜j˜j1ÕbªÅT‹©VS­¦ZMµ™j3ÕfªÝT»©vSí¦:Lu˜ê0ÕiªÓT'©æ’多KN”“j.9QNª¹ä$ùFª¹äD¹©†©†©†©†©S-¦šìG[Ö¥Y×¹{fÿ8nådÉi{þlÿïåûôå§¿|ýù/«NùU0wóï—ê'Ãoì˜ÇU§ýËáØöÿ–ë'㎫›åÕòAùþåòby—<3 <,o–“ji@9©æ¡’o¤šÇPnªaªaªaªaªÅT‹©S­¦ZMµšj3ÕfªÍT›©vSí¦ÚMu˜ê0ÕaªÓT§©NS¤šPNªyää+©æ¡”“j{@9©æÁ”›j˜j˜j˜j1ÕbªÅT«©VS­¦ZMµ™j3ÕfªÝT»©vS¦:Lu˜ê0ÕiªÓT'©æ‰”“jž‰ ùJªy*多ç"H¾‘jžŒ@¹©†©†©†©S-¦šG,ûEPgù.GÜ/–Æ­£,–”çg#ü°XòÛ_–oŒ|û³xõéûwŸüêå?}òæÕçÏ×Nòfh,sÿuk;ùhùÉÖqòN˼+ºÿ‡ýa3ÑaÜñÚzµ¼XÞ)Ï%$Ë›å“òÜê/yµœTó®(多wE%_I5ïŠRNªyWTòTó®(妦¦¦ZLµ˜j1ÕbªÕT«©VSm¦ÚLµ™j7ÕnªÝT»©S¦:Lušê4ÕIªyW”rRÍ»¢”“jÞ¥œTó®¨ä©æ]QÊM5L5L5L5Lµ˜j1Õ|.kÝ‹htí|÷èæqÜ:úÉ…~}þˆçëÏß½ùù§¯>ùâÕÏ¿xõî—¯>{6jgÃnÓþPwCó U¯'Cžÿ¾óVåÅ2¿<],Ëå²_,ó¶äÕ2.—ír9¯–ùµçbyÕ(o<^,·«Fy»ñjyÙ(.Åe£¸l—Êe£rÙ¨\6ª—êe£zÙ¨]6j—Úe£vÙ¨_6ê—úe£qÙh\6—æe£yÙh^6šWòfßÕòªQÞâ»X®WòÆÞÕòªQÞλZ^5Ê›xWËËFqÙ(.Åe£rÙ¨\6*—êe£zÙ¨^6ª—Úe£vÙ¨]6ê—úe£~Ùh\6—Æe£qÙh^6š—æU£¼vµ¼j”wÏ.–ëU£¼gvµ¼j”wÊ.–ÛU£¼?vµ¼l—â²Q\6*—Êe£rÙ(o“å›¶n·»®ÏSïo“Æí“Ó“Ùs{þ´ûg¯Þ¼zÿê“'“èOß~ñÙósÂóÁÛϳ>ÈíE÷ýa;ÞË×\·uÎý›Ùɸ³Éšäù¢kÉ‹åò|×µäay³|Ržï»–ÜT‹©VS­¦ZMµ™j3ÕfªÍT»©vSí¦:Lu˜ê0ÕiªÓT§©NR½½[rR½½ò•ToïÁ–œToo–œToï–ÜTÃTÃTÃT‹©S-¦ZMµšj5ÕjªÍT›©6Sí¦ÚMµ›ê0ÕaªÃT‡©NS¦:Iõö’lÉIõöšlÈWR½½([rR½½*òTo/Ë–ÜTÃTÃTÃT‹©S-¦šgÂïWåk¬Cf¢÷÷šãÖyò&­|žö>û°—ôÃ$ùñåÙßOO&I? >~¤üDó5Ç)ó>[*£å;¹Ö“qg³%Ê‹åò<¾Nò°¼Y>)Ïãë$¯–›ê0ÕaªÃT§©NS¦:I5gK”“jΖ$_I5gK”“jΖ('Õœ-QnªaªaªaªÅT‹©S­¦ZMµšj5ÕfªÍT›©vSí¦ÚMu˜ê0ÕaªÃT§©NS¤š³%ÊI5gK’¯¤š³%ÊI5gK’o¤š³%ÊM5L5L5Lµ˜j1ÕbªyDöþ÷l‰r6ùÑIÈýlé0nÛÉli<Rïn¶ô8Yz÷æíûçWtëÓ‰ÒáƒÜftíäÎâx¨cÿshQNF.·Õòby§<ËÃòfù¤¼l–WËMµšj5ÕjªÍT›©6Sm¦ÚMµ›j7ÕaªÃT‡©NS¦:Mu’jN~)'ÕœüJ¾’jN~)'ÕœüRNª9ù¥ÜTÃTÃTÃT‹©S-¦ZMµšj5ÕjªÍT›©6Sí¦ÚMµ›ê0ÕaªÃT‡©NS¦:I5'¿”“jN~%_I5'¿”“jN~%ßH5'¿”›j˜j˜j˜j1ÕbªÅTóVa|?W¾:±¼ßV{µÎ“£zoX^™úöÕæÁvù;š1O>ÊíS<{…UÎO×<®¦õ“agÓS¨÷Ù©ÔAu£zJ½ÏL¥®T©÷i©ÔdYÓr]Öu¶+y[,Ë›å“ò¾Y^-”Õòb¹©NS¦:Mu’jNJ)'Õœ”J¾’jNJ)'Õœ”RNª9)¥ÜTÃTÃTÃT‹©S-¦ZMµšj5ÕjªÍT›©6Sí¦ÚMµ›ê0ÕaªÃT‡©NS¦:I5'¥”“jNJ%_I5'¥”“jNJ%ßH5'¥”›j˜j˜j˜j1ÕbªÅTsRZÛå?:ã»›–ÇíídZº>(ôôô‡§=oÓyäóéþÕãGº¶õ8îl®Dy±¼Sþtÿê•<,o–OÊŸî_½’WËMu˜ê0ÕaªÓT§©NS¤z·õJNªwûW/ä+©Þí_½’“êÝþÕ+9©Þí_½’›j˜j˜j˜j1ÕbªÅT«©VS­¦ZMµ™j3ÕfªÝT»©vS¦:Lu˜ê0ÕiªÓT'©Þí_½’“êÝþÕ ùJªwûW¯ä¤z·õB¾‘êÝþÕ+¹©†©†©†©S-¦ZLõéþU˜„Üí_=Ž[çÉÙ8·S=ÏfKyãîéLéùÝÓý«ÇreÿêqÔá²ñéþÕ+y±¼Sþtÿê•<,o–OÊŸî_½’WËMµšj5ÕjªÍT›©6Sm¦ÚMµ›j7ÕaªÃT‡©NS¦:Mu’êÝþÕ+9©Þí_½¯¤z·õJNªwûW¯ä¤z·õJnªaªaªaªÅT‹©S­¦ZMµšj5ÕfªÍT›©vSí¦ÚMu˜ê0ÕaªÃT§©NS¤z·õJNªwûW/ä+©Þí_½’“êÝþÕ ùFªwûW¯ä¦¦¦¦ZLµ˜j1Õ§ûW/O,ïoFmËÉA7·EœM}¿iâ?¼}ýùó„k^ˆÖ}Ð~ÝuònçÖÖ‡ã'¸îW¤siËRG;÷üOaݯH)o–OÉ·ýŠ”òjù <啼XÞ)ßHuÛHuÛHuÛL5L5L5Lµ˜j1ÕbªÕT«©VS­¦ÚLµ™j3ÕnªÝT»©S¦:Lu˜ê4Õiª“T󽯔“j¾÷Uò•T󽯔“j¾÷UòT󽯔›j˜j˜j˜j1ÕbªÅT‹©VS­¦ZMµ™j3ÕfªÝT»©vSí¦:Lu˜ê0ÕiªÓT'©æ{_)'Õ|ï+多ï}¥œT󽯒o¤šï}¥ÜTÃTÃTÃTÃT‹©SÍ7×”} =¶)+÷wçãöIöóãñ‘wÙï^¿~ý¿Æþ%`¼øé»ß¼ùøƒ×ÿáíÇ|ñÕï¿ý˾þæOÏçþu}èsF“ÿñÆÕ‡}ì¼-°†VöoSPïߥ¤.Tw©÷oQRÕê)õþíIj²d9Ér’åË|^@j±ÌK-–¹sGj±Ì 8Poby{<j² ² ² ² ²,dYȲe%ËJ–ùx~Ýÿ{K»’çãù’‡åÍòIy>ž/yµ|PžçK^,7ÕiªÓT§©NR½=ž/9©Þχ|%ÕÛãù’“êíñ|ÉIõöx¾ä¦¦¦¦ZLµ˜j1ÕjªÕT«©VSm¦ÚLµ™j7ÕnªÝT‡©S¦:Lušê4ÕIª·Çó%'ÕÛãù¯¤z{<_rR½=žùFª·Çó%7Õ0Õ0Õ0ÕbªÅT‹©–ùPZûðÀÉõ5¡\Ò£,Ë~}2n[ÎNÛ/þ÷ïãs´Ú³wï_~ñþ“w¿yóáI“ןÿâ°ñtÓÍá\Ütsw\^Ë›åSòûM7òjù ünÓÍ…¼XÞ)ßHõ~ÓÍ…œTï7Ýüí(Ï?’›ê$Õ|¤‡rR͇z('Õ|¬‡rRÍ{$ßH5í¡ÜTÃTÃTÃTÃT‹©S-¦ZMµšjMÕºWò¶X–7Ë'å}³¼Z>(«åÅrS¦:Mušê$Õ|ʇrRͧ|$_I5Ÿò¡œTc#Õ|ʇrRÝÿ-åaªaªaªÅT‹©S­¦ZMµšj5ÕfªÍT›©vSí¦ÚMu˜ê0ÕaªÃT§©NS¤šOùPNªù”ä+©æS>”“j>å#ùFªù”妦¦¦ZLµ˜j™ùXÌœetYy¹?,÷0nŸ×ž¬ íWfÇU¡wï¿xõòWÏçôy׾Ͻíãd\~ZkNÌ+Bû÷ÚýÂeÎXÛÉÀÃÚÁþ½–òby§|ÿ^KyXÞ,Ÿ”ïßk)¯–›j7ÕnªÝT‡©S¦:Lušê4ÕIª¹‹rRÍí\’¯¤šÛ¹('ÕÜÎ%ùFª¹‹rS S S S-¦ZLµ˜j1ÕjªÕT«©6Sm¦ÚLµ›j7ÕnªÝT‡©S¦:Mušê$ÕÜÎE9©æv.ÊI5·sQNª¹KòTs;妦¦¦¦ZLµ˜j1ÕjªÕT«©6Sm¦ÚLµ™j7ÕnªÝT‡©S¦:Mušê4ÕIª¹‹rRÍí\’¯¤šÛ¹('ÕÜÎE9©æv.ÊM5L5LÕÖ–Š­-[[º·Sçœk9Ë|…ì~?×aථǕ»¼/yŸ½üì³O~|õ®Î‡Þ—e)[?{[T¬ÛÉv®xØ'§ù ÜÙ¯y\j–OÊ÷¯û”WËåû×}Ê‹åòýë>å¦:Mu’j‰D9©æ‘H’¯¤šG"QNªy$多G"QnªaªaªaªÅT‹©S­¦ZMµ¦ê:GíR>)o›åÕòAy_-/–wÊÇbyXnªÃT§©NS¤šG"QNªy$’ä+©æ‘H”“j‰$ùFªy$妦¦¦ZLµ˜j1ÕbªÕT«©VSm¦ÚLµ™j7ÕnªÝT»©S¦:Lušê4ÕIªy$多G"QNªy$多G"I¾‘j‰D¹©†©†©†©†©S-¦š»¿JùjuY¨¹[C:ŽÛÖ8YCÚžŸœôÙ«7¯Þ¿úŸ,#݉Èe¤1N†ßžXœgOæ—ÃÞöólÜqõc³¼Z>(Ï/‡’Ë»äù¨åay³œTóQ9ÊI5•“|#Õ|TŽrS S S S S-¦ZLµ˜j5ÕjªÕT›©6Sm¦ÚLµ›j7ÕnªÃT‡©S¦:Mušê$Õ|TŽrRÍ«ÉWRÍGå('Õ,('Õ|TŽrS S S S-¦ZLµ˜j5ÕjªÕT«©6Sm¦ÚLµ›j7ÕnªÃT‡©S¦:Mušê$Õ|TŽrRÍGå$_I5•£œTóQ9É7RÍGå(7Õ0Õ0Õ0ÕbªÅT‹©æyK˺¬±ÒêÅÝ“uÇqûDõdm%žËôæõ»÷OVVÞ=_hOž¯;޾-üÄC=Ù¡³ÿíXËœ-ÊɸÃzC~%—¼XÞ)ϯ䒇åÍòIy~%—¼ZNªù 多bI¾’j>ˆE9©æƒX’o¤šbQnªaªaªaªÅT‹©S-¦ZMµšj5ÕfªÍT›©vSí¦ÚMµ›ê0ÕaªÃT§©NS¤šbQNªù 多bQNªù –䩿ƒX”›j˜j˜j˜j˜j1ÕbªÅT«©VS­¦ÚLµ™j3ÕfªÝT»©vS¦:Lu˜ê4ÕiªÓT'©æƒX”“j>ˆ%ùJªù 多bQNªù 妦¦¦ZLµ˜jî¡iûßúM–R×yÆœÛ<[ÀÙÖççj—q»qŸ½þ§‡/.Û^üôÓ7ï~óæÉ¿ýæ_÷õ·ß|ü©wÿ÷_¿ûê_ë(ÛúµeéËÙ/ñqôa\}(¹ŠÔFœŒ;.× Ê÷¯°”Ë;åûWXÊÃòfù”<y¢œTó‘'ÉWRÍGž('Õ|ä‰rRÍGž(7Õ0Õ0Õ0ÕbªÅT‹©VS­¦ZMµšj3ÕfªÍT»©vSí¦:Lu˜ê0ÕaªÓT§©NRÍGž('Õ|äIò•Tó‘'ÊI5y’|#Õ|ä‰rS S S S-¦ZLµ˜j1ÕjªÕT«©6Sm¦ÚLµ›j7ÕnªÝT‡©S¦:Mušê$Õ|ä‰rRÍGž('Õ|ä‰rRÍGž$ßH5y¢ÜTÃTÃTÃTÃT‹©SÍåšØ–u›E;r¹fŒý¿–­Í“qÛzràuîÙ¼Ïþþg/?ýß_}þÙ'ÿøò‹ÏóMh?{õË—¿{ýö‹¿?LÀÚCnÚ?ϳ“Ÿæ~1Ü=”7Î×Ú–¥æ`‡qÇ©UXÞ,Ÿ”ïÄ”WËåû·^Ê‹åònªÝT»©vS¦:Lu˜ê4Õiª“TóÆ9多7Î)'Õ¼qN9©æsÉ7RÍç”›j˜j˜j˜j˜j1ÕbªÅT«©VS­¦ÚLµ™j3ÕfªÝT»©vS¦:Lu˜ê4ÕiªÓT'©æsÊI5oœK¾’jÞ8§œTóÆ9多7Î)7Õ0Õ0Õ0ÕbªÅT÷ÙÁX÷™Øz:UúÑ)Îýá‡qÛ¶œÌÄÚó3*òÙˆOß~þÙë÷¯ß~þlÀºf=ÏV-u=z»¥ö™åyö)Ò>G<ûŸÿþó…¨+ÕCê|êBu—:Ÿÿ€š,Y²œd9ÉrŠåíÁ¨ÅòöØÇõzËÛCP‹åí‘ëõ&–·> &Ë Ë Ë ËB–…, Y²¬dYɲ’e#ËF–,;Yv²ìdÙÉrå ËA–“,'YN±¼=×µXÞžê€Z,oÏt@-–·':®×›Xޞ瀚,ƒ,ƒ,ƒ,ƒ, Y²,dYɲ’e%ËF–,Y6²ìdÙɲ“å ËA–ƒ,'YN²œd9ÅòöÔÔby{fãz½Šåí‰ ¨Åòö¼Ôby{Zj² ² ² ²,dYÈ2ïû¯Ë¼½Ötîã8ŒÛ¶³×åŒç§väjÓ«/¾xûÅóù÷þ]¼æJS¯ídØã[|ÚCœ¼çz}X·ým]OƦùûôMê.uî8€:¨nTO©s·Ô•ê!u#ËF–,;Yv²ìdÙÉrå ËA–“,'YN±ÌÃ{¥Ë<ºWj±Ìƒ{¥Ë<¶êM,óÐ^©É2È2È2È2Ȳe!ËB–•,+YæV‚mûpCêo繕@ò°¼Y>)¿=* yµ|Pž[ $/–›ê4ÕiªÓT'©æI½”“jžÔ+ùJªyR/多çïQNªyR/妦¦¦ZLµ˜j1ÕjªÕT«©VSm¦ÚLµ™j7ÕnªÝT‡©S¦:Lušê4ÕIªyR/多'õJ¾’jžÔK9©æI½’o¤š'õRnªaªaªaªÅT‹©SÍ'D£ø"ÜýN´ÃÀmÛNÖçó“^rmðÃã@‡­í¡Æœsp2ðñÛU«ƒûÀR—9Ëè'ÏÎ$ßÛ”WËåmµ¼XÞ)ï‹åa¹©vS¦:Lu˜ê4Õiª“Ts%rR͵4ÊI5WÓ('Õ\O“|#Õ\Q£ÜTÃTÃTÃTÃT‹©S-¦ZMµšj5ÕfªÍT›©6Sí¦ÚMµ›ê0ÕaªÃT§©NS¦:I5×('Õ\\“|%Õ\\£œTsqrRÍÅ5ÊM5L5L5Lµ˜j1ÕbªÕT«©VS­¦ÚLµ™j3ÕnªÝT»©S¦:Lu˜ê4Õiª“TsqrRÍÅ5ÉWRÍÅ5ÊI5×$ßH5×(7Õ0Õ0Õ0ÕbªÅTmm鶸6êœ[ Zúßxw¸m'ïÏÿZŽ‹kŸ½|ÿòg/ß½ú±U¶¼Y:÷ÿ×f=ù·Ö³£vö »º¶ei¥ŸŒ;NÜ«åƒòýÂŽòby§|¿°£<,o–OÊÃTÃTÃT‹©S-¦ZMµšjMÕýëĺ­—òIyÛ,¯–Êûjy±¼S>ËÃrS¦:Mušê$Õ%¿m¡‘¼Z>(Ï-4’ËIõ¶…FrR½m¡‘ÜTÃTÃTÃT‹©S-¦ZMµšj5ÕjªÍT›©6Sí¦ÚMµ›ê0ÕaªÃT‡©NS¦:Iõ¶…FrR½m¡|%ÕÛÉIõ¶…òTo[h$7Õ0Õ0Õ0ÕbªÅT‹©S­¦ZMµšj3ÕfªÍT»©vSí¦ÚMu˜ê0ÕaªÓT§©NR½m¡‘œTo[h$'ÕÛÉIõ¶…òTo[h$7Õ0Õ0Õ0Õ0ÕbªÅTs M,ËRƃûõŒÃ¸}²w²žQÎŽ¨þôí矿ú4߈v¾¢±_ýñý'xø·Op;[Ñȳå—|›u“qg«”WËåy¾¼äÅòNy1/yXÞ,7Õ0Õ0Õ0ÕbªÅT‹©VS­¦ZMµšj3ÕfªÍT»©vSí¦:Lu˜ê0ÕaªÓT§©NRÍUÊI5W$_I5W('Õ\|#Õ\ ÜTÃTÃTÃT‹©S-¦ZLµšj5ÕjªÍT›©6Sí¦ÚMµ›j7ÕaªÃT‡©NS¦:I5W('Õ\ œTsU€rRÍUÉ7RÍUÊM5L5L5L5Lµ˜j1Õ\Øëuÿ®#“îûUømë'«õìpÚv9ä?œ. 䱑±Ý~Gg$?Ç~r€Æm+7HŒ8uœo®–Ë;å·U,ÈÃòfù¤ü¶ŠyµÜT«©VS­»jÿP\ÈÛbyXÞ,Ÿ”÷Íòjù |¬–ËMušê4Õiª“TóôHÊI5O”|%Õ<=’rRÍÓ#)'Õ<=’rS S S S-¦ZLµ˜j5ÕjªÕT«©6Sm¦ÚLµ›j7ÕnªÃT‡©S¦:Mušê$Õ<=’rRÍÓ#%_I5O¤œTóôHÉ7RÍÓ#)7Õ0Õ0Õ0ÕbªÅT‹©î“ßmÎY×ëËû©ïaÔ¶“©o;;:òý«_ýúí/¿ø?r?|ûøöæã¸MÍãažÜ¯cÎeÙ–q2îùBy@y±¼S¾ <,o–OÊ÷¯”“j y˜j˜j˜j1ÕbªÅT‹©VS­¦ZSuÿ¿6ξ¦çø«åÅòNy_,Ë›å“ò±Y^-7ÕiªÓT'©æ!”“j@9©æ!”“j ùFªyH妦¦¦¦ZLµ˜j1ÕjªÕT«©6Sm¦ÚLµ™j7ÕnªÝT‡©S¦:Mušê4ÕIªyH多‡H¾’j@9©æ!”“j@¹©†©†©†©S-¦š·ÏëøpHÀõ9úý¹”‡qÛ6OÖúÙ¹”ï_ÿêÕÛß¾?_AèOwÔ†ß>»yrjf¾Ûs¿ Þγq‡„ÜM$yµ|Pž»‰$/–wÉóÝž”‡åÍrRÍw{RNª¹;CòTsw妦¦¦¦ZLµ˜j1ÕjªÕT«©6Sm¦ÚLµ™j7ÕnªÝT‡©S¦:Mušê4ÕIª¹;ƒrRÍÝ’¯¤š»3('ÕÜA9©æî ÊM5L5L5Lµ˜j1ÕbªÕT«©VS­¦ÚLµ™j3ÕnªÝT»©S¦:Lu˜ê4Õiª“Tsw多»3$_I5wgPNª¹;CòTsw妦¦¦ZLµ˜j1Õ\[YÖe•V/î÷gÆí³·“µ•qvãÏ_¾ùæ|ee¿ú_×ýw²´õdðípÈr\WÉ-Úu´_ªŒ:,6ämÈs‹¶äÕòAynÑ–¼XÞ)Ï-Ú’‡å¦:Iõvˆ¥ä¤z;Äò•To‡XJNª·C,%'ÕÛ!–’›j˜j˜j˜j1ÕbªÅT«©VSÍ-Úe/zŸ—òIynÑ–¼Z>(Ï-Ú’Ë;å¹E[ò°ÜT‡©NS¦:Iõvˆ¥ä¤z;Äò•To‡XJNª·C,!ßHõvˆ¥ä¦¦¦¦ZLµ˜j1ÕbªÕT«©VSm¦ÚLµ™j7ÕnªÝT»©S¦:Lušê4ÕIª·C,%'ÕÛ!–’“êíKÉIõvˆ%ä©Þ±”ÜTÃTÃTÃTÃT‹©SÍoµxìÕu—û¡Ã¨-ÖçÆ‹}Nñ,û§‡üðë~Ó_üôõ7øêÿz6j”‡eä‹`£œ 2øù¸þз¶‚qöË>ÿ#˜ ÕAu£zJ½.›åÕòAùºZ^,'Ñu#Òu#Óu#ÔuKÕ)›åÕrS¦:Mu’j>ñI9©æŸ”“j>ñI9©æŸ’o¤šO|RnªaªaªaªaªÅT‹©S­¦ZMµšj3ÕfªÍT›©vSí¦ÚMu˜ê0ÕaªÓT§©NS¤ZR- ©–…TËJªe%Õ²’jÙHµl¤Z6R-›©†©†©†©S-¦ºÏ öïÜs.³Ó*ïmºÎe-cž Üb{6 o/ê~½²g^Ö¾ÌÇìåŸÿõ¿~ùÏ_}÷õï¿üsþZû×Ôø°ýñ‡üö/ð¯_þþ¿}ù§¯>þħoÞýæÍÉt®ö6gõäWý8ølf—‡M—­ŸŒ;ÛI–7Ë'å9Ç“¼Z¾ÿßÿüÇþäJžó<É‹åòœçI–7Ë'å9Ï“¼ZnªÓT§©NR½Íó$'ÕÛÛÿ¿ÉtF”Ó¼cYO/û·ˆçýxQ÷ïøÏfy;™ꋟ~öåw_þó—ýêãÏülŸÑ}òÕ7øë³µîÓ¥ÈmN±ö“úñƵ‡Qö)í>ædÜó?™5OD…<ÿ@$¯–ÊóDTÉ‹åò<Uò°ÜT»©S¦:Lušê4ÕIªyæ多g>QNªyæ多g>I¾‘jžùD¹©†©†©†©†©S-¦ZLµšj5Õ<u¿ÂZssÅß®ó@T¨ƒêFõ”:C…ºR=¤Î“P¡.T“å$ËI–“,§Xæ!OR‹eñõ*–yÀ“Ôb™Ç;I-–y¸“ÔddddYȲe!ËJ–•,+YV²ldÙȲ‘e'ËN–,Y²d9Èr’å$Ë)–y†“Ôb™'8A½Šežß$µXæéMPob™g7IM–A–A–A–…, Y–ùPz{<…é˜ÿè¢Òm»Ã>ýÌâNÆmQŸ Èíû4è>ûå·ÿã¶Ò¶~ضðýþøõ7øë÷?øò›?|ÿþöË?ÿÇoÿòÕ×úæ‡÷õ?ÿåË¿|ýÕóe³Û­÷ý›ÃÜJœ| ß?\±§~[–q6èx}_¨îRß–‘®×Au£zJ}[Bº^Wª‡Ô“,'YN±ŒE,ooÓZ,oïÒ¹^¯by{“Ôby{Ôby{‹Îõ:È2È2È2Ȳe!ËB–•,+YV²ldÙȲ‘e#ËN–,;Y²d9Èr’å$ËI–S,o/ËZ,o¯Ê¹^¯by{QÔby{MÔby{IÔddddYȲåíí8ë㯗¯¬sæ°O8æhqö‹œÏöï+÷Ù¯¿ýëwúËWÇ­ÎyÚÂÈYÉŒy2î¶{ÿ¯áä­8ûµBé5_Ûsö >ÿͯûÅ‚äûÕåay³|R¾_1P^-”ï ”›j5ÕfªÍT›©6Sí¦ÚMµ›ê0ÕaªÃT§©NS¦:I5ϦœTó<®QÎö¢¶åYöæGv$䱪߿\ê8êñˆ‰ía;®PÞÎÕØöëv2ð¸Ê7(¿«y±¼S~;kò°¼Y>)¿¹ ¹©6Sí¦ÚMµ›ê0ÕaªÃT‡©NS¦:Iõñ4VÈIõñDÖëùJª§²BNª'³^Ï7R}<rS S S S-¦ZLµ˜j1ÕjªÕTog¶îÿÅ–qö]ÿ¸·Z^,ï”ßÎl…<,o–OÊog¶B^-7ÕiªÓT'©ÆBªg¶BNªg¶^ÏWR}<³rR}<³rR}<³õz¦¦¦¦ZLµ˜j1ÕjªÕT«©6Sm¦ÚLµ™j7ÕnªÝT‡©S¦:Mušê4ÕIªg¶BNªg¶^ÏWR}<³rR}<³rR}<³rS S S S-¦ZL5ÏlÍÏ÷eЂÚý2ßaàù2_~èÏëo¾þîë/ÿüõÿóåw_ûÍɺ×o’?Ž}\‚lgÛëòÐr§BýdàÙ åÍòIyÛ,¯–Êûjy±¼S>Lu˜ê0ÕaªÓT§©NRÍ0ÊI5WÀ$_I5WÀ('Õ\“|#Õ\£ÜTÃTÃTÃT‹©S-¦ZLµšj5ÕjªÍT›©6Sí¦ÚMµ›j7ÕaªÃT‡©NS¦:I5WÀ('Õ\£œTsŒrRÍ0É7RÍ0ÊM5L5L5L5Lµ˜j1ÕbªÕT«©VSm¦ÚLµ™j3ÕnªÝT»©S¦:Lušê4Õiª“TsŒrRÍ0ÉWRÍ0ÊI5WÀ('Õ\£ÜTÃTÃTÃT‹©SÍ}nûeÇœýl…êÇW™>¬€-ËÜÆÉÀó°ñü´ŸO¿ý曯~Ÿ«_ù+å×?}÷¯_ýþë?~ýûÓE±}®¿­eYö_þäÃ}ü '“þšÏö¶('ãÎ&ý”wÊ÷I?åay³|R¾Oú)¯–ÊÃTÃTÃT‹©S-¦ZLµšj5ÕjªÍT›©6Sí¦ÚMµ›j7ÕaªÃT‡©NS¦:I5'ý”“jNú)'ÕœôSNª9é—|#ÕœôSnªaªaªaªaªÅT‹©S­¦ZMµšj3ÕfªÍT›©vSí¦ÚMu˜ê0ÕaªÓT§©NS¤š“~ÊI5'ý’¯¤š“~ÊI5'ý”“jNú)7Õ0Õ0Õ0ÕbªÅTsvÐë£w™E?¾©xýð2àøó9ÿ|~N×çß~w|°mŸ…fµ¬y~ØaÈãFœö0OÎÞÊeˆ¹¬õdàóßùºÏG)ùb°¹å¡;ß磔Ë;åû|”ò°¼Y>)¿-.A^-7ÕfªÍT›©vSí¦ÚMµ›ê0ÕaªÃT§©NS¤š¯£œTóÕ`”“j¾ŒrRÍWƒI¾‘j¾ŒrS S S S S-¦ZLµ˜j5ÕjªÕT›©6Sm¦ÚLµ›j7ÕnªÃT‡©S¦:Mušê$Õ|Så¤šï “|%Õ|[å¤šï £œTóa”›j˜j˜j˜j1ÕbªÅT«©VS­¦ZMµ™j3ÕfªÝT»©vS¦:Lu˜ê0ÕiªÓT'©æ«Ä('Õ|™˜ä+©æëÄ('Õ|¡˜ä©–T‹­-[[*¶¶Tlm©ØÚR±µ¥ÛSyûÙºG´xÿTÞaà>cz6 o/Úòã/¸½Ãl¼øé»oÿß¾úî°Š´>Ôº,Ë~=uòQ¾{²Tµì×wsôq2êl©Jò¶Z^,ï”÷Åò°¼Y>)›å¦:Lušê4ÕIª¹TE9©æR多KU”“j.UI¾‘j.UQnªaªaªaªaªÅT‹©S­¦ZMµšj3ÕfªÍT›©vSí¦ÚMu˜ê0ÕaªÓT§©NS¤šKU”“j.UI¾’j.UQNª¹TE9©æR妦¦¦ZLµ˜j1ÕjªÕT«©VSm¦ÚLµ™j7ÕnªÝT‡©S¦:Lušê4ÕIª¹TE9©æR•ä+©æR多KU’o¤šKU”›j˜j˜j˜j1ÕbªÅT_22Çì°fô¸í®/ËÒãdÔqYk¶mû_9Sþ8êâ™òLJe†§gÊ_ÈŸž)%/–wÊŸž)%Ë›å“ò§gÊ_ÉMµ™j7ÕnªÝT‡©S¦:Lušê4ÕIªwgÊ_ÉIõîLù ùJªwgÊ_ÉIõîLù ùFªwgÊ_ÉM5L5L5Lµ˜j1ÕbªÅT«©VS}z¦ü…üé™òWòby§üé™òWò°¼Y>)z¦ü•¼ZnªÓT§©NR…TïΔ¿’“êÝ™òò•TïΔ¿’“êÝ™òWrR½;SþB¦¦¦¦ZLµ˜j1ÕjªÕT«©6Sm¦ÚLµ™j7ÕnªÝT‡©S¦:Mušê4ÕIªwgÊ_ÉIõîLù ùJªwgÊ_ÉIõîLù+9©Þ)%7Õ0Õ0Õ0ÕbªÅTŸž)/ jw»×ŽÏ—ùâýLùãØ‹gÊž­€QÞ,Ÿ”?=SþJ^-”?=SþJ^,ï”S¦:Lu˜ê4Õiª“TïΔ¿’“êÝ™òò•TïΔ¿’“êÝ™òòTïΔ¿’›j˜j˜j˜j1ÕbªÅT‹©VS­¦ZMµ™j3ÕfªÝT»©vSí¦:Lu˜ê0ÕiªÓT'©ÆBªwgÊ_ÉIõîLù ùJªwgÊ_ÉIõîLù+9©Þ)!S S S S-¦ZLµ˜j5ÕjªÕT›©6Sm¦ÚLµ›j7ÕnªÃT‡©S¦:Mušê$Õ»3å¯ä¤zw¦ü…|%Õ»3å¯ä¤zw¦ü•œTïΔ¿’›j˜j˜j˜j1ÕbªOÏ”—U¦»3åÏWÀÊÿ§gÊ?ܵ3åãÎ&ý”wÊŸž)%Ë›å“ò§gÊ_É«åƒò0Õ0Õ0ÕbªÅT‹©S­¦ZMµšj3ÕfªÍT»©vSí¦ÚMu˜ê0ÕaªÓT§©NR…TïΔ¿’“êÝ™òò•TïΔ¿’“êÝ™òWrR½;SþB¦¦¦¦ZLµ˜j1ÕjªÕT«©6Sm¦ÚLµ™j7ÕnªÝT‡©S¦:Mušê4ÕIªwgÊ_ÉIõîLù ùJªwgÊ_ÉIõîLù+9©Þ)%7Õ0Õ0Õ0ÕbªÅTŸž)³è»3åã~˜ó¿zÿ“ßìÿ÷ÿî™Î¯ endstream endobj 1646 0 obj [ 1645 0 R 1647 0 R 1648 0 R 1649 0 R 1650 0 R 1651 0 R 1652 0 R 1653 0 R 1654 0 R 1655 0 R 1656 0 R 1657 0 R 1658 0 R 1659 0 R 1660 0 R 1661 0 R 1663 0 R 1664 0 R 1665 0 R 1666 0 R 1668 0 R 1669 0 R 1670 0 R 1671 0 R 1672 0 R 1673 0 R 1674 0 R 1675 0 R 1676 0 R 1677 0 R 1678 0 R 1679 0 R 1680 0 R 1681 0 R 1682 0 R 1683 0 R 1684 0 R 1685 0 R 1686 0 R 1687 0 R 1689 0 R 1690 0 R 1691 0 R 1692 0 R 1693 0 R 1694 0 R 1695 0 R 1696 0 R 1697 0 R 1698 0 R 1699 0 R 1700 0 R 1701 0 R 1702 0 R 1703 0 R 1704 0 R 1706 0 R 1707 0 R 1708 0 R 1709 0 R 1710 0 R 1711 0 R 1712 0 R 1713 0 R 1714 0 R 1715 0 R 1716 0 R 1717 0 R 1718 0 R 1719 0 R 1720 0 R 1721 0 R 1722 0 R 1723 0 R 1724 0 R 1725 0 R 1726 0 R 1727 0 R 1728 0 R 1729 0 R 1730 0 R 1731 0 R 1733 0 R 1734 0 R 1736 0 R 1737 0 R 1738 0 R 1739 0 R 1741 0 R 1742 0 R 1744 0 R 1745 0 R 1747 0 R 1748 0 R 1750 0 R 1751 0 R 1753 0 R 1754 0 R 1756 0 R 1757 0 R 1759 0 R 1760 0 R 1762 0 R 1763 0 R 1765 0 R 1766 0 R 1768 0 R 1769 0 R ] endobj 1644 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 1646 0 R /Contents 1770 0 R >> endobj 1771 0 obj 15626 endobj 1773 0 obj << /Length 1774 0 R /Filter /FlateDecode >> stream xœÅXKsÛ6¾ëW`rhìŒEà¹5IÓq&íÄcuzˆs HHæ„"e>⨿¾‹ >Ä$=¤öA»öõíb±Ð㊠ÿkñ2Š’ÃêQ¯RäzÉñê£Ò´r±Ë"¨¡àCmâý½*Vý¾úø ¾L§«“Âw«[˾øÿtûíW¯6«ë·>"mv=Dn踄Á_ÀPä¸T€Ùæ€>^¼‰›x׽ГÏk^¤õå'´y·úm3É%ôévà¤5¤¡3J¶”vÕ¬(Eâ«\çA*­ŠTΩϳNáÞ'l»4ÌóO5~>Å¡$؉É¥nx6›?µI"…í.6ŽÇ‹D¥ú²h BHsýÖÞ{Œ\ê0 Äwuió:©²c“•*w()‹‚'‚[×Gž]`xjÛ÷œ0GÆÕÆʺ1ð ¦7;t‰Ö¸\4YÝs6÷dÝTY±¿²ö5=]ñcÅk^4µ­•÷Œp°ˆÖJYõôÍËdš‚ªsz>€ž}Åïnß[žñê ¯lgê,åºQ P@bì’P¡PÈEÒ‡ÂPI'¢÷º<Ú"Kb™2½ø”5½`··óIrǪL8O;­_²Ø±yý¡7dJ¡Ó\ÎØØg_x1e¢ࣸHѱ¬gF‚1(f8šAäÚÕA0¶ËC³&¶ècÜ<ˆ_ dyaË6gÕu{à©-ZZŒ©^­Å¥Yp•Õi°#¶m¤MœõY*aÏ窆2‚ç¯"ûº~S@£PE _&ŸyS;†ß(í‚ܵynh‡ U€’ê7+=†Sé--Nc›4 /i£*ýÖ^Ld½×0uGÁ‰"â‚·ía+«X0GHO¯4§ j|,ÄÚS&C–bªö5§*_*èÄ­b I¨8Ù ÀS ø\ ®?ŠA¡è,6Qâûs=ŒýÐSRév±‡NîdOD]÷ŒÈ¥Ì2ôtA§f‚¯;D©#òކãO4o¦ì¶ dÙÕ‰È9W…*å/x ÚAcŽ[QnÎé7¼c¡ƒ\….Ö¨ˆBy*«tÙɘöPI¸ÿ/žšEsfݼHªÓQŸ¹fL÷e¿¿îewêö‘ô(Øn}cÚž`’¸èè-·ý™©GŠÙ(6~86'¤®P”íPQ¢ÎU°RñÇzXúÃàSÊœ aª`~zŸŠÜ ßë ”LkæR·µ\Jƒ+H­ Ç­A.ês¬wt³Ó’Ê|Ìí‘Q<)ßÅm£¸ç{0w-CPCÆ|0¢†9“ÕË(N¤æØ®­  U-ð¢%(Í2Í"t+f첫u"7b£zŠkšÓ²›‰î”Á7þ$ÙjQÏŠnN-«È]–[{ÊŽTu ÷XûS¾m÷{ÛȆ¼xÏë~»ºÂ¦. *C-Ђ^‘˜®ÇS7Å(¤,ò#}ÿ,~>·€² ºôNŸ‘‚[¶(ß AA„4¤C]†œÀãïð¹u=ðÐÕ‚ï³mWÙ²—  ÇDà%Ö¯)=q¸pÂm/­[üV¿Ÿ­%Ýujk©YÔñÚ¢“<ƒª±réõÉZ¹¿0LÞO.%NÈÄc†3¡€®Ã©~Ì•§.Ï#ãË‚¢ûKÇrhˆP^®GíDÀJ£‘оyùX¼I/ÊŘYK³zeðµxØe»L]XzMMD†{!ã^×å:/ãt-FêWÖ÷OYò`ñ]¯³\*-æl<âÍ{ÝÖÕ5q=ƒŒ‡ÿs–ˆgäEj ºø5M3rœwK»<Þ×'cRdžvds%ïYÕoô®¬ø¬ºâãŠw´µ¢r h+澸šÃ§£pTjìËçþâÙ:OžA~» x!sˆøí«»Pn À$γd.õ‡1¸ô¥æç3®ç8d!!z<¼‡Xº{Yy7=—œ,Áòˆž'¹€Ds9ÅÂ÷‚‘:´èn:Äè_» X [òNTMÇ´+mìº9yw{wŠ9ê¥tñ;Ðö™çÑ6\¢ïÅ×ý3äNÕG2À}ö7ÚöL±¹*îNðÎüºð{Î\:: €EØ7é8?øÞŒ€ýÐÄD8g·ÍYèGý,ø1ýŽÌTÀ~ÔLLú£6Ü9ã§ÉÔN„çìü¢&7ÑŸÎZ¤Þœ‹ö<>±FÃ9kæˆÉ_EoWÿ¾ØÐ endstream endobj 1772 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Contents 1773 0 R >> endobj 1774 0 obj 1719 endobj 1776 0 obj << /Length 1777 0 R /Filter /FlateDecode >> stream xœÅWYoÛ8~÷¯dM¬URÔE{] ©"‹ —Ýö¡)ŠM§ÚÊ’#ÉM½Eÿû©Ã:¶]°HŠ3ß7'éǂ߾|Ø\‡ùª÷˜­Q°u`V¶dZ@ M7aÙØ_î* ô|„t>»^Ð#ðº÷þ¾\A§©«SÂÓÞM _¾!¿ŸÀCïtÖ{qf%0[î\ÄlQŽ‹ƒ£1]Ñg³¼?»‰{ïÆNÝù§¾ññ˜ýÕ›Ì*&1ªÿ&ÝT8`XmÝÖjÁVÒ,]ÕT‘|ågqÈž©Öt˜’KŸ¤ÈŽ)SªÆù—‚w‡Ø–‚”hN%¸:ãÑüÅ^kRbö0 X‡B+f©àÚ™Q©Mç—x®ïýë&^¤æµ8Äp€qÍàR¥å¤¢ob‘ïç-ûm¦qÃ@ÝH÷ß¹ñb9×"r‡jæ‡î¢®ápîÇ~?\ÜÏïŽSµeeŽYSûÈR‚•ÉlÎm#HBX|p5>}÷Y…j0Ã¥E^¸Év-`FÍàÅ0µyŸ±IèÔÀÁ2üWaˆ¹t2L×bî-½yÅåLÆÆ¨«±ÐnJ87ÌéÓm¸_ \¼PØQá¾PP‡k–ib:V‹|?î® ˜F‹À":0ûšÐ `·1ÚÄ"êD ä!0þ-k7ŽŸÂhÑ#[Pç÷Ob»Œ·±+Ç'‰¼à¡UçmÏË #5tji„aAR#‹xyk•bÝùѤ ‚M³M†åâ4ÂÝ(/j‘¦ÀT™‘XG"A"'EÉâ‚8ÜDs»Ú~2–®Q«ŠÖÌv: ‘.>R•âØp¢JÝÝà+Ü“Vä3ìC³å·Íö¬jgØëdˆ`m׉X@®úgÉ2bkDǬ"Üy&+[Y7åoÝ'8ÓÔ(é*–RÅTòG3ò)ZQ ÑÒ|¼ "ò·eA•6ùdyŸE¤óߟâbz¿•0ýÚ¡¡èS^£/1æ‘p•·]O/ÙK2˜äùÖÎ [Ã4#Ô¤Yk¿ ï-Vf[š‰±çœdw‰³ñøb߆gÞ2±ÀL–÷]7k6šmûfʳ}nHß Â§¾˜c#SùT,¸ÑÃf…é´[QAÊÇe]’òn¶Ü*ôqi),!ù^œ¤Í‘‚,:¬ú¶"[ÆÅJxÿfZ Ë‹[|Aõš/¼‡ ŒÄâ;¢jT£xÔnê•&_ÜÕÚ߸í€5°{s½Ü†CÀ¤Dׯ˜f«/7*Ýðu³ô6H,O>tÖ>†qòÄêr Š¡pCš›Í[‘Ih¤£ ÑR»­HR¼é6¶ïÜÜ—pw¤î`ƒ¬¬áðî('~ëëËþYžçêàîZ`t³ÕÏ P¤î]ƒ®ûŸ‰÷©ª¢ÑKøíÏWÓ›‹¾lùÓŸÌNNO¦P¼_TXÃÕõä¾bˆmÓS}{Ù‚cÑz4Ë¢«ÒQ ^€™¼R­>{. :nÔþ¾`,#¯¡þ¶ŸæC_ÆcQ,K+³µƒ¶`8-ÁhòƒƒñíùÛÉíèëY$Äl<ý6œNnå‚rj>Ì]=*œ,¡‡oÎÇ£ŠÛ‡×ïJ+yº ¯¯ng#j06D„¿ßŠ(F#G#Óë둲½#¥x=~2¥,Â(¥Ú¼ÿ¢áûÎ,koóÖ¥ëÿ+8•öíˆaWlÁܽÍ:jmkÁd·/*MÂÀßîf›ôxÎfOx±ØÍÖ˜ y“NW’2·ÊéŸ+Wmº$–X´„À0jÖc w¥•þfßôþÒ:š´ endstream endobj 1775 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Contents 1776 0 R >> endobj 1777 0 obj 1373 endobj 1779 0 obj << /Length 1780 0 R /Filter /FlateDecode >> stream xœÅVKSä6¾ûWè¶Ëa„ž–´·IŠ•ŤrXö <pÅØƒåaÃþú´ü{Æö°ìeвÔÒ×ýµºÕ­§ˆ"¿Eø(ÃPò=µ2ŠC¤~BysCÿu|à?àò¢BöÙ¦™½ËJsxWej3ôìJŸ9n;J¯‡††*¡ ¦ŒëÆÊežV /ýf+Pw,@”kl%DBbÕØ¿½ëf  8&ÜvaBl±ºKÏìöd|TËÐúÕúS±q¥­:̲®Å}H2ÿ”-j“êŒ:P‡:æ)£“ùTÄ r'X«Ï¿IÅ.1 yºêêxõ²qh]”;ôSM¿(&–H Ý^¢ó"Ï]‚„n6.I×i²2jŠ8T£$Öš­%oÔܼä•ý/¤M²S¸ð ðX$9¥˜ÅÐĸèO¡Û (-&P+ŸÏš¡„MÙ™·@ɱ­wå¼ þV|ÊÆÆzÿµ(Wóvt<›ÊMÎøød†”Cye ²Y«ö _8Ÿ”é¦jËÁL\ÇÎóŠá˜Cþ ­G!] Jâ Ä ¤ü•nå×åU˜„쯓?\ ä‹m õ4ÔI|œŽ8ÖÚÉãq8§ùŒ s|‚ªš‚Û “úšÚ-,Ážæ.g'hŒ•PFK-¦a’á6Ë0wyR¾l*h'êï {¤ Ù FµUäÏ¢:Þ†ElpL b%;Hî¶&Ÿ ’PL yÕ½n®¯R¨Ô]›b¯“•Ú…Œ 'ì-ï)á}m4ú!÷<†»ÓñØÍ;B;ë‡ÃWE#¾*Iõ£Êýƒ-Ý@uV;÷Ò Öiæp?½¬VWnm·Yµ¿¹ŸÕY½›¥þX-—àýó:Ýúòè„h¤àöÅ|J+1¡ã;’QB6Ðѧâ­o˜1xÎ2hÈ4>x{Ôëëè<)gS endstream endobj 1778 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Contents 1779 0 R >> endobj 1780 0 obj 1037 endobj 1782 0 obj << /Type /Annot /Subtype /Link /Rect [ 286.93 340.587 352.93 349.587 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 621 0 R /H /I >> endobj 1784 0 obj << /Length 1785 0 R /Filter /FlateDecode >> stream xœÅXIsÛ6¾ëWà{¦‚±$ácâ¸M'“Ô•2NœDA6jŠ” *ŽúëûÀM7{|HåÑËÛ߇‡?Î("ð7w?d(ÚΫ5І¸_- Q3¶¨ ;ªÖ€Õ#ø)‰`pþš%3‚~}ý›kD€áiFºâ æÅ즥ßퟮŸ »ÙÛåìâZ JÐrs 0§>¾D!æÌ !fË-úzv¥rµRV£·*z˜ëdmÏ¿¡åï³÷Ë—8eÿƒK7'6@ZàN² n^®ÁJ)ÈmÅUªßRj9,+G"G›HÛ¤Ó<ÿTåã)#%8Y M¬ º¤èóõ5º‘º.-–ïDapwÔZçÊÄööOÖ7© PR¯*ÛõÕÕÇ©ÊÀ=Žs—¯ §rܧs—)øîÜCg—éSRf¤œ?èÃSš­ *»Ûo¡šWÀëã¸-Ë™|œmöIÔ@§ZJ[šbcë4Tš’–Z(¨§»'¼m¤”+éꨦ-]ÆÄBˆN,Ì]’fz=p†àŠû‘Cú½`2¾=:ßË(÷ÛdîœDuL›PºŽ•:è®ßdþð²(Í¿ý4^íB2%ÂuFIš#»ßíÒ,‡ƒÇ£{)NÃÕ#P±<¨ù‚òºÓÙ®ÒØDN*ÛžéFP`)\'ð©èöéú·wªOü)âDx¦:à¾tÇ—™býeB)Sœ6¸^™¯Õê{“®&‡ MF GuL/` ׂ>¯þGÂŽjæð¬g†¯÷îÓãÍÔB*Ñ€û]¬ŠúBB:!þ|Çç…!˜/CˆRÆG³ÊTfô¸'€r`;e«j/÷áHÕv4óÚ f‡Í³¦YÉôãÞdåõZ®ä¯nïU¦[¢ã¹Ãq¡hŒÓyKëZoÔ>ÎO‰³¢ónfÆŽÂÆÅ‹yx]ìmvæ¸où˜ãئã½hH„¼ ¥:!éK`¬Æ“›Õs=ºüï;þöŸì{^R²yá½ô·žá>cϼÃ}ÏÜxHùâÙ‡8ÍCœ=Ä9nýãäfö†ÁÑÁ endstream endobj 1783 0 obj [ 1782 0 R ] endobj 1781 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 1783 0 R /Contents 1784 0 R >> endobj 1785 0 obj 1417 endobj 1787 0 obj << /Type /Annot /Subtype /Link /Rect [ 286.93 295.902 352.93 304.902 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 621 0 R /H /I >> endobj 1789 0 obj << /Length 1790 0 R /Filter /FlateDecode >> stream xœÅYKsܸ¾Ï¯À)‘·<ðݼ²•õ–bÅ+%©Ôjk ÃÁhñ1&8’'¿> $Áá#[>8öaÐ t£ñu£»A}YùÃÿµþ‰Ai¾úby>Š ¢‘e…ò„(Gv¢L¯r¤ÁYƒ=úçªXaô—Õ¯¿Áäax]ásuðýê³³¿žÁß}ŒžV?>¬.oBäcô°ë!¢±G}ÿ"†=ÌrôëÅ{^ó WýÈÓçµ(¶êÍoèáçÕ‡‡Á‘¨OþGú<°Ü“Ø;sv#M 8F‘žÊ¬ì¯Ñj†Æ8ó;kîm®IC?×Íç]kA{ÉÀ¹$ ³ÞüΨ©÷îÎC‘ŽM0ÆþàXsc{(s¦ë²(DZ˲@÷‘ÊL¹¦ÌAUœi ˆúc Éh¹?5ÿŠÊJ;}kúZ5ìá AQèQ0S-írX|¶> Æëw2ÏÅì&>&c)ô§ò íãšßÎ&ì“…¬×»c‘º6%A4q´7‹€2ìÅÄ(¶yD¨´’ ¨ŽíX}ŸzALÁØLã4 wòûXì¾®dñ„*q¨„E­‰z/P«N¦éûÏ·²èETJ›KѶM‚z¥·l, _·œ6 ¦"oæ M]h«àðIÛ†è‘ð ìpjÝ߸RÆakÛ¥bÄ|'q”° = Ä3<ƒLÈwðnô³£è(S\6ŽóNB½H_=?œ²ñ*yY®æ“õ—ä;^e–uDZ ^‹ û».¤eÈ¢ö'n¯Å˜æ,UµàÛ©Óµ¿Æ®¥8:3—7í‚›¼•êù\ ÖÔÈÊæ¶žÙ‚dÉ+óâäµÌ…+ºãÊ–"Ë;‡pqmç¡xªdí*M÷"}¶¡Ý.s7PøÆÐÖFW^‰ºŠC^ž'ÀçàüëÓõO¿Ü}ºûû=ÚezÖÝÝÜ GP)ÚäþñáŽÑVÔ\fêñ·˜(ôõ1äŸØôpóþýíRb IâD4 È¢‹GëL— AWåkabègqz-«mÏp»AñÕŒ]]Úäžê _Ï*2©Z/Ø g[ȧÃÙ¬(†Snþ ÉÔÙKª1ÐpŸaêôvâ é"Átúg˜.á;^§ñ½2en­‰ZL;(5‚³õ‚ƒég4‰¦”›œ´~‘âu>Ù%xI….½EY#u<ʪ†{·ã¼+YŽÖ@åJFœ´¯ô|Sf2Õzy²/o} O}–$á2¸£uãa)Çi®áºÄó#ý|Ž¢ íл-”¼$úvaS.Iªr¡¸’}ë®Q°xÔâ´@‹(¡æ¦Îí 9ÌÓ²8ò'dÅW¸jvgJãaðñúN¨¦}]r•`xGg¡‚9ÃmÀ±½ówO3ñ¿Û¼è &IbóÿmÓ©K1o?ÄvF`v orF 7ðu©1»÷´û„3œ zkY™²i8õ’‚»ë=‘fÒæjC·o‹žó8ßd¦-¨B@| ЕfE­öž*ç%K:  ö¦ pÉÊ´}«XŽéŒZ¤rOµ'ì°ÙÙÝ̼'AP™Ïé*¡Ÿ1/B§`êÝ/ï®o?üþÓÝ_? Ó•ÚWš 0¨@ê-KŽDñ"«²Ðùû<B€‡&ÚwÅ­}ÞþÃd®.„¢©Ï—>ƒŽoðX¸…Ä7 zœxXâÓßƲͧ¦ß¶{®zBWXÓ#ZS¡Ô/†ylŸVÆxÌ}¬ÚyÀÆ®*óžêãÖÐLöc[ú§úر@‰êÅô+†Öí4oÞ¦¦$¡ï¢a €T=«°Ý~C¹3Ɔ?;k…!>ê]ÍÙ ãºÃÂÐî½3œÓ¿¸ê{:q¬0PBð ;‚¶î©·= |R9ª¤rWCõ$¹sH[%' èRÐŽjß~›UM‰GWe*cxzÀJ³«vÐŽ!Yý¯y GvVòm+4_%ô·K =Н¿iöN3xϯËA¦çš„-é@ïîßߨëë9]ù¼ú/þ¼Ì endstream endobj 1788 0 obj [ 1787 0 R ] endobj 1786 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 1788 0 R /Contents 1789 0 R >> endobj 1790 0 obj 2075 endobj 1792 0 obj << /Type /Annot /Subtype /Link /Rect [ 404.78 194.172 488.78 203.172 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1093 0 R /H /I >> endobj 1794 0 obj << /Type /Annot /Subtype /Link /Rect [ 264.16 182.172 366.16 191.172 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1077 0 R /H /I >> endobj 1795 0 obj << /Length 1796 0 R /Filter /FlateDecode >> stream xœÅWKsÛ6¾ëWì-v&Bð Ò·Úi:é$õx¬LqÙœPMPÕ_ß…Ú_qãJ.ÀÝoß ð~Æ€âî2ánf÷~ä "¿FÀÂCØ€§CÈ×Á[  wðû¬˜Qøeöå+¾\Eï3Ú…Û _Ï®ô»7ôÅõS¸/fo߇À(,ÖO!’–à/J &‚;c¶ØÀ—“wªVKe5œ«ôÛ\+{ú¿Î~^¹$ÿ\º:²Ó*¹$dï¥E³‡; {•û<øgƒÚqÍsÔ(úd=4é8Ï/ª|<ÅÒ 2Jâ£äò@Œfó…£ÖK¤ÓýèOÒõ'ˆS""Š¿ˆ5ÞÀÍI¹µwpfÒLBšŸ½^kUo+m_ßœ6ž">„ ìj}fJ]©Zëý*7j57%¼Js{ŸÏM¥Ò\!A±áyû^ÃÒŒñ;rÇ'Ò¥E2ÑÈ|(²:Syö§ª3S´½”¢ºD¡>'èg«[þ¡1ÁMÂ$4hþ»,<˜2—E!Ú‹ìöÚ€Sõ†Ë½Xú9C`›«vüÔ»RÃÚTC¬YLù~ü8Þ,$ĈaÀ}Ô.LQèÔ®Kfë,= ½pÍt`8gD& ÙÀ\ïŠZ=€YCú8·8•„„17}CÖ¦¤åGîŽ@ Üæf©òy¡6ãÉgœH¸&†)ê l­®Æu„WG8¤£TÖ~7ÕjT§CQhës,]K_2Ê_©ï´M«¬Üg}1º‚) ¸SÖÑK )޼(é‡ÏʬÎwäà[újö-RR endstream endobj 1793 0 obj [ 1792 0 R 1794 0 R ] endobj 1791 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 1793 0 R /Contents 1795 0 R >> endobj 1796 0 obj 1217 endobj 1798 0 obj << /Type /Action /S /GoTo /D [1797 0 R /XYZ 72.0 430.541 null] >> endobj 1799 0 obj << /Type /Annot /Subtype /Link /Rect [ 232.94 575.321 298.75 584.321 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1798 0 R /H /I >> endobj 1801 0 obj << /Type /Annot /Subtype /Link /Rect [ 232.94 553.441 298.75 562.441 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1798 0 R /H /I >> endobj 1802 0 obj << /Type /Action /S /GoTo /D [1797 0 R /XYZ 72.0 619.701 null] >> endobj 1803 0 obj << /Type /Annot /Subtype /Link /Rect [ 232.94 531.561 269.05 540.561 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1802 0 R /H /I >> endobj 1804 0 obj << /Type /Annot /Subtype /Link /Rect [ 232.94 441.921 298.75 450.921 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1798 0 R /H /I >> endobj 1805 0 obj << /Type /Annot /Subtype /Link /Rect [ 232.94 398.161 269.05 407.161 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1802 0 R /H /I >> endobj 1806 0 obj << /Type /Action /S /GoTo /D [1797 0 R /XYZ 72.0 263.261 null] >> endobj 1807 0 obj << /Type /Annot /Subtype /Link /Rect [ 232.94 230.881 261.82 239.881 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1806 0 R /H /I >> endobj 1808 0 obj << /Type /Annot /Subtype /Link /Rect [ 232.94 73.481 261.82 82.481 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1806 0 R /H /I >> endobj 1809 0 obj << /Length 1810 0 R /Filter /FlateDecode >> stream xœÅXKsÛ8 ¾ûWðèÌ$ªÞcÚ4î¤ÝIã™=Ô=02k«‡CJIóï$(‰6é&§nr0ăà‹€øð!²"$e³xÔ¼€d!‰RÍJRÄ^˜†èqBj9Ë„ã~p väŸE»ðɧÅ÷ðqC|x^øÇË)á»Å­¡_~ñÿ¸~Ó‚(ÿ nw! 3ïho”t„<ààBòS­Ã¦qU¢qø{Ò(¶ÉwE›ûç”ûäañ~µxwÀ'«íœ´™ |/ ù’UC¾/Ã8>ûAV->®¬ÝüÃQ³6Rêžü‰H{¹2þÀ-Ÿ„æ™ïûiŠ>}ª;!(AÇÞ]g2·L™ 'IàÅQ B¹Ä×®g£€;Èb/‹ HXí*AÎÈEêedù UN ã›è«ºž¨'fÌêwU[Ïä¾Û5íÙæ|bÑv3Û®ŸùÆ’œmgmÉfUkè`Ó¸¡æök^oGŸæi÷ŒÍÓö¼Û3nXYWíO¶ÁX™ÊÓ£IÛˮ㛪•N‘çªß‘^†m —GTŸe€v f;Ô ¨ÜÑö0u;ôg„³§JT]+¼#­*~î¥a^YŽJ/ûžW÷ø™³qì˜, ¢Ü F?ûƒÕmMâþ_VöÂàˆ¾ãlc00¸š ÆxC{zO3XÀ¨™g0&ÃM”›2œí9¬í´Rár5ô]-»zhZAÖËŽ“mÅêXŸÉS‚¦Ø¡C/ñaCôÐá*û ÒdôÆ¥Ö’¹càÁÑÄÔ÷Š%tJ\Áú[EüH8 !͇˜Ã,‡9Y’áœ]ÛÂ’J.Û­é¯ÚnI¼ÍvKÌa;œ¦0•û£ír]v[S_µÛ’8yjŠÌó‹üÄ!fÛ $ À`‰ÊV?+ÈòŠm«¶’;0ónà¸ôáX7,I|¸Øzyuu³>sDÁV¼àý`=ƒ|w{Cg ù¿QV´DBûE¤$TŠž¥B¢S®;<… ôCP˜é¡§qì“åÚV ͵«ŠyÚÓ$>Z <ýrÂSKñ !>‡r ¨„.O4‚Že&BEc¢dX&¢j@!„ä|æmXÍŽXÃÂ#7qt¹ÒK²¾Ü|ÞèZ A—£VP~³Yâ>äfšä‡s] [“_;1¶Ä›Nº-æ°ŽX&Ñ ˆÓ·,­°d.[‚J¦mÿ²g¿ÉÜ((¼4•qt¥¾–õÀ¡ÇžùZ l‰7A‹-æ0;¼Nx„‘a6Y·‚ÜíYYA]ã.7,ÉKòDëÁ‰§=ZT(PÁƒ 2Zî°Pb•| ssX•F^ …6OôN\CSP=¨Ô.䙿ÚrÅø õ›oii£@ér°Özy}ýÙ –ÚK¥ +°ûÓfÖ–wÍL}蚦3n*±Ÿ©¾›ÇtB»ÈxKë™SW÷\7½ÈxÞU´‰,»¶‡ŽS˜œf_Õv÷(=:v~«ý!¯úZR؇¶ˆèÕ8m .µÆTq.·®*©l!?86 ò-’gÑõY¼•;ê²Äš Á•Ð)zècè¿:Ê °]d ;êÞѦÆßAK&‘öîÛÕû/wåöLÙ¤^L–ß–µŠ#‘â=ö•І¢‘PjÎÝ‹“Gjj¡ñÓ uMQ#:D·íŸ±ïTôž–?aÑ‘„:á²: ެn¤)þpqÓý0ŽŒnªàpÌ ¤ðî2KÍbæËZŽW&dtüj/7­º5Æ%Ü“>ÎKñîÙÕKÇqtäÞl°¡Vm‰:NÏ—°ب·•p!r)±¦^BVèÀ½Néa‘K}ûPØ4Eô”й²9J €ßºg—Ö¼×ðÞ±²Óüðòd²(tÈØ'ÐÎÁeß ÆiKÆÆLu><Àu²¹JBùê‘(q޳Wm½ Xas¸¢}½û<í†òÍÄhb`K5Îî8ž¤1%q 0Â+¸âŸu²#QÍPCȃYÈ]ñh3@´<ŽÆ†àìã/yîÛ-ò±RØ+ËØT |àЮ]˜¨o²æ¹¼Õf¢t?ªWÑàz>±:C[;s±Ï™Èí4T¥{Zï±¾`Êà —{Ð[º'ãàˆ\–z œý¼Çf[1׊ÖLõº[˘Ô5›Úä¡á8c¤¦2Ф~K‰3ÚiÎü ôøb„ÄŒv#ÇX¬ö5n‹èoÞQÀÍ#W5&­—•Ǽs"” ¹>³#›¾ËÛdhÀ[qÚ zêznÏÇ–'ȼ\šÛ5U9Ó\2gJ?äà¸eÁçqÓqã‹NM$¦Üî5§ ÓÆà㜭¢=PNM}bP[åÊÕ4 <Çw2ö‹•°AGlãØ‹b(|ý¼¹’[íZÛšùâÛ¯#¾-ã¯Î·‹ÿD®Ç endstream endobj 1800 0 obj [ 1799 0 R 1801 0 R 1803 0 R 1804 0 R 1805 0 R 1807 0 R 1808 0 R ] endobj 1797 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 1800 0 R /Contents 1809 0 R >> endobj 1810 0 obj 1862 endobj 1812 0 obj << /Type /Action /S /GoTo /D [1772 0 R /XYZ 72.0 433.491 null] >> endobj 1813 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 709.5 191.33 718.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1812 0 R /H /I >> endobj 1815 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.998 709.5 539.998 718.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1812 0 R /H /I >> endobj 1816 0 obj << /Type /Action /S /GoTo /D [1772 0 R /XYZ 72.0 383.593 null] >> endobj 1817 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 697.5 176.78 706.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1816 0 R /H /I >> endobj 1818 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.997 697.5 539.997 706.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1816 0 R /H /I >> endobj 1819 0 obj << /Type /Action /S /GoTo /D [1772 0 R /XYZ 72.0 350.129 null] >> endobj 1820 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 685.5 204.1 694.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1819 0 R /H /I >> endobj 1821 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.998 685.5 539.998 694.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1819 0 R /H /I >> endobj 1822 0 obj << /Type /Action /S /GoTo /D [1772 0 R /XYZ 72.0 264.231 null] >> endobj 1823 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 673.5 219.11 682.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1822 0 R /H /I >> endobj 1824 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.997 673.5 539.997 682.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1822 0 R /H /I >> endobj 1825 0 obj << /Type /Action /S /GoTo /D [1772 0 R /XYZ 72.0 149.171 null] >> endobj 1826 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 661.5 270.214 670.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1825 0 R /H /I >> endobj 1827 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.952 661.5 539.952 670.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1825 0 R /H /I >> endobj 1829 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 649.5 191.33 658.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1828 0 R /H /I >> endobj 1830 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.998 649.5 539.998 658.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1828 0 R /H /I >> endobj 1832 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 637.5 171.78 646.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1831 0 R /H /I >> endobj 1833 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.998 637.5 539.998 646.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1831 0 R /H /I >> endobj 1835 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 625.5 204.1 634.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1834 0 R /H /I >> endobj 1836 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.998 625.5 539.998 634.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1834 0 R /H /I >> endobj 1837 0 obj << /Type /Action /S /GoTo /D [1775 0 R /XYZ 72.0 720.0 null] >> endobj 1838 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 613.5 219.11 622.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1837 0 R /H /I >> endobj 1839 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.997 613.5 539.997 622.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1837 0 R /H /I >> endobj 1840 0 obj << /Type /Action /S /GoTo /D [1775 0 R /XYZ 72.0 607.992 null] >> endobj 1841 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 601.5 270.214 610.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1840 0 R /H /I >> endobj 1842 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.952 601.5 539.952 610.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1840 0 R /H /I >> endobj 1843 0 obj << /Type /Action /S /GoTo /D [1775 0 R /XYZ 72.0 397.304 null] >> endobj 1844 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 589.5 191.33 598.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1843 0 R /H /I >> endobj 1845 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.998 589.5 539.998 598.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1843 0 R /H /I >> endobj 1846 0 obj << /Type /Action /S /GoTo /D [1775 0 R /XYZ 72.0 304.016 null] >> endobj 1847 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 577.5 244.201 586.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1846 0 R /H /I >> endobj 1848 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.954 577.5 539.954 586.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1846 0 R /H /I >> endobj 1849 0 obj << /Type /Action /S /GoTo /D [1778 0 R /XYZ 72.0 720.0 null] >> endobj 1850 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 565.5 179.0 574.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1849 0 R /H /I >> endobj 1851 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.998 565.5 539.998 574.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1849 0 R /H /I >> endobj 1852 0 obj << /Type /Action /S /GoTo /D [1778 0 R /XYZ 72.0 695.117 null] >> endobj 1853 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 553.5 204.1 562.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1852 0 R /H /I >> endobj 1854 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.998 553.5 539.998 562.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1852 0 R /H /I >> endobj 1855 0 obj << /Type /Action /S /GoTo /D [1778 0 R /XYZ 72.0 630.263 null] >> endobj 1856 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 541.5 219.11 550.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1855 0 R /H /I >> endobj 1857 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.997 541.5 539.997 550.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1855 0 R /H /I >> endobj 1858 0 obj << /Type /Action /S /GoTo /D [1778 0 R /XYZ 72.0 497.291 null] >> endobj 1859 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 529.5 270.214 538.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1858 0 R /H /I >> endobj 1860 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.952 529.5 539.952 538.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1858 0 R /H /I >> endobj 1861 0 obj << /Type /Action /S /GoTo /D [1778 0 R /XYZ 72.0 299.582 null] >> endobj 1862 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 517.5 191.33 526.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1861 0 R /H /I >> endobj 1863 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.998 517.5 539.998 526.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1861 0 R /H /I >> endobj 1864 0 obj << /Type /Action /S /GoTo /D [1778 0 R /XYZ 72.0 246.728 null] >> endobj 1865 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 505.5 214.275 514.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1864 0 R /H /I >> endobj 1866 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.916 505.5 539.916 514.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1864 0 R /H /I >> endobj 1867 0 obj << /Type /Action /S /GoTo /D [1778 0 R /XYZ 72.0 211.786 null] >> endobj 1868 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 493.5 204.1 502.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1867 0 R /H /I >> endobj 1869 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.998 493.5 539.998 502.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1867 0 R /H /I >> endobj 1870 0 obj << /Type /Action /S /GoTo /D [1778 0 R /XYZ 72.0 146.932 null] >> endobj 1871 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 481.5 219.11 490.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1870 0 R /H /I >> endobj 1872 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.997 481.5 539.997 490.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1870 0 R /H /I >> endobj 1873 0 obj << /Type /Action /S /GoTo /D [1781 0 R /XYZ 72.0 674.283 null] >> endobj 1874 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 469.5 270.214 478.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1873 0 R /H /I >> endobj 1875 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.952 469.5 539.952 478.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1873 0 R /H /I >> endobj 1876 0 obj << /Type /Action /S /GoTo /D [1781 0 R /XYZ 72.0 546.402 null] >> endobj 1877 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 457.5 191.33 466.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1876 0 R /H /I >> endobj 1878 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.998 457.5 539.998 466.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1876 0 R /H /I >> endobj 1879 0 obj << /Type /Action /S /GoTo /D [1781 0 R /XYZ 72.0 290.373 null] >> endobj 1880 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 445.5 214.275 454.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1879 0 R /H /I >> endobj 1881 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.916 445.5 539.916 454.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1879 0 R /H /I >> endobj 1882 0 obj << /Type /Action /S /GoTo /D [1781 0 R /XYZ 72.0 255.773 null] >> endobj 1883 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 433.5 204.1 442.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1882 0 R /H /I >> endobj 1884 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.998 433.5 539.998 442.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1882 0 R /H /I >> endobj 1885 0 obj << /Type /Action /S /GoTo /D [1781 0 R /XYZ 72.0 191.603 null] >> endobj 1886 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 421.5 219.11 430.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1885 0 R /H /I >> endobj 1887 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.997 421.5 539.997 430.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1885 0 R /H /I >> endobj 1888 0 obj << /Type /Action /S /GoTo /D [1786 0 R /XYZ 72.0 720.0 null] >> endobj 1889 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 409.5 270.214 418.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1888 0 R /H /I >> endobj 1890 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.952 409.5 539.952 418.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1888 0 R /H /I >> endobj 1891 0 obj << /Type /Action /S /GoTo /D [1786 0 R /XYZ 72.0 499.932 null] >> endobj 1892 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 397.5 191.33 406.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1891 0 R /H /I >> endobj 1893 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.998 397.5 539.998 406.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1891 0 R /H /I >> endobj 1894 0 obj << /Type /Action /S /GoTo /D [1786 0 R /XYZ 72.0 246.198 null] >> endobj 1895 0 obj << /Type /Annot /Subtype /Link /Rect [ 144.0 385.5 170.65 394.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1894 0 R /H /I >> endobj 1896 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.998 385.5 539.998 394.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1894 0 R /H /I >> endobj 1897 0 obj << /Type /Action /S /GoTo /D [1786 0 R /XYZ 72.0 211.853 null] >> endobj 1898 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 373.5 204.1 382.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1897 0 R /H /I >> endobj 1899 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.998 373.5 539.998 382.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1897 0 R /H /I >> endobj 1900 0 obj << /Type /Action /S /GoTo /D [1786 0 R /XYZ 72.0 148.193 null] >> endobj 1901 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 361.5 236.997 370.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1900 0 R /H /I >> endobj 1902 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.953 361.5 539.953 370.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1900 0 R /H /I >> endobj 1903 0 obj << /Type /Action /S /GoTo /D [1791 0 R /XYZ 72.0 672.0 null] >> endobj 1904 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 349.5 219.11 358.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1903 0 R /H /I >> endobj 1905 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.997 349.5 539.997 358.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1903 0 R /H /I >> endobj 1906 0 obj << /Type /Action /S /GoTo /D [1791 0 R /XYZ 72.0 551.264 null] >> endobj 1907 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 337.5 270.214 346.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1906 0 R /H /I >> endobj 1908 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.952 337.5 539.952 346.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1906 0 R /H /I >> endobj 1909 0 obj << /Type /Action /S /GoTo /D [1791 0 R /XYZ 72.0 365.968 null] >> endobj 1910 0 obj << /Type /Annot /Subtype /Link /Rect [ 168.0 325.5 191.33 334.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1909 0 R /H /I >> endobj 1911 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.998 325.5 539.998 334.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1909 0 R /H /I >> endobj 1912 0 obj << /Type /Action /S /GoTo /D [1797 0 R /XYZ 72.0 720.0 null] >> endobj 1913 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 313.5 155.55 322.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1912 0 R /H /I >> endobj 1914 0 obj << /Type /Annot /Subtype /Link /Rect [ 524.997 313.5 539.997 322.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1912 0 R /H /I >> endobj 1915 0 obj << /Length 1916 0 R /Filter /FlateDecode >> stream xœÅÝM³dÙuáyÿŠš!yÎZûc Á„PXÀÀÁ@È t„,d>̯'OUÛÊ]'w?²Ã¨ÝQýî[÷ꩪÎÜqîZÿã»ãÓãù×?¹þ6êüô‹¿üîüøcǧq~ŠþãµþéÈÏgûô—Ÿ~üçöé—WõòçßüÓóo_£ç?ü·Oÿñ»_}÷øô'ßýùzþË¿øôxøßß=¾ýp_ÿÙw?}ùù¯óøÿùŸþëwÿügßýÓùüáǧŸý—ßý_ísÕãñ8úü4?ÇY×ÿÎO?ûËOþ“?úÓ?ûéŸþãÿôégÿúy²}{²÷ÛOÿþ·ßÿæ·ÿèÓŸüÏþâû¯ÿøgË—ÇùÿáËÿéò9< Œs|þæÆ—ÓñõÇž?òõ]ÿê—?šýø÷¯õë?~ýä¾þý÷~Rß}N×Oiý5ñú“ÿí/‡êÈÏÇñüåðèÏOëñy.¼ÿë‡ßkúüÿÝóú¹ÿWU÷_ªÿö×õýo¿~9›G}ޏ~3̸ÿÚþÇÏäèŸëÓO¾=vžÏßC×o¢ÖnÇ>ßâ&ñ|ÆóùïŸÅ‡q§Äâ|Hw‰ âvJÜ$Á.‚]»"8DpˆàÁ)‚SKK Ïž< x>@ð<@ð<@ð<@ð@0 ˜æ‚y€` ˜'æ ‚)w2)w2)w2)w2)w2)w2™uãñ8àÊ,¿\¸ŒšmæíØã›|œÏ÷’ßTÿæ¯ÿörúwo’Ÿ¿Æx6sÌû‰¯ŸN~>î7xÏ×6ù|·Z£¿ù™noÅŸ/n¤Nª‡ÔÏBê ºS]Ïúù« m£~¾Æ‘ºQ=¥Îƒê¤zHÝTÕj²ìdÙɲ“å ËA–ƒ,'YN²œd9ɲȲȲÄò|ˆåùËó!–Ïj±<±<±Ä2b™±ÌC,óË<Ä2O±ÌS,óË<É2È2È2È2É2Éòºm­æho^ÿþ[È/E:ßÜ^ÞoE«?ÿÓü»¿TúÃþÍÏóÃýÑÆgù7ÏuÞ}ý”ÎÏçýbôI0ÎóŠÏû¹wWoP? ¤Nª‡ÔíAuPÝ©.©ûI5Yv²d9Èrå$ËI–“,'YYY–X^WoR‹åuõõ!–×Õ›Ôby]½A}Šåuõ&5YYYY&Y&Y&Y&Y6²ldÙ.ËçïΜoþSþîêMê¤zH=TÕê’zžT7ªÉ²È²È²Äòºz“Z,¯«7©Åòºz“Z,¯«7¨O±¼®Þ¤&Ë Ë Ë Ë Ë$Ë$Ë$ËF–,Yv²ìdÙɲ“å ËA–ƒ,'YN²œdYdYdYdYby]½I-–×ÕÔ‡X^WoR‹åuõ&µX^WoR“eeee’e’åuõ6úã1Sî¹–çoçÞ^½=?¯µúW¿úá¯~øù/ø¿?ÿ«~ý«7RûÕ·£_>±ç‹¥~¿€kÏ}´ªœã~îÝÕ”Ôê’ºŸT7ª§Ôã :©RO²œd9Ér’e‘e‘e‰åu5%µX^WSPby]MI-–×ÕÔ§X^WSR“eeee’e’e’e’e#ËF–,;Yv²ìd9Èrå ËA–“,'YN²,²,²,±¼®¦¤ËëjJj±¼®¦¤Ëëj êS,¯«)©É2È2È2È2È2É2É2ɲ‘e#ËF–,;Yv²ìd9Èrå ËI–“,'YYYY–X^WSR‹åu5õ!–×Õ”Ôby]MI-–×Õ”Ôdddd™d™dy}ÇÇó…Äõ •r´<v;÷öjªõoª?úõ¯~õý/®k©ëç¹þ€øô“?ûïßÿâ‡ÿòÃ/ÞÞV=ß•ŸG>ÏŸüþÑ~÷1Þ¼=o×3r=ò~ìÝÛs©‡ÔÏ·çRÕê’úùö\êFõ”:È2È2È2É2É2É2ɲ‘e#ËF–,;Yv²d9Èrå ËI–“,'YYY–X^oÏ¥Ëëí¹Ôby½=—Z,¯·çPŸby½=—š,ƒ,ƒ,ƒ,ƒ,“,“,“,Y6²ldÙɲ“e'ËN–ƒ,Y²œd9Ér’e‘e‘e‘e‰åõö\j±¼ÞžC}ˆåõö\j±¼ÞžK-–×Ûs©É2È2È2È2É2Éòzmÿ|3?çð–÷Ë»óvTµÙîÇÞ¾;ïó›êÃQô·›³èoç¾ý¢—aôõËä³ë×ÑguR=¤~~¶QÕê’úu*ýFݨ&ËN–,;Y²d9Èrå$ËI–“,‹,‹,K,—)õµX.sê7j±\&ÕoÔb¹Ìªÿ¸>År™V¿Q“eeeee’e’e’e#ËF–,;Yv²ìdÙÉrå ËA–“,'YN²,²,²,²,±\æØoÔb¹L²ÿ¸>Är™e¿Q‹å2Í~£ËežýFM–A–A–A–I–I–I–,Y6²ldÙɲ“e'ËA–ƒ,YN²œd9Ér’e‘e‘e‰å2è~£ËeÔýÇõ!–˰ûZ,—q÷×§X.ï7j²¤{Ÿ¤{Ÿ¤{Ÿ¤{Ÿ¤{Ÿeî=ÜÏ-ßhv;wÆü¦ç§çŸ.kõïþÅ?ÿ£o¯ëwsïoý×Ϧ½»-¼&iF=Ïg÷s·w÷×$M¨Kêk’&Ôê)õ5Iê¤zH}MÒ|þ‘^-úNTwªKêk’&Ôê)õ5Iê¤zHÝɲ“e'ËN–ƒ,Y²œd9Ér’e‘e‘e‘e‰åùËó!–çC,ÏC,ÏC,ÏC,ÏS,ÏS,ÏS,Ï“,ƒ,ƒ,ƒ,“,“,“,Y6²ldÙȲ“e'ËN–ƒ,Y²œd9Ér’å$Ë"Ë"ËËxˆe<Ä2b‡XÆ!–qˆeb§XÆ)–q’eeee’e’e’e’e#ËF–,;Yv²ìd9Èrå ËA–“,'YN²,²,²,±Ì‡XæC,ó!–ùË<Ä2±ÌC,óË<Å2O²¤{Ÿ¤{Ÿ¤{Ÿ¤{Ÿ¤{Ÿ¤{Ÿ/÷­ÏzÖù¦þý7œë¢ÑoÏÝï[«ª?d¦þíÐæLýÛ¹ûÕÛ”úu¦þFT©_gêoÔAu§º¤~©¿Q“e'ËA–ƒ,YN²œd9Ér’e‘e‘e‰å2S£Ëe¦þÇõ!–ËLýZ,—™ú×§X.3õ7j² ² ² ²L²L²L²L²ldÙÈòu¦þÇõëLý:©R¿ÎÔߨƒêNuIý:S£nT“e‘e‘e‰e<Är™©¿Q‹å2SÿãúËe¦þF-–ËLýZ,—™ú×A–A–A–A–I–I–I–,Y6²ìdÙɲ“e'ËA–ƒ,YN²œd9ɲȲȲȲÄr™©¿Q‹å2SÿãúËe¦þF-–ËLýZ,—™ú5YYYY&Y&Y¾ÎÔ‡{®åêívîíÕÛñøÃ‡êßÏnNÕ¿|w;Ey·¼(¬¿“7Ë'å¯Ãõwò´|P>Mušê4ÕiªeªeªEªË˜ýœT—AûùAªË¨ýœT—aûùIªË¸ýÜTÃTÃTÃTÓTÓTÓTÓT›©6Sm¦ÚMµ›j7ÕaªÃT‡©S¦:Mušj™j™j‘j(·“‡åÝò¢üu9ÀNÞ,7ÕnªÝT»©S¦:Lu˜ê4ÕiªÓTËTËT‹T—e;9©.ëvrR]ì䤺¬ ØÈOR]–ì䦦¦¦¦š¦š¦š¦ÚLµ™j3ÕnªÝT»©vS¦:Lu˜ê4ÕiªÓTËTËTËT‹T—u;9©. 6òƒT—•;9©.KvrR]Ö ì䦦¦¦š¦š¦š¦ÚLµ™j3ÕfªÝT»©vS¦:Lu˜ê4ÕiªÓT§©–©–©©.ûvrR]6lä©.;vrR]¶lä'©.{vrSµ»¥´»¥´»¥´»¥´»¥eý€\.ß”w?øþ~2¿›õã3I×Oó|Ÿ~òÇÿççùßy¿³|¾˜>¯O2ñæÃüîüíÜõ¸XTµoÎÝ/Y&å_í„<-”y´ò°¼[^’Ÿ_턜TÏ©ž©ž©ž©ž'©ž'©ž'©ž§©†©†©†©¦©¦©¦©6Sm¦úåÛ†Ÿ/MŽóÝ–÷¼(ÿòmÃ7Ë'å_¾mò´|PþåÛ†!ËMušj™j™j‘jÎ^oÞn ®×L’wË‹òë5“äÍòIùõšIò´|Pž¦š¦š¦š¦ÚLµ™j3ÕnªÝT»©S¦:Lu˜ê4ÕiªÓTËTËT‹T¯§Ü('Õë)7ÊIõzÊrR½žr“ü$Õë)7ÊM5L5L5L5L5M5M5Mµ™j3ÕfªÝT»©vSí¦:Lu˜ê0ÕiªÓT§©–©–©–©©^O¹QNª×Sn’¤z=åF9©^O¹QNª×Sn”›j˜j˜j˜jšjšjšj3ÕfªÍT›©vSí¦ÚMu˜ê0ÕaªÓT§©NS¦Z¦Z¦Z¤z=åF9©^O¹InwKiwKiwKiwKiwKiwKiwKiwKiwKiwKiwKiwK_žrëÏ_ÆÑí"s}ÊívðÌÇ7®§Üú·ºvö>ÞOm.~¼¼_óMÊ_W?îäiù üuûãN–wË‹ò× ;¹©vS¦:Lu˜ê4ÕiªÓT§©–©–©©.ë wrR]Bnä©.+!wrR]–Bnä'©.k!wrS S S SMSMSMSMSm¦ÚLõuCäFþº"r'OËå¯["wò°¼[^”¿nŠÜÉ›å¦Z¦Z¦Z¤R]Fî䤺¬ŒÜÈR]–Fî䤺¬ÜÉIuY¹‘‡©†©†©†©¦©¦©¦©6Sm¦ÚLµ›j7ÕnªÝT‡©S¦:Mušê4Õ2Õ2Õ2Õ"Õe£äNNªËNÉü Õe«äNNªË^ÉœT—Í’;¹©†©†©†©¦©¦©¾.˜” µõšïvðý5ßøv&¬˜¼Ý]1y;øîŒònyQ¾¬˜ÜÈ›å“òeÅäFž–ʧ©NS¦:MµLµLµHu]1¹‘“êºbòãü ÕuÅäFNªëŠÉó“Tד¹©†©†©†©¦©¦©¦©¦©6Sm¦ÚLµ›j7ÕnªÃT‡©S¦:Mušê4Õ2Õ2Õ"Õxêºbr#'ÕuÅäÇùAªëŠÉœTד9©®+&?ÎÃTÃTÃTÃTÓTÓTÓT›©6Sm¦ÚMµ›j7ÕnªÃT‡©S¦:Mušj™j™j™j‘êºbr#'ÕuÅäÇùAªëŠÉœTד9©®+&7rS S S SMSMS]VLÂ-Óºbòvðý ØüvêÛßmÅäíÃm®˜¼{÷¦ŸòAù²br#Ë»åEù²br#o–OÊÃTÃTÃTÓTÓTÓTÓT›©6Sm¦ÚMµ›j7ÕaªÃT‡©S¦:Mušj™j™j‘jΗ©dyZ>(_¦’mäay·¼(_&ÞoäÍrSí¦ÚMµ›ê0ÕaªÃT‡©NS¦:MµLµLµHux¿‘“ê:ñ~#'ÕuâýFNªëÄûó“T׉÷¹©†©†©†©†©¦©¦©¦©6Sm¦ÚLµ›j7ÕnªÝT‡©S¦:Mušê4Õ2Õ2Õ2Õ"ÕuâýFNªëÄûóƒT׉÷9©®ï7rR]'Þo䦦¦¦š¦š¦š¦ÚLµ™j3ÕfªÝT»©vS¦:Lu˜ê4ÕiªÓT§©–©–©©®ï7rR]'Þœ¤ºN¼ßÈIuxÿq~’ê:ñ~#7U»[J»[J»[J»[J»[Z'ÞÃeàú]y·ƒ÷ûÉkâýó%ñšmL¼ÛõÖËÄûÛÜx;x¿E›”/ï7ò´|P¾L¼ßÈÃònyQ¾L¼ßÈMu˜ê4ÕiªÓTËTËTËT‹T׉÷9©®ï?ÎR]'Þo䤺N¼ßÈIux¿‘›j˜j˜j˜jšjšjšj3ÕfªËÄû¼(_&ÞoäÍòIù2ñ~#OËåËÄû<,7ÕiªeªeªEªëÄûœT׉÷ç©®ï7rR]'ÞœŸ¤ºN¼ßÈM5L5L5L5M5M5M5Mµ™j3ÕfªÝT»©vS¦:Lu˜ê0ÕiªÓT§©–©–©©®ï7rR]'Þo䤺N¼ßÈIuxÿq~’ê:ñ~#7Õ0Õ0Õ0Õ0Õ4Õ4Õeâ=Üa­ïoß?8ó›lkâýíÔîÄûÛÁÛÕÁ2ñþã|™x¿‘§åƒòeâýF–wË‹òeâýFnªÝT‡©S¦:Mušê4ÕiªeªeªEªëÄûœT׉÷ç©®ï7rR]'ÞœŸ¤ºN¼ßÈM5L5L5L5M5M5M5Mµ™j3ÕeâýÇù2ñ~#OËåËÄû<,ï–åËÄû¼YnªeªeªEªñ ÕuâýFNªëÄûóƒT׉÷9©®ï7rR]'Þœ‡©†©†©†©¦©¦©¦©6Sm¦ÚLµ›j7ÕnªÝT‡©S¦:Mušê4Õ2Õ2Õ2Õ"ÕuâýFNªëÄûóƒT׉÷9©®ï7rR]'Þo䦦¦¦š¦š¦ºL¼‡ µõÙºÛÁ÷×|Ïß‹kïogw'Þß¾»£¼[^”/ï7òfù¤|™x¿‘§åƒòiªÓT§©NS-S-S-R]'Þo䤺N¼ÿ8?Hux¿‘“ê:ñþãü$ÕuâýFnªaªaªaªiªiªiªiªÍT›©6Sí¦ÚMµ›ê0ÕaªÃT‡©NS¦:MµLµLµH5¤ºN¼ßÈIuxÿq~ê:ñ~#'ÕuâýFNªëÄûó0Õ0Õ0Õ0Õ4Õ4Õ4ÕfªÍT›©vSí¦ÚMµ›ê0ÕaªÃT§©NS¦Z¦Z¦Z¦Z¤ºN¼ßÈIuxÿq~ê:ñ~#'ÕuâýFNªëÄûÜTÃTÃTÃTÓTÓT—‰÷pË´N¼¿|{v ÏX³¿ÓÄûû‡Û›x?÷îM?åƒò׉÷;yXÞ-/Ê_'ÞïäÍòIy˜j˜j˜jšjšjšjšj3ÕfªÍT»©vSí¦:Lu˜ê0ÕaªÓT§©NS-S-S-R]&Þï䤺L¼ßÉIu™x¿““ê2ñ~#?Iu™x¿“›j˜j˜j˜j˜jšjšjšj3ÕfªÍT»©vSí¦ÚMu˜ê0ÕaªÓT§©NS-S-S-S-R]&Þï䤺L¼ßÈR]&Þï䤺L¼ßÉIu™x¿“›j˜j˜j˜jšjšêëÄ{x½L¼¿Ÿ;ó|óžÿä‰÷÷#›ïï¿ýÊ—‰÷;ùËT²üu*ÙNž–Ê_§’íäay·¼(x¿“7ËMµ›j7ÕnªÃT‡©S¦:Mušê4Õ2Õ2Õ"ÕeâýNNªËÄûœT—‰÷;9©.ï7ò“T—‰÷;¹©†©†©†©†©¦©¦©¦©6Sm¦ÚLµ›j7ÕnªÝT‡©S¦:Mušê4Õ2Õ2Õ2Õ"ÕeâýNNªËÄûü ÕeâýNNªËÄûœT—‰÷;¹©†©†©†©¦©¦©¦©6Sm¦ÚLµ™j7ÕnªÝT‡©S¦:Mušê4ÕiªeªeªEªËÄûœT—‰÷ùAªËÄûœT—‰÷ùIªËÄûÜTín)ín)ín)ín)íni™x/—ËwåÝÞï'Çùå?³köï~óó_üòûoo2ççÞ®ûÉoŽüͧ÷ûÉçk³8âñˆ–oÞî ž¯Í(Ÿ”?_›Qž–Ê/ÉÃònyQ¦¦¦š¦š¦š¦ÚLµ™j3ÕfªÝT»©vS¦:Lu˜ê4ÕiªÓT§©–©–©©^Ï¡RNª×s¨’¤z=‡J9©^Ï¡J~’êõ*妦¦¦š¦š¦š¦š¦ÚLµ™j»TÏšóœ;y?,OËåãayXÞ-/Êçiy³ÜTËTËT‹T¯çP)'Õë9TÊIõz•rR½žC•ü$Õë9TÊM5L5L5L5L5M5M5Mµ™j3ÕfªÝT»©vSí¦:Lu˜ê0ÕiªÓT§©–©–©–©©æƒTóAªù ÕÅòº½‘š,ƒ,ƒ,ƒ,ƒ,“,“,“,Y6²ldÙɲ“e'ËN–ƒ,Y²œd9Ér’e‘e‘e‘e‰åuG#µX^74PbyÝÏH-–×íŒÔbyÝÍHM–A–A–A–I–I–×kû–?~“íþmÇ×€Ï×BgÅ›sïïdú·£÷7_ÞÏnn¾¼¼½ÙÝ|¹“wË‹ò×Í—;y³|Rþºùr'OËåÓT§©NS¦Z¦Z¦Z¤ºl¾ÜÉIuÙ|¹‘¤ºl¾ÜÉIuÙ|¹‘Ÿ¤ºl¾ÜÉM5L5L5L5M5M5M5Mµ™j3ÕfªÝT»©vS¦:Lu˜ê0ÕiªÓT§©–©–©©.›/wrR]6_î䤺l¾ÜÉIuÙ|¹‘Ÿ¤ºl¾ÜÉM5L5L5L5L5M5M5Mµ™j3ÕfªÝT»©vSí¦:Lu˜ê0ÕiªÓT§©–©–©–©©.›/wrR]6_nä©.›/wrR]6_î䤺l¾ÜÉM5L5L5L5M5Mõuó¥Ü2-›/ïŸïiÞÜ€Ío‡ÑýÝ6_Þ>ÜææËÛ¹woú)”/›/7ò°¼[^”/›/7òfù¤Þ|y;²»ùòvðÛ¯|Ý|¹‘¿n'ø8_¶läiù |ÙN°‘‡åÝò¢|Ù|¹‘7ËMµ›j7ÕnªÃT‡©S¦:Mušê4Õ2Õ2Õ"ÕuóåFNªëæËœT×Í—9©®›/?ÎOR]7_n䦦¦¦¦š¦š¦š¦ÚLµ™j3ÕnªÝT»©vS¦:Lu˜ê4ÕiªÓTËTËTËT‹T×Í—9©®›/?ÎR]7_n䤺n¾ÜÈIuÝ|¹‘›j˜j˜j˜jšjšjšj3ÕfªÍT›©vSí¦ÚMu˜ê0ÕaªÓT§©NS¦Z¦Z¦Z¤ºn¾ÜÈIuÝ|ùq~êºùr#'ÕuóåÇùIªëæËÜTín)ín)ín)ín)íniÝ| —뤤ÛÁûýdÎ/¿ü×ìO~ùëßþöç¿ùëoÚçŸ7íÚ}ù|ùôæÐ×O*Þ|RÏסǬë;ë͹o¿öçËP©ƒêNuI}mø¤¼Y>)¾¥<-'ÑkÃ'ådzmø¤üR}þNlÑwòk€äÍòIy–§åƒòö°<,ï–›j7ÕnªÝT‡©S¦:Mušê4ÕiªeªeªEª×󶔓êõ¼­ä©^ÏÛRNª×ó¶’Ÿ¤z=oK¹©†©†©†©¦©¦©¦©¦©6Sm¦ÚLµ›j7ÕnªÃT‡©S¦:Mušê4Õ2Õ2Õ"Õëy[ÊIõzÞ–rR½ž·¥œT¯çm%?IõzÞ–rS S S S SMSMSMSm¦ÚLµ™j7ÕnªÝT»©S¦:Lušê4ÕiªeªeªeªEªù Õ|j>H5R̓Tó Õ> endobj 1916 0 obj 10319 endobj 312 0 obj << /Type /Action /S /GoTo /D [1917 0 R /XYZ 72.0 720.0 null] >> endobj 315 0 obj << /Type /Action /S /GoTo /D [1917 0 R /XYZ 72.0 690.141 null] >> endobj 318 0 obj << /Type /Action /S /GoTo /D [1917 0 R /XYZ 72.0 610.85 null] >> endobj 321 0 obj << /Type /Action /S /GoTo /D [1917 0 R /XYZ 72.0 283.519 null] >> endobj 324 0 obj << /Type /Action /S /GoTo /D [1917 0 R /XYZ 72.0 249.432 null] >> endobj 327 0 obj << /Type /Action /S /GoTo /D [1917 0 R /XYZ 72.0 186.288 null] >> endobj 330 0 obj << /Type /Action /S /GoTo /D [1917 0 R /XYZ 72.0 123.144 null] >> endobj 1918 0 obj << /Type /Action /S /GoTo /D [1797 0 R /XYZ 72.0 219.501 null] >> endobj 1919 0 obj << /Type /Annot /Subtype /Link /Rect [ 277.692 636.47 295.472 645.35 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1918 0 R /H /I >> endobj 1921 0 obj << /Type /Annot /Subtype /Link /Rect [ 277.692 636.35 295.472 645.35 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1918 0 R /H /I >> endobj 1922 0 obj << /URI (http://cclan.sourceforge.net) /S /URI >> endobj 1923 0 obj << /Type /Annot /Subtype /Link /Rect [ 476.444 199.788 508.124 208.788 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1922 0 R /H /I >> endobj 1924 0 obj << /Type /Annot /Subtype /Link /Rect [ 516.1 199.788 540.0 208.788 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1922 0 R /H /I >> endobj 1925 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 187.788 205.52 196.788 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1922 0 R /H /I >> endobj 1926 0 obj << /URI (http://uffi.b9.com/) /S /URI >> endobj 1927 0 obj << /Type /Annot /Subtype /Link /Rect [ 172.79 136.644 195.56 145.644 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1926 0 R /H /I >> endobj 1928 0 obj << /Type /Annot /Subtype /Link /Rect [ 201.67 136.644 275.01 145.644 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1926 0 R /H /I >> endobj 1929 0 obj << /Type /Action /S /GoTo /D [1797 0 R /XYZ 72.0 364.901 null] >> endobj 1930 0 obj << /Type /Annot /Subtype /Link /Rect [ 415.55 136.764 431.1 145.644 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1929 0 R /H /I >> endobj 1931 0 obj << /Type /Annot /Subtype /Link /Rect [ 415.55 136.644 431.1 145.644 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1929 0 R /H /I >> endobj 1932 0 obj << /URI (http://files.b9.com/md5/) /S /URI >> endobj 1933 0 obj << /Type /Annot /Subtype /Link /Rect [ 338.57 73.5 356.35 82.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1932 0 R /H /I >> endobj 1934 0 obj << /Type /Annot /Subtype /Link /Rect [ 362.18 73.5 458.86 82.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1932 0 R /H /I >> endobj 1935 0 obj << /Length 1936 0 R /Filter /FlateDecode >> stream xœÅYIwÜ6¾÷¯À-ò{Œ…àâ›"f4#%r,¿lØl¶ ›ls±£üú) &H*sÉ$¡ÐU¨½ðþº¡ˆÀÿ—êO”0”7_ÍEC<4["D4ÀL #2k Åå,ذ‚?š ôë¦ÜôÏͧ/ðãø¾!Óãzá›÷Ž~õ ùÛõ»pÊþ/¼?ÏBÄ"<ÉM/ÍõìèƒÔO… ›ù«OÕKmœþ»h±6‘ù sÿ>å=m~|ܼ¹ˆô¸·E ¬öpÌõCGô邾ú‚ÿ½ùÇ£—Ë¿9f^•îÑŽX€ãÞô3§b³8"„„¡öèúžÚ¼F£Û²­«]—µ²*µŸýIGЫçLjÇ„&I eØóÐÕ§ªÉ±pÎ F1ÅA š9Tß}x7Hø ˆ1¡ÀÎ@…'Š^KŒCt!»Níòº:«ÒÒw²99B%¸¼O³Ünµ•]/zÁˆÀa¡|ƨ5oã8ˆ@’@­,¹#ÐÅ.mÓmÚä ¶{WvYvÇ-$k¤«½]Ÿ¹,Î\JOE~ÌË6Uémìi¹ÓV»¹J¸ï[/"`ZX#íVZç–hºÓ©ªÛ|‡íÞãÁaxÊ˼N G¢­¡î:÷ãZ¿^NHCSBiúF¯K@6!IBõe­r鸩¼Þ96–vݺê\œí”f¿§OÏöÙ;…;·Ceñתþ½Awí¿Ð–”‡˜$š†›õ/Ù´Uý¼¥3„£"ˆCH-¤sECLWB ˆ|¬fc0sÄzèM0“Ì©uŸêê·> endobj 1936 0 obj 2158 endobj 1044 0 obj << /Type /Action /S /GoTo /D [1937 0 R /XYZ 72.0 720.0 null] >> endobj 1938 0 obj << /Type /Annot /Subtype /Link /Rect [ 187.72 560.768 250.77 569.648 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1798 0 R /H /I >> endobj 1940 0 obj << /Type /Annot /Subtype /Link /Rect [ 187.72 560.648 250.77 569.648 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1798 0 R /H /I >> endobj 1941 0 obj << /Length 1942 0 R /Filter /FlateDecode >> stream xœÅWMsÛ6½óWìøÐq2 €ø íŒR+fZϸRÛCœñÐ"$1¡H™¤bëßw!€²LArœƒ+xûvßîð]@àßÀžS¿ù“ÁhrÍWVí ‘†{OBè“°¶ÉU.(ÓeºÔ6( <–„D ³>¶€É__þ:œŒÃÉðÝp< ߨ$!O[ðä~͘êÔ)\ÔÕ Ò¢€6½-tó#|Íõ=>ò2Óº´Ì Ñwk]Nñ-/!…,ŵi£Ã.2剌Ó$‰¤%z¿.§m^•済2 “DQ'âxS¶éCL¡G=§cÔS O,LÙÏ¿ÀóºÑ( #’«®£†õ|½Ôek³øOZ¬usÜe££P!!¥òz|PÄ”Hl¸óW¨3þ‰ŽBuûYOÛã¼*•B3œ)™&‹¼û+;Ó³t]´ÐVÐ.4|5:@5ƒ·nb—ù·á7¨ C… $]e_èfZç«ýâö¶:ÁÞ£œ%”¾´õN”BÁœ‡LÏf‘%›ƒJ0àC<Ü/ò颲1J~—x,RÆ2Öväz{ô.WÅcYúº›)ÆJ¢?¤ÛæÎ‹¼iV·ë7½Ž5˜÷ ØB×çgíf¥o¶°3°/·ùWy‰#\~æ%L¤ßG—L&"±×ÉΓ՗G_¶cã ¼¶ñóokÊ‹ˆúªZöB—yÙÜÌëj½òSñ¾¶ŽjW«^”è défUedMk?—ìKt}¸a{q_ÝúdYòâÒâÄSZ—¿ÿáYI_^œyjÂo¿4ã\x2î·-¿'Å\yRì·÷£Ü?¯Oí ÂhÊeóØm¿ã<Ó0šÍð°hNí¿õ’J%*îxü³ÊòYŽ¥„;7î¶µ†eжÜ1±Æ$ÕÅ&/燞þaÁJ…»¨¤Ô…[×t·›“îa% Šå6Ý˪üF‰@<¢¨ÛS§z{¥xŸÍÛµ ð¹Ä–Ž8Å›Cw/çs„›3t]Wµ9/Í~ Í]±k¼Êg'/B*”Ò\8©òð<2)‚bØ> endobj 1942 0 obj 1045 endobj 848 0 obj << /Type /Action /S /GoTo /D [1943 0 R /XYZ 72.0 720.0 null] >> endobj 1944 0 obj << /Type /Annot /Subtype /Link /Rect [ 187.72 515.237 250.77 524.117 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1798 0 R /H /I >> endobj 1946 0 obj << /Type /Annot /Subtype /Link /Rect [ 187.72 515.117 250.77 524.117 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1798 0 R /H /I >> endobj 1947 0 obj << /Length 1948 0 R /Filter /FlateDecode >> stream xœÅYYsÛ6~ׯÀø¡µ=‹“Gf’Åuw2i¨éƒåZ‚,¶©”ß"AÚétRçA¸öúv»`¾NÂðoª~¼€¢åvòÕ¬äQÄ\³$\D¸CÚ"3(V§ZZàG‚Áý9I&ý2¹¾ÍÂ@ð0Á]v%ñçÉUK¾ÚÁß]~[Fèÿ¢ÁÕ¡<ê9ß”ÔL¯ÁŠf¤¶b›ùÕ\õP+§•ÂNØŠQ÷û Çènòv>ùé@£ùº ZOìø4PÍ·èú˜Pzrƒæ¿N.æ=o~gÔzŽT²k{"àXcLÌ*룴MíÔFY`à>¢ƒ]¡Îûšà|vþþb:Ÿ½ýp1½úãâÓåÅg¤ÔdÄ@ºàAŸÁ‚R¯Kà ó4)²4FÅF¢e¸ÜDÉJרoc‰Â¢È¢Û}!Qñ´“¹SãYŒáÄÁήæünŸ,‹(M*šaÜÜÀÄÜ>?%EøXa Çw]æyÆò¯c»Ï-'••rZ8ýº—Y$ó.dUB¥¨Óшb› RÄ ”ÙhÐ˧1I¶P…H÷D1ì~›=eÒõV!XæÃ&1צzý=„A’StÐt³ìn¿•I‘£0Y¡/a¼¯eSY…ð—3ˆtfó@/‰‚¥G3C9=dA&w™ÌA5 Qe½N34ìX—8”A"`Ê,üçƒúP×#Di†^­ä:ÜÇ…3„€?Ø ¤D¢G4¬)QñÑ;?‚ !ž…àãå‡aLX(J Öñ>ߌ#@1u<w±Ç¹=x­ÑÐ'›Õ6¹}›„ãQÊ”ŽDéí_rY Ëõ|Çó€ §ž…ƒæ›(GQ#ã|T¤åu}¯RB]Ö§fcZÉÕÑ[O`‡À °Àbäø]Âü1Ú–I/Ñ#`&P¥ %fÏF2W¥x˜¾Öàa-7Ò§ü × „577± ¯Ò¿Ð½qÀ;mÆ–èk6‡­T} öÕuç2‹ÌëW2FÝ(PÅB[y8zÒ O½p+7á}”î3»µá*Ý-/×Í8jC¤³³ÙËû ô;ðœð„ºQˆÅªá ™soŒðÀöÄâr/èÂßNMB\'h’ÓL;éY­æ­IÙj­Z ™É°}$Z·'E{«FÐÆz¸üBö®ÚpuŸö «9 ‚j„´ ÀØšþ7h%iaqM@:jhPË„N£A=Î7àC8êR ÓgÒÀcv„º‘¯ Òc]¨›yšž…PÐê‰|Œò¤¡9là3lÑ«x7“¡f ¤/ˆyj¯%QXL¿þ9£µÃ“Émz/WgÍ DP?f–¨°rhÍT D«šÉD)mBE-ŒÜÆœ;®êD`ùL#í×â·áS=¾•õ0l©Ÿµ ;èÀû§ë¢_Î*/«qYÙšs›æT;÷6(õ¥otµ¸…ˆF—ñ tQªP*§gZ=nTÐóZ=-U0;»]¬»Ã%m¶J7›e…CCUÞ¨z8òŽt™C](ÜV[Æü­®Øb›)#oS±cc3\íhœZà,.d–Àq/ã§³–[Z>kÁ¸#ü²»àß §£Ä6xªwÝ™%Ðh·šW¯¯š¸êMP/´ûír¡ q=?ìŽýV{\ŽO-ßG¦FÊisLgŠ‘PÇ©Yйc6õ…d6ªP5s“´zRg­!´`Áº5¹²Ö¹ÞÊ(º•àfùj-£"~B¹,^ð$b®ï`ì¾/Ì“èâ1Üîâæ»ƒí[ÇÐM È\}÷[ƒæÞ˜Ê;ÇÇ1´KӺ뜖_gG1·/Hyú(Z¡W—çq1"‹Ø8Ò΃­w~›Í}ä·7•O`ëíïçïgŸÀ%ÕžE®Jä¹ÚG•+€Í—Ù'ÍGˆŠ‘••‹{ ¬²tgÂ}Øtïeû}Œ_’O"è"û/òÉÅ6˜¾5Ÿ\ÚEèù|b®m—uQͧšÁX'••)ïb\»¢ü?Ÿ«É?“ZŒÂ endstream endobj 1945 0 obj [ 1944 0 R 1946 0 R ] endobj 1943 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 1945 0 R /Contents 1947 0 R >> endobj 1948 0 obj 1777 endobj 869 0 obj << /Type /Action /S /GoTo /D [1949 0 R /XYZ 72.0 720.0 null] >> endobj 1950 0 obj << /Type /Annot /Subtype /Link /Rect [ 199.72 439.676 262.77 448.556 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1798 0 R /H /I >> endobj 1952 0 obj << /Type /Annot /Subtype /Link /Rect [ 199.72 439.556 262.77 448.556 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1798 0 R /H /I >> endobj 1953 0 obj << /Length 1954 0 R /Filter /FlateDecode >> stream xœÅ]oã¸ñÝ¿‚؇vsØðø%J<`M{{‡[ì&hQ$A¡Ør¬V–¼’¼ÙüûEêÃE9/[çÁ3´æ{83¤òeE¿Ký*†ÖûÕ»FQÈ—v)ˆ Ì´GP¦Ÿ¬…àË<Àýs•¯úmu÷?n‚ç³kˆoVŸòõ/ä»ËjÀ)û¿hðé4 ! ñ(6 57k°béŸ2ë6ûm¸Ð(g¾g•"½NÄí«î÷NÐÓ꯷« %èvÛ'm¨ )ÁSúÃÐíݽ¥L\< ÛßWn'ÑüÎ^›RËîìáˆB`#B=1« nh26}Œ÷‰1Êá!¦0‘~>2×o>|¾½üüáoÿüË 2´å+OKLiï ÇÂG€®ó*)kTYR¡b‹6q£4¯ 7ðc\%¾²·f„3ÅD-Æ0þõ˜¯ë´È[šyI…)Rë±›—¼Ž¿µ„Ê!Œ’B­4Ô|F–Gbú`Ú˜{Y&ë¢ÜTcWIë?ý7yA­6 ËHFœbêbÖÆ\b<¸CB\×eúx¬“j^ŽrÐyäpB¦Ï³£G‡ç^%C0‡-_/qZz¤(‡f>)ʡ՗cR¾Ìg{!‚; i÷‹'w]†¼ÿ-oÊ9–ì“ ¥»*ŸŽû$¯+çô“@9†¤ ‹ažNŠ¥.’+t?rô¶‚ÌŸÞuèËþ±ÈZ¬(O×Óu‹ß|ú£“o‡2©*¨íJ™è° 8·kõ.iÁji'aÛBq÷¤®R=ó´ÒlÆ{\%gìO¨)‹0 uÍ ]´ã OýJ=öÇLQ,ˆ$$ˆfw¾;rÂ+”KtïX t£½M“Љæk‰`XAÎÈ\ë×Ì*Ã$Á V„q©ß|F9¦ *¥®zä´|Bã2ÜðñÛ Ã[gó„©×dx(,†qÝH¡ì;Ë£Ûè ™?Ü?6@ c¿¢CÙ"š»CŠÏ œp邉ƒ $DFÂQÀÝN˜Ð\¡† J×XRd•œróƲÅCº`l¨K W‘ŒØ¹U…ºÈ®:Ûä´Œ…8dº³0戊Çÿ$ëz^®"8ˈ`¡ƒ F·»´BÏi–¡M² —ÒEÜdäãö‡ËVæx¹ÿq"±~aÖ¥¿$ÕºLÃ)Ó5`sNF„fæ­Í´«54 ¤:$k½G6èÑ;øÁ¨¯(Ñ}\:„x[+ã‘yû (–ªy\8ˆ3N'>zô¼K×»6x•ŽÞlÀNü0L%…ÝZN·»¤ÔýòºtnÓ¯ü¿T-Ü´ô2!x1S@³b¦€´¥Ûbf¢‡`u8(lá$C,\ϸ…¯sÛ-TºE<³¥äÐÎlQ›Ú¼ÐŸ ú¨[ñëŽ@`Yç¼hJzç.G¤p*¤§"F±‹‹6¾ëq=Gvˆ Š$ÔÁ•Câ9Jäåðî,-”€‚ ‡Ù(.-–º¦i<ô¯ö “ð€„Z¨à(1åçï^Ly‰Ê4Ûh¤ÌôÀ}LR Ý( vÞ¦ mÂCŠ{éM¡ï°uœ÷Èã@Éc• ü÷¼KÏ“¬sä4ÌϧJTÇÃ!K [¨…°wíyCÃq–õp—ŠÝRšw '· –”C¡ $uÈ÷›``òÐâNüu¯I{ÆÑp])ß¼;CK&¢þêd*éŒ}ȉæ `$ƒCï´ÞqÙZd{ÓàºÈŽûÞ6}h«Î1GÐGA`kãD™…Ê* +z¨¦8r Ó)!Œ09 $í™” ±Å¬õô¤=YÜ–ƒxRF©H˜s’CårƤþÕú0#,ƒÁ€—[ÊY¨‰í\èUÆ”³Se7YÐs%Ø&¨p°ó–3J}¤¸—n·#íÇ‚IK»|ÓŽôð*"—ÏÎØ‚y9œ¥…à`²‚檘‹ÇÒ>Š}¬¹Éù[  °dº¹xø3FùH{Ù6_N™ä Õ/e(x€E¡ƒ/_ r©„ê ó°W“ó\BŽ ̤ïpìâ¶&ÔGß«`êZ«Ûn+•AM¥2ð}Ÿ‘ýb“÷ýB£îñës»O ²-Že½{wŽWôè=„rÅV-¥¨>êó4ªß$θL›ƒ ãyÝ»ÐEÊhÙ&çõTúÔ éI¯s&í@3Ð7Œ{µi6Ö©6Ó}2,%x‹ —:Þ}¥ˆô•^Ñ÷4Twz&\V-4'î%îÄ7;ÊjÕAƒël³`î³ lîšZìäzÛ²ìAsÊn1³‘¬ˆ$KÖp¢u$ ãfÖj¶~¤°¾ Ϫ¢ÇšKð5³¯=%‹G˜Áþ€sˆô¿’ùh±•/Ú2b`[F ²M·õ®G÷I½+Lû5 þ‹8ÍA÷”Ô!|¡ª@¯j xà ¸ØTþ%7ê3£Œ@º\±Xùyúèú”IäiöjM µpªéc ÐñÉ)©IË€µlû‘ÁL?2pp0xsrð0ÖÄ7HÜ%ÁD©…Ò@|´½ôÓ†ïºÌŠ}Ûe¶–ù@X¸0¸=ø¶‘£fˆñØßoÚêqÆí«€žCF+.Ãå÷x¯ÿgÀ÷žŠæ ›1e©îmuCwÍuÛ¥ñºËâNöqš=Œ_ækn™§Üýü´-‹½¦> endobj 1954 0 obj 2275 endobj 861 0 obj << /Type /Action /S /GoTo /D [1955 0 R /XYZ 72.0 720.0 null] >> endobj 1956 0 obj << /Type /Annot /Subtype /Link /Rect [ 199.72 439.676 262.77 448.556 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1798 0 R /H /I >> endobj 1958 0 obj << /Type /Annot /Subtype /Link /Rect [ 199.72 439.556 262.77 448.556 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1798 0 R /H /I >> endobj 1959 0 obj << /Length 1960 0 R /Filter /FlateDecode >> stream xœÅY[oÛ6~÷¯ ò°%EÃñ&JÐbÙzA‡¢[·Ãƒb˱6Yv%¹IþýI]l‰¢ èÒRúÎçª_&øw®~ü¡ùzò¥Ú£ÈgˆËjË“ˆ Ì<´Fí¡T½µG°š‚ó+ôÇ$›ôvr}ˆà~Bºì4øjr¹'_=!ß\þ¾œ²ÿEƒËÃ(øÌÇØh47{°c©Giå¶ê×p5¤QÎü*EZˆÝ)•ºßN8Aw“Ÿ§“Þxˆ4]¶Ië+ %8`¡úchºF×§”ɳ4ýuòzÚ‹æ7öZ/JvcGBèY:¸~e”±éC´ŽQ7ˆ±é©÷øôû«‹éëó¯ùíã«+d° ‚òó@½ÎÃ>vƘß}Ú.¢2.P¹ŠÑ×(ݹY¢ø!)Ê$»Cy<ßä‹×ø Å$$ÀSžovÙ¼L6Yv– ±GA7ŸVκzÌÊ衆a”xØ!!¼’†ô_Çè@ô_ÜiKÏ+‹º^’6Öµ" FGê[$”Ñm*ψ‚¾û'~DALÈ>**Ë<¹ÝAÜ¥qbÁ9äè#Ö}ß$İ k<2<‹¢¯çÛ(ɇ¥bÑÌ!E‹V÷«8àO3D‹!]ÑmT8¤„6C^¼Dã…rŽe'Å«qùÝnge¢l>Ê¢0ØçùéÚ+M”Ú0è rtZ@fwÏ›åãúv“Ö«M~¸ŸÌëõÕåûšŒ¶y\P(êxüäyÔ…G÷«d¾ª“¿PÙ?˜ðþ’SI¡zù§©Š£š/ "BfîÑå*ÛÕ}ôX4 3§hÒ§J¿ØÂšÄ®mÒ\\šåÒLWšŽ#°­^ä›{Ü,ÞeV)K(øåóféHjîÛ\„!$¦Å#XÀÕÞnäÏ7pßK²Ö쨡Tû²„¦©C^ÚÃTî9P-´û±+âŠÒ'H?[Õ[gÕBÍцr$kÀp ®º¾'-º1œ©QÊÁá º0Iq¨¾40ióËèÜÀIèÂךäqG“þ5I¨Væsfa䜄pAq%Z71CΣ:Œ·qâÚ[Pk³ƒt°dPt=¥MdfpHwÛmšh~fÜ6CGiÚÒM¨›-`†t~8À0Aßïëâ.°Œ8Á¸‘ÿ®UÅd{etÄlñü5™T³D††žÍe㉮²ÂÁ¡õZëÀ¨¡ôìZ/ô 7ä|“îÖ­mêFXcŽà CO€. ©ÑWf¬šZJ£õ>÷iU³ãL [pqUäÕfeЦM7PT[í5}Ü5éÈœ0Ä\À -¨°è3zÞ™ð]øZÖ®áKLBUwUÃúœœw#QP\Ë6íKQU÷2d’ëìñçö©|=›£ŽÈÝÐÅàIQƒ„Þ#4 ¹…×XæyÌ…n4q}ÛRhÙB$¥ ¿2 [©n‰fêðø–s%ê+Šêíì´s“Ÿ™«ì“ 4`ó¶æþú!ZoSÇgNåAhM\Š ^}i‡bšÂÍ ]ë‘ê\•¢tF-¯£$½é~šVÜ rCÕßË|³VÈmºyŒã›>Öƒ$Àꋺ~aðÉâQ›tüËÁ¿Œ…^Wz§ ­~²$YÐLtÐ/^B@f§'ŸÓh‘¬“ü¼³$ƒßTýþTl¾&q‰7ùÝÉìÌÊ“ËÏYçkýžKl‰`À¢Æ²:¿Wªêˆý¥?'žü¹Ë“«R’Œ0Ýû›ªÀW,ßFwQö[¹úCηrÕ)„Nî Ç#<t£Óó„-K¬¬ÂnPš/Õû¯IÒõý9’ 9}üdH>˜×Gž )†¼7t2ôÿS^Nþ •&ì endstream endobj 1957 0 obj [ 1956 0 R 1958 0 R ] endobj 1955 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 1957 0 R /Contents 1959 0 R >> endobj 1960 0 obj 1868 endobj 864 0 obj << /Type /Action /S /GoTo /D [1961 0 R /XYZ 72.0 720.0 null] >> endobj 1962 0 obj << /Type /Annot /Subtype /Link /Rect [ 187.72 508.037 250.77 516.917 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1798 0 R /H /I >> endobj 1964 0 obj << /Type /Annot /Subtype /Link /Rect [ 187.72 507.917 250.77 516.917 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1798 0 R /H /I >> endobj 1965 0 obj << /Length 1966 0 R /Filter /FlateDecode >> stream xœÅXmoÛ6þî_AäÃ3Ç7ñe@‡¥‹[lè:¤16 I>(6íh“¥T’›øßï(É–,QJºóAŇw÷Üñî˜OŠüMÝC†›É§zŽ"Å—õT ˜hƒêq€b·ª5`û<ªE0¸GL’ Aï&×·ðq‰'¤»] ¾š\¶ä»/ä«ËokÀ)û_4¸<ö‚b w|S¢y53ÕFîS\ÓV?«]«a¥\õTŠ4:?)µº_O8AëÉ›ùä»·¢ÍWMÐ*¤kfÜ¡ù]ŸR¦ÏnÑü—ÉlÞóæWf­çH'û`G« !ôȬҹª6ª²éC¸±•Q„FÌ`"·^W€‹ÙûÙ|6ý8ûé·W¨Â”+¬˜ÌX{ØêÄ]ØØev‘fË­²tƒB´ ‹ð.Ì-‚Glñ^åÑ_PL eµãÛm²(¢4Ùc†©’T£hMÕÕ.)§=Ðx„Q"°!0ro@ùëØ¬…gå²´tZ[ÚeIz7ÿæo»C{…@ŽFŒø9`Ì+hD÷Éx¼·™"}˜1!Šø«£`P§^c^ÿ€ž÷>å " U;ÏÖÛMŠ…ÉýÆ[›«ì¢!°’6¦O}ï°Q"=st†¦L`Nó"‹’õ·­‰Ýæ.›÷4ë~‹ÍÌÕåûæÅ>=d6Ïá 4s™us`!Hif‹{Û¼$-ZòVÍ8l!Ü¡l‹Šòã-£d˜·’©:,t]Ý'/÷ÖXs¡!„'lýêaÎÑjÇpCì¸pF 62±àáì•߇‚Yö4håÖA(½ûË.Ša¹Jc¥­Ly¶Áh~åè1Šc´´«p¨H‘‹›Ïî “Wõ‡é^æ+üüdPK„€Ü-X¼/l¾È¢‡vþöÖ,I0¸ˆPÊøè’kîB ‚t±^”ÃDQ¾ÚÕqZÍÕ¡_½Ôǧz9>>ÕÜXŽTXj0‘C”ö•:&X­™Ï²F~YýºNdmëƒ]D«È.›©»ÝK áša®£%ç]FÓ› r Ûˆ^Ä© ‡h ´Óg“ Å:¨=1y»Çx¼÷ûÈÎ]hÿ«h†¼„9ƒBè ’6{ 7qSD|çp„)”!Éë|ssšC0/ t½Š²¼˜º”|‹®ã°ÛMÅ·Ý®Ãíæš­£ÝPýû¾Œ@>ÄéÎÚ[60CØ2€Ñõë -o!óxÅ+:(>²ñ²Ô?GIßœyКwÐPÈo€“?·Yt‚NÞ…ë*$ŒÖÕèÇ<ýÙ§ÙúäæÌ»§éÓ{܈õ˜0×·» ]º­Çq‹Úeö¿øXða’Ÿó±]Š¿ØÇ"è2ú%>ÒÃØ‡Ÿß{V*8>𠣊¢ªûúhiÑlµÂó±|p¸•)b4×uñkº„t±]A‚œmBØ«®~Ûdi³¸,)ûDñ‚<n,pï0¤¾vž—ªA¶¾Ûª§)4Š0ZßíÒä%%ÑØh©”2Ó–U6„ûfTl+Ç„Kh—¹RU°ïKªÎÒ”-`–Õ½©iõ叨=Øæ-ÿ’j9˜v QÞZ­AÁ¸*cõçÖÎ#õXj,áNA•ÍGË3l ë×4I‹æ%lÓîÍqó\í’¼Ä n JˆA…G©ç‹!Ô…|ËsmW¬ú§R ÑÁºƒàZ§¼ ë®Op—Ï¡v:£Ë|ä:èv_5ì>(€@ÖÐNõ%Ž·SœŽ‚Ñ2uÙ)ujÛ,FàMšÆœV6³¸õ ËÉ?[p׊ endstream endobj 1963 0 obj [ 1962 0 R 1964 0 R ] endobj 1961 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 1963 0 R /Contents 1965 0 R >> endobj 1966 0 obj 1387 endobj 888 0 obj << /Type /Action /S /GoTo /D [1967 0 R /XYZ 72.0 720.0 null] >> endobj 1968 0 obj << /Type /Action /S /GoTo /D [1797 0 R /XYZ 72.0 185.621 null] >> endobj 1969 0 obj << /Type /Annot /Subtype /Link /Rect [ 228.72 553.412 285.66 562.292 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1968 0 R /H /I >> endobj 1971 0 obj << /Type /Annot /Subtype /Link /Rect [ 228.72 553.292 285.66 562.292 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1968 0 R /H /I >> endobj 1972 0 obj << /Type /Annot /Subtype /Link /Rect [ 223.72 529.412 286.77 538.292 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1798 0 R /H /I >> endobj 1973 0 obj << /Type /Annot /Subtype /Link /Rect [ 223.72 529.292 286.77 538.292 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1798 0 R /H /I >> endobj 1974 0 obj << /Length 1975 0 R /Filter /FlateDecode >> stream xœÅXms›Fþ®_±Óδr&Ð{;д™‘må¥ãرE›ÌDù€ÑÙR‹@”DÓô¿w°8pÒÌ$Òîm÷Ù}övWèn@à×ÈÒe¬wåÉ€‹rÉ@-“Ù°‚rlC˜Ÿj Ø~„âðz <¼}‡›s (ða@Õí„§ƒË~¾C¾9~ÓNÙw±àò~$“æAlvÒ¼XÕBQ¾–´•ÏBk1,Œ+žF‘Ú&¢'¥4÷Û¸{ƒ_žÚ@ x7õ¥•¹ %¦ÃÜüÃÀ[ÁÛ!åäèx¿&^+šß˜µV sìÊëBè=·vÁ•¥S…OçþJNih°`®I„Ÿw É›ÉÉÞÄ8¹xùr|~ …p%BmfJŠÈBÒ¶ðŒ1y( ú`òQ›LÁôò ‚xµò£9|X,ƒ$*Û$Q Q ïýp£RsïŠÔ¸bQ“¸u‹B÷3©dÀÓMdË8ÚËv³'\Ó¦ŽëJZ²7ÝF™ÿq/èj@)‘¦Ã*“¼ti÷9`Á±4'Uá»Q:}HœÔÉÀÞ4åÀê@zêã:QiÚà å Z´ŸþVÛHNts?ó¯ýTu‚q=q¿=‡cD¹ƒ‰bb9å'·›•вò›óçî¢t›œC ,½\º®Å>’ZùB-¦G•Ù¢%a SæNR¦E\ø \F¹)jáBh´@¶ð3L–\OÉÃ.™ÒÌÏTÎL™N–aXæ”&¥ôT9ÎØapõ$µÄÆ}ÑG€_ÿ¥‚¬‡$¬}ÕXLjÔ˜à-–iÁÁ\Ýø›0ƒ,FêTAÄ7ð¨Ü0ö˜Ì‡/$£ŽéæuGrZ@ª4H–ë¬/¤yéµl“I‹Föµ·()በg˜›WMò˜V“}¥¬z ƒ°Mnq$W´Q?óò3ËíÓò¸¶¤¸mÕtåoëÉuÿ¦ÛÕub±Ö;[›W¯Å‰^S–,£ÛƒZš³mcü$wá”í¾J<ŸË[Ü´PU´­'¥ŤN§úðÚOÓ›$^56ëáÝF%ÛÇõ¼ð£—!.16ëu¸Tóz¥§ø2a jÊ…Ô¸÷`¢riõÉ×&Tñ,¦e’¤ âzŒ9dhØÇÖz_ýÿH4×Å:!\Ç•ö>_üÕ:¬«½®Asì/*ql«Ù f‡ ~…1´)T Þc¬ÃøfË•‚`á'³!'³£Ç»­rAâÂìè‡ÙQÛkn“ìªÕÝ;Žùn¦:¢û‰ÖT·‹U<þz±D›ü ÈSs«ªà?þzr†)e¼º˜zÏ®&8ÕCãtìÇÓ üc9䘋ӟ´‘-ÚÅ)"Ö÷lÑh©_ÅÓHƒÎXú$I°,¿8Áäêêâj௠F5x¢B?oà‡¸5ߢ½Ë4K5h¼ëBìÐ~ ql’DÍM´õE!µìž^)¬~I–ê(‘½!#x;>¾¸òÞ¡’ÝO¬^¼6ÎPg¶ÓC±æ¸ÛÃÑ©ºÞÜæé“m× žÃ Fg¡Âµ.lòEtá‹‚I°J‡ðÖñÙ°uÑGŸfÃW'ø|:žzÆË‰÷üâöWÞ8|ëš =ФF~-?ilá¤Û̺M´IÕÜð“[MBÙû aÛz@Øï/Ã<ùº4ñE´¡“=±˜Æ›$Àô› w) ?7 5еQU{ªÁhòæ’?}qq¦ijaÝÚ ¾è·E°ßvˆhJü<‰×…K[»ë¢PÛf׳ոïãrðÑq›9 endstream endobj 1970 0 obj [ 1969 0 R 1971 0 R 1972 0 R 1973 0 R ] endobj 1967 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 1970 0 R /Contents 1974 0 R >> endobj 1975 0 obj 1338 endobj 882 0 obj << /Type /Action /S /GoTo /D [1976 0 R /XYZ 72.0 720.0 null] >> endobj 1977 0 obj << /Type /Annot /Subtype /Link /Rect [ 241.139 560.759 298.498 569.639 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1968 0 R /H /I >> endobj 1979 0 obj << /Type /Annot /Subtype /Link /Rect [ 241.139 560.639 298.498 569.639 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1968 0 R /H /I >> endobj 1980 0 obj << /Type /Annot /Subtype /Link /Rect [ 235.72 527.208 298.77 536.088 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1798 0 R /H /I >> endobj 1981 0 obj << /Type /Annot /Subtype /Link /Rect [ 235.72 527.088 298.77 536.088 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1798 0 R /H /I >> endobj 1982 0 obj << /Type /Action /S /GoTo /D [1797 0 R /XYZ 72.0 386.781 null] >> endobj 1983 0 obj << /Type /Annot /Subtype /Link /Rect [ 235.72 484.106 309.6 492.986 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1982 0 R /H /I >> endobj 1984 0 obj << /Type /Annot /Subtype /Link /Rect [ 235.72 483.986 309.6 492.986 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1982 0 R /H /I >> endobj 1985 0 obj << /Length 1986 0 R /Filter /FlateDecode >> stream xœÅ]Û¸ñÝ¿‚Oíæ°ËŠÔ'S´@®MWWl³í¡¸ÜƒlÓkµ²äHòmößwÈá—-ZÙ¼¤¹v†â|rf8CZ1’ÀwêO)8ÙVŸÌ#%'ia–ò‚°ŒòœˆsÒª]À-p{òóª[%ä‡Õ/¿ÂÇ-I€ài•\²ÓÄV÷|õ%ùæòC RÆÿ/ÜŸŸBÉKzq6š:Å5XAFêSkÜfþ"WQ9ü{U©Äë”ÄbÔývÂò¸úþaõ‡w9a yØù -!KhÅ…úÇÉÃürÃRþêWòð·ÕÛ‡Ùi~c¯ÍRÉvö¤„ÁÁVI’°3³ôá–Æ(´é§ú Ѩˆ²ŠpA“"Wû+$¸ÿçÛü› ‰ÛXeTd ŽgÙœâ#çåÅ~±´Ÿ¼ý,7§I’º#îß“O'9<²%ƒœNCG¦½$ÓéØÊ‘Ôð?i›q¢Öˆ2bDÆh"P „d'‡fCÞºÍÔô¥½î·BМUB”ÌøíÃs7ÕŸ-¡ˆeINÓ*M’”§Æ0ýoæºÈNmòÅFÆb;‰U¸Ðñäë;ùù8Èq lŸ™ÀY“÷»ÿÊç¡<çªm=Õëz”W…Áæ¯3.MbÚM§vº›žr¼.«Œ΂¬èíÚz:^€¯=­,zZ»F¶Û»’ôº=Y=¨?ý™ ;¾Ý,MišBd…¡~3<ž²›FwÿªÛ“W ¢;84/)S9–ñb9ÐfU†åY„üMG^‘;È\An,i1#…¼d©H’2/#<ÆO­gòM8/h&ÀCŒE¸yVÓ¾ž<6HÅX;Ë­Õöª†9‹™CŸöÍfïÑf<ÓWn&¹ Äö¡P] ½ÀËj¡œª¼sfÂÇ›c.X·ÏDŽÓóÇW&FÈ(} °Hh Ašd©ˆ'uü`gdoÈÂq¦´ä*@9_HúõÀ5‹ÇX–À&ãe„ %{pôSÓ¶d+wµ2\«n•ßT “~G¾3î¬Ìç\¨‹DÎËCÔ5sš7äû¾o%ÏÓ¾;­v¨– Ž«ÅZ0jÇ"ŒúñýUUÒD,‘~Án¨xV¨zwµÇÍŸ‘¾42攺L%“Œ5 àÃõðHKZ«¤`V*:¼çÁç¯ëÓÔÿ‘Fò‹çPtEŽq¦‰)¤d™SFnާá¨NÑ-@\9xÚc®#V›rëW¯›ú²¹ê¤”¥4KX­Ô\¹¿¼‡Jt= 2 f È˘eæ} åáØÖ¦Ô!ÒIªËr ú”Ƙ#‹ÄAåêjRâšN‹I«ÂÞ7ãÑ€XFƒ 5$ð`(ÐÇihºÇ‘ôý®)äö´‘£#‘ÚôãdEì P·m¿©'àS¿ê×ÊhΡ‰¿™¤òQE—P%«+ÖïÇBäêQó‚C çpZÐÈÏå/5$8-X&DÍœ؋‡°Æß{¼é6}÷›ìÙm-1®Ö†éÌ>8ÁµÍÇsÇAÕ:—mN‹èóG:SíÇXÂäƒD‘°Ì—øÆhIn°h:•DX§´Gu~¿îõ<}K!ò¹ä/¸¼J 5K°4Bê%‡Z)rˆ½ç@Yt°_09‡¦˜ÇMY–ìNw1òì\5ŸÁ0ï‡6> {‚t“©Ç4]·’Ú%[ ´ÕÔ îdbŠbáÝiØaÏsQ•y>Wqñn«ªJ+ØŸ¿6¥mÁΛ ›ú˜ÇÒâœé-«(·M¶p¸R¶±l¬‡-ŒµÁšq†Mi@Ä–Zü7õèßU)|jÆ`{íA5.{¬ „aË Œ¬:7R¯KA‹èD¤ö l¥½ãpâ)øZ‡<ðBw¨m¸³WünÁQ>õ‹0Ã4!GðXÌÎ"9·³Ù‚ʺŸ€Qh¯ÝPønteFYQªW˜ø‹RB*šž½&½n´/84ï܎Ðw«´ëµ]¯Íß±yìÜWà%åpkÐÝÐ XÝ­›ÉÒêb €" —·ò(»-Öl…ŸŽvH ôçÉ…Êç¾ñ¢Ñ§1íQ}µo¶ý j AÇ€Kœ3ôƒ~½Ûµ=„Þ×Åg,ùZñÓ5Á˜²¡¬8K-7…’/` ÜWmöÚÌná©™ö«=Ü˸à¢Qt £gAUZåiQìaaðäK„ÔËþy/»h’¦0f¤LTÀñë4ÉØá­—mÇ6Ävæýدà?F½=J¸˜¶±ð.å\¢;ým°Kw¡"h“e¾É]Ÿˆê€¢·þDláQ–Ñ,…©»¨bJ.6^L,‘ÞzéÖ£FñÀ£Æ¬»_ÄÿÚÏŸ´Û"†AöB;ýÜ£~ú§Ùxù™sF¡wjP 7bf[UB)­Ü1!â ñ¶ÅE¬AvÈ)‰è(=ܯ§º;Ÿº•wºƒBØ4P†£úyÄaM÷BQ·á¾!`›Úó4½°‡îBkãš=ÄÿÉœ8"Ê9·³¤¡ñÛ W‘íΡõ½Cú`‡îâ­@é×'¸Â×ê×%»¢ƒfŒ+êwi‡ºr~ý)=/ æPÚÊÔt•ãfhŽÓÒó ¶*‡Œ)ÆJãMó3˜R-+üU…0¶ÿÛ7eÄü;·[ZøH@¿ËRå^ü†Ï+ƒxµ¼ˆ°¹ušØFìP{µ×Þ¶º‹š1L‡¿!r6i·‘|å…bXhRõÛ­mOj Å®W|ó|‘©‹ jÝ\Æ—ŸÉaæ( KMЬŒÐ{Üœ…¨¹½ÇÀ„ÞÑì—“²‚–…À'™¹2/zÝUS÷¯Fè^{ÐÞkˆá½fŽåù°îÛËbG[$âB :ËŠ¦Þñ•Xžº`âMéõõâo›EIÕ£¨~)ŸK|q²¤PTøDn¢f Q•¢,’2˜%R]œ¯+œCéâ ¢ˆpxÙC=¯€…ºÇyáátÀR}¦Î¬`© ËñWÿ9¯¥vBý·@êd›ªÜn^¯Zßgö›{˜1ý>ÿ,ƒ¸~ç ¾›[AþFÜömˆõþŒì‹#bhÏC†õeK¡Ž&ªs+Ï"X¿Fó7ÂM8žÔ¬zÝá¸z¿úó¶J endstream endobj 1978 0 obj [ 1977 0 R 1979 0 R 1980 0 R 1981 0 R 1983 0 R 1984 0 R ] endobj 1976 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 1978 0 R /Contents 1985 0 R >> endobj 1986 0 obj 2497 endobj 920 0 obj << /Type /Action /S /GoTo /D [1987 0 R /XYZ 72.0 720.0 null] >> endobj 1988 0 obj << /Type /Annot /Subtype /Link /Rect [ 241.139 560.831 298.498 569.711 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1968 0 R /H /I >> endobj 1990 0 obj << /Type /Annot /Subtype /Link /Rect [ 241.139 560.711 298.498 569.711 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1968 0 R /H /I >> endobj 1991 0 obj << /Type /Annot /Subtype /Link /Rect [ 235.72 527.304 298.77 536.184 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1798 0 R /H /I >> endobj 1992 0 obj << /Type /Annot /Subtype /Link /Rect [ 235.72 527.184 298.77 536.184 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1798 0 R /H /I >> endobj 1993 0 obj << /Length 1994 0 R /Filter /FlateDecode >> stream xœÅZ[sÛ¸~ׯÀø¡36  HîtwêNœŽ·YwkÓéØž-SRtH*Žú°¿½< A‘ ìngRçA ÏíùAÊç…O(ü;UaÌȪX|Ö{> áRo’øÂc)ˆ¦’«·ë(øÀ—€Ø¿/¶ Jþ²¸¹ƒ‡„ÃÓ‚ŽÅµÌ׋«~õ„~sýC ¸Ïþ/\žBÈBot6-7Ç=ØAAêQ®aÓŸ(I4?g¢Æ&jE›ûí”SòqñçåâoâS²\›  £O½ˆÅê‘eAn^ù<8¾#ËçËÉi~cÔ&©t÷þpâÃÁF”RÿÀ­öpCíút™):eAD„Å•z?B†Ÿß_\.O¯~9ÿ‚Œýë>hõ%håRNo Ç ÌÅ@~®²mS“„4Éý.O*R¥eÕrM>ïÒjëz—7µ×9Z¾Gc R%J}»Û®š¬Üv<óXÉØ ü(ŽC_cu½ß6É׎1¶(óiàñ Y¾VGÚ¿‘ß‘°¼ù¨¼=mÃP›äΟŽ-i3iÂЊ>M¿>lõ‰#,`6}¿û”îJYdó¿Éš<­gUqfƒÂ¡…së²*’Æ¡&´zäPÚœ©³;|ÔóJ„os¾nª4)æµü·Á ¬Áð@R%u:«' Ö“ùþò|æøœ{²Ž¡@¾³êã®HÛlÞ>I¾3@ZL ( >ˆàܽ“¢åbÊ}¶%ÇäjAL^uœr ïsà ƒp*¢þœ/°ƒ1é‰8RàM…IÍ&iÌ *Èmê÷’í×WïÌ‹`¿|Úd«Yfõ¹éªIjË¡ÒfW ”$“ú#›¡·¯Kà>ß“´xlö·Çº“:m<÷ÙÆÔ“J½¤±=í‡:a;#޳ä^ÈTl2æPHÊû2ÎC C#Xhã‘åp~Êòœ<¤ëD¹È6›”|Q1®ZÕkýà´ÓùÚó™ç‡Tú­†Z±™2‘<«Û^ %Û~¬IY‘ù’Ý—…ª÷†6 ./ÞÍC$B+Á°”*H-:ÏàEDªq@ƵÊÛ˜pM€8qÁ@½Xhî©(' ”µ‰(‡ÿ‚9ø^ÀüÐÀ)ÜM¸ 4 uu}“Ö«*{l\]àã>FÉõIè‹44) uDwÐK}›Ð+ˆÔî50¾¥½`˜¥j”ØFÕú~oáÑ-Z‘}ƒV ǰI¡t„2Žâ0°xóâÉG‚9'%ý  EÒ[xŸŽ¿WБ˜΀zÀPï‹û2ÏVfG; c²Ù++C%µ¥ùÄldÇêµT1Ãdl1õÙ±‚ÉÈÅoLè!Ã¥ŽíÚìà<…´¥ã›‡KŒ\`ZP‡†ph Ns¾¯¸Ú›"F!n”[T+ǽMfÔ—EÇseGàöãXPfá6ô`ár“ lO Ùˆ~G&ãÕzê“¥3/R7auÉUÊ#ã¬7Ešlþtã;®^× Üo’êákñkóhx€»:}ðÌBÂÙ¸#ëÚ‰pÖµÐÆêàüœ€¾Šô;‡¸Ä6n´±…äì1ø1ó‡éC iQîlâ>u±3“á[ô “oʈõ4òü>)p1H Üè“—º¤µ´c&—˜7Æ™EùsA¢®Xvc‡ÖX¾Y<¨ÂN¹Ešk<‚Ñ$ qW]§*EuYÂ.Iqõë™ÝbOiè> õÚ¾Y`䔕%TØxˆøõÃÉÖDÇo['ˆ*í öüÕT¨ññ8’‘þ)ðükR<º~ØPf@aƒy†BgûïLÍ<äó‡Ü¤ *{¸#7묪›ÓmR¤°ÈC§E’åw㟑@GÁv¨ƒØþ¾[WeŠÊ}šZ%Á¿DÒÓ&ànþhÌî¬òà\ò¾Ãy‰üþöÕÑÅ›#rôöoïÏ/Ï~:òú—÷š:ÿéìâÝÑíñí±EL<‡.ÞN Ñ2iEŒ¼°ãÃò ù'Y‘Uä] 1®sEü©.¿diã•ÕÇar|*ŒË:]«÷¯›$o¥Õ-q(Í", '`PÙÚC–UÙÔŸö„4HH³‹Æ§"¹Ì>eMÂþZíêÕ&ýB>ib(Í",@ÿëÐð5ÉÆhæÁ‘ÎŒ§“6 þ©ÿD¥Rm6Š» &‰ÈE~øžG6åÜÖÿ{J1Ft…ÄÄ¡5Éà?\-þ×r ± endstream endobj 1989 0 obj [ 1988 0 R 1990 0 R 1991 0 R 1992 0 R ] endobj 1987 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 1989 0 R /Contents 1993 0 R >> endobj 1994 0 obj 2165 endobj 909 0 obj << /Type /Action /S /GoTo /D [1995 0 R /XYZ 72.0 720.0 null] >> endobj 1996 0 obj << /Type /Annot /Subtype /Link /Rect [ 242.16 559.076 302.99 567.956 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1968 0 R /H /I >> endobj 1998 0 obj << /Type /Annot /Subtype /Link /Rect [ 242.16 558.956 302.99 567.956 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1968 0 R /H /I >> endobj 1999 0 obj << /Type /Annot /Subtype /Link /Rect [ 217.72 315.844 280.77 324.724 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1798 0 R /H /I >> endobj 2000 0 obj << /Type /Annot /Subtype /Link /Rect [ 217.72 315.724 280.77 324.724 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1798 0 R /H /I >> endobj 2001 0 obj << /Type /Annot /Subtype /Link /Rect [ 217.72 271.62 291.6 280.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1982 0 R /H /I >> endobj 2002 0 obj << /Type /Annot /Subtype /Link /Rect [ 217.72 271.5 291.6 280.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1982 0 R /H /I >> endobj 2003 0 obj << /Length 2004 0 R /Filter /FlateDecode >> stream xœÅYKÛ6¾ûWð”&AÌ’EJZ`S$E‹E‹ ‹öæ •i[­,9’¼›ý÷’z­5ÒÆ=¤»)Î|óâÌÈþ¼â„ÁÿÚ~èXô°úÜîq¢ T»*Â%!9–InOÑQðá±'®Š#?¯>~‚‡€á~ÅÎÅ9æ«÷#|û„}sü±ÿ‹ïGA MÏb㸿;^}”·nk?½TOzåüç¬RlЉáNiÕývàŒìVonVß¿ gäf;$­¶ŒœÑHÄöO›ùøœúÅ'róëêíÍ$šßØk“@ZìÞž€plÄãÌrÁÕ­QަߒƒñF!n1e*´ç#ÏðáíõÛŸnˆçéOFšreq=eùK}v>^:OÞ~1é©15IÈç“©È.»3iö†Ô§ã1Ï̆¤eQ7U’MM;4b€ä”Å „+/üÝ©H›¬,:žy_©˜†<ŠcÍ[_}x(šäKÇ#`œ…4–„ ÙÚâþν%‘“µÉMÚœä‚aBŸU¦nH§ gçªp%¶lcŠ&Ûf¦ªgµâÙ?æaO(Ì¢$Ïçq"LÃ%ˆSl“ÕMVtnCpè4áSl[•‡y u)†Æ0vUy:®oæ O†y)0ÅöÉ]VìæQÐÜYBQXdòì͇EÆhšÍƒ„ ˰r»­Íå€õÛ?ŸFOwlH*5ø?ˆ¹ç¾ªv§t=%Š ù#ÉOCv • <F4ÒÌ|ÝÔ‡tÍÉ Äm—™p^¸Ñ¤ÜöÎR>49æZÈD@ý9'æË̯¡"ÌË€ÑÌf¡Œ1Ä@Œ­÷û ˆ¬ØdiâÇ«´ÌO˜¬J?hÑeßDÁ¤&d0éð¸O&WäMYæ&)–¡ `lƒk7znÂõµh"¤ò–)ͧý‡š°ü^RVäPV†|x= ä¯%m;× 7õ IM!@ºðáWjÂvUœéò.̼2€Üa2†uÂt)jÌi(Ã8êßJ 8è„çŠe±.ÌÚç,oÌÎTËȨ ¡ŸÄ!6P Èžÿ„Tà P3Ž8ö„íBW¡¦QÄã( ƒ…¡Ÿð^ ®c(S`Ø‚ƒNx.•LPè*q¤ÃïD(î”íj¡ŒK‹° Iˆ@RÞþmJ˜`ÕÄH¡1”Ü쳚ÜgyN6f›@K´…Û¾ßÙÆf+üËöÁºÃ|ù„w„„2ɬ™BfÜ5ž¾ÌB‡)ÁÎN;¯è<ÿ¨Ú:Ž#‚ûåzÞ[PXŸ°[*¨”p‘à&Ϫ¸ù֯Ό §›Y‰Å$õѤnʘ7˜ÇÔÎ LqD”ÍŽÁóàó×É©)éù÷ ÖQ)á+ÖÖkËù‚¬a?&ϧêhƒØoئ£›ý*i§«agü4MNc1³>±¤±‚+ L¹Ÿ®áºÏ:%€ÀÇvÚ‰aêœ24/GZŽe5ÒÚÖ“~Q€IU–.H#» À—˜[aÖy >’$"ªÈóë¬>+_ êaj0ÔÃaÝìáFõ«º© ×tعiƒÑr›Í)5õ˜Ý ‹´¬›ôv a†+a´£É°7’bkÌÚXœY .Mª`„”:uû¥¿;Ú+æéù¬€l×LÃèõoжœB3 ŸLaîÑ!A«ú»~ fYÜ™"3E:¨èœåI÷¸jƆAo]ÐÆf×#‘h²„LN“ÅÊi“»·¡P4 %ãŠó¾ð5³Qò•¶[ùð:ÒU~å®dÝ/çpI¸U’K÷ ç+`†óî-lÊÜ£ô²J SHƇA[ïí~Ý^SG—Ò-­›i=ÕÞ@Ì™At¦×¶¬@8h%Ä&ý*±ß:§vr§ýž¯šžîên·îâáW>ƒ9ÿ%"‡ÚÅ$”t!Ú-u PK¬=výÖ&˜#:ºw§_:gzòv0£2Í©*ÌfPcž Ù™ÀײKª ¼uÎ;–ðuÁR>Ònz#méßmy¼ÏêîTÒ~晫m–Ì:¡0Â=rºÚ¥óõô>©Ï˜ÜØ6†£Ä4MüûtÛ»÷3]ï®Ý0æÓÖM¦ö‡¬mð£ïHR™×ýOI£_À,¢†ÎîÅ›b$r­ø]êuæZp@CòüÓª]8oxÊu<Ó?Iú'IGÔÙ®´o1¯ºµ}!îèh}›5½—+ŽRòу9šbãk¥Û8Ë¢çÚ›3w3˜Ï Æ#ŠþðfýÑÅþÚ”'¸ÉÄû œÔ{'±ß‰ø§ëm^Bh}Y^€çâRøfØß“1.Òá‚*¥‡ õbqE&¦¼o°Žn/‡_¸„ðd½·ÈÕˆÇ SCƒsËr€ñEãÊ•ôT_ ÏÙQµ’º†š½0Ê •ï°±.© 4Mc9#)/ Hlâìµû]ãݒλk¾4UBÚÂà.,ûQÂ5ŽÏûÕ¿T%™¡ endstream endobj 1997 0 obj [ 1996 0 R 1998 0 R 1999 0 R 2000 0 R 2001 0 R 2002 0 R ] endobj 1995 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 1997 0 R /Contents 2003 0 R >> endobj 2004 0 obj 2039 endobj 911 0 obj << /Type /Action /S /GoTo /D [2005 0 R /XYZ 72.0 720.0 null] >> endobj 2006 0 obj << /Type /Annot /Subtype /Link /Rect [ 241.139 536.832 298.498 545.712 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1968 0 R /H /I >> endobj 2008 0 obj << /Type /Annot /Subtype /Link /Rect [ 241.139 536.712 298.498 545.712 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1968 0 R /H /I >> endobj 2009 0 obj << /Type /Annot /Subtype /Link /Rect [ 235.72 490.687 298.77 499.567 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1798 0 R /H /I >> endobj 2010 0 obj << /Type /Annot /Subtype /Link /Rect [ 235.72 490.567 298.77 499.567 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1798 0 R /H /I >> endobj 2011 0 obj << /Type /Annot /Subtype /Link /Rect [ 235.675 468.542 309.465 477.422 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1982 0 R /H /I >> endobj 2012 0 obj << /Type /Annot /Subtype /Link /Rect [ 235.675 468.422 309.465 477.422 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1982 0 R /H /I >> endobj 2013 0 obj << /Type /Annot /Subtype /Link /Rect [ 411.625 468.422 441.625 477.422 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 882 0 R /H /I >> endobj 2014 0 obj << /Length 2015 0 R /Filter /FlateDecode >> stream xœÅÙrܸñ}¾åÚ¸¤- ‚ƒgªâ*%ë$ÞòîF¶²©ÔÎ>`f ‰‡“õâoOã Á‚ýâÈêѺ}@þ° ˆÀ¿¥ú•æ mv‹v¢”!žØ¥8A4Â,F;dá•j×`=¿Ì&пÕ‚ ¿/~û>n‚゜³ÓÄï7#ùê ùæòÇpÊþ/Üœz!e)>ó¦æf V #õ©´f³¿ WåÌïY¥ˆÓ‰øbÕýv º_üåvñǿňt{ç‚6U„”àŒåꇡÛúí‚FìòwtûãâõíěߨjG*ÙÃy8¢àØŒBOŽ¥›ÚC™3ý,vÒÊc†(C,Ç$‰ÕþÌüðËòæ_¯ßýªa/% §Dm$ªcé9  7lD'QýQ6H”%ê$êûR¶¨¾C}8Èæ ÷º§Ý#ŠI®$$†çObÓÔ=Á¼’Ç4Ëó”Z½ª:ñ©'Ì=’(‰qž&@Ã{ýõÏÙ‘³È³s[/õQÎÍÙíêbuñ²‘m‡z}@›3…h–xHEsßΞi.ç$«Ë€Æ| ê£,å§=èØu5+‘S¯Ù^>ʧ€P{M(:±­œwñs^ND|ÚÁ™e·ìžörÞ”Qæ3%z¹®·¡“Å^s*¢YIqäó3úó+d}>Ô)‡"Epëhj¨¯›ûÃNV]‹DµE¿ŠòàŽê1X)Î@NHʦq6É(Tùïœâ•4Üê¢)唨‚´Ôâ°àŒbJS¸ÝŒ…cϯńüºB—h I#G=i2!…ì@yÊÇ©‡Gû¡tL¾@ÆåàJ=Ü«îAtk¤b¬½4¬‰‘öïoÞ:D[šLJbóàТ=ÑWn:¹‰­ÇB»C3"Ζ2jÎÏŽ°ºØ×`‚u©UȠݸ»}÷¤R‹ÅM°h+»«9>ÈF:JaT׈®ö Ú;Q9Á¢ëšb}è¤wk ØàjMOvw¨6K ÜÈÓ]0ÓÌC‚:ñjŠþ6†¯S}\7ŠD¹?#z¯À”ìŸã”©:Î Dõú¿DÁ€OSEÈRŒn $ü­¼*0 ¿·ð²óý3‰r )ø¦É|êöeB FAª%Ž“4&„“ØÃà®å¶g¢4èáî[_›ysñG $è„ûTÃ=§Û‡io6‹ê ~¢þ´øç9ø„ðÜ#ãç7ogÕãPXæ)íÞKù¬œç8a>óº#Ÿ É]/ò®nã;3µrCWló@ùv­ïb'$¤y–ÇC¥Ó·ó™XÌ8ŽcòœðiQ÷Çà„äéöt|[´{´©·ò ªæ£DE½ð¼kShT¿ÏŸ&[h$›Ã{QÝ/×Eµ·38!°ò.l¸8É!Ëe$_Ê )¦D*ÔmÉsÈOrsè@ûP§©†TSîatKÖõæ-~¾ÇâÐc±<†°ég®d»iŠ}°,({AŸ”2®$[Þɽ„™hkŠ)eÎTÕV05Í.FP&§Ó(öx&2³íHþ±€+TÄVQ¦ý5¬è›÷¼î,J èÀQ–zäûN¦&úyÚ±2c½M¾è1ÇÛ9ÅûæÄ¢M}a­,‡Öª·ÃÓ¬ èßÎò 8©Ö}g—Ù €“$7-þ /ꙓ,ÄçÊêÑ·— Þ‰^»µ´€°¿!í˜PˆÎÏ'_Ÿvëº,65í¬‚œž½<faphÝ’„智ýÅŸí”"hwçÉÇÇöø,cçâLunƒ]ÍÉ#H²<ËHäà%¢T5­f¨´ˆGª1 º0 M[÷­@ḖõæqÀÔ,檢àÞÙ3î¶œt37Œ8Ü5õn@ÀŸ;déˆ?N•ù1›3¬Ò2I‰ÏHFj(½F49£Ñq¸¤0àäÆ9&L?[Q #v©Ž8“X ,@sð”vJ¼©¬š‡mT«=ú6BÜ8ep›¤4,?Â@/º>ýN‰ç‰,Ã<ƒ*–pîQúôË×>ð$Dï4P}„Ãô 0`ë¹3×Õiû}YØ\köÖóaÀ²¯ ž,òÐ =sRòs5æÐŒÏŠ{&h`İÀè0Hs, ,:× ióÕàÒúRKL1¡‘y˧—Wú¤â2 ä‰=t!Mk‘²­ Tؕµqk+»Ýüš³š%f[µ©~_Ó¯Æ 3n·)'£‡ ¶+v‡áHe}4W„ªqjSŠFœOúÊ|à’S¦ª£ƒ¡½Ó.h;ÑèU!ÊžWHêø?Áb ®Ú˦E¥„A=ÐMwÔö„ý‹X‹LV† Êb Í! ©qà¡Ô“‰‡TÝZZú²eaá@ýV8`&»Ø´ #ªá­Ë~·ãöh‡Í"çýè“Ô-f†H‹ô­žýdÇ{‹Žê]1žCÎcs˜þÌ|RNw~IG|„ºàrñ殇ƒ8¡ªü%¹‡×—9>1WOI©:ò„G¯„ñÿXiº ¦Q®ß¦ŒB/êjž²,LõQ 9Ù ’0Ï’æ‹s¸þ4l2]î€êÇL÷ÕÆžÝ›FU•–SŸÃür¦'DÿŸÄRÇN È<ú•X±Õ‘¬€”¢j tYÅF§žM½ÛëPÅ´eÁá;sŠ9‰M(ýÚÉ!Š<äê¬ìó¾o´ˆ)ñ¶OÚ6ÏŠw¯Ú]]Xâ+·`k3}õˆßð²ê–y'›‡ÚÁ¿òè°¿–¢me»ºÉ+*¿"~vh“Ló6kí<‰ÊÄ4æá?¯Ð,D«ƒa]ªm_nÜTõõÉ Æ@íª6°>„öúIo·^¨›L˧ƒ‰SŠsBó4mÃòú“Ø)Ñ¡Æ,ÛÍc˜8c÷MèMý‡ÐV@i~Ò•qu‰^7#³z¥V‘ž5ÚB‰z±ºœº(aäLΪ-P7 ½øÌÉ5º—&ß}fWñwŸÿðB‹ƒMp•·ºg[ÚaÖÈ]]ªI0¯œJzõ ý$Š+ôÏB6àÏ “!0ëxxBìMxþCles…Þ‰j ‡ÿûxª‡R‚c2úÿ 7‹ÿ¦ÆE‰ endstream endobj 2007 0 obj [ 2006 0 R 2008 0 R 2009 0 R 2010 0 R 2011 0 R 2012 0 R 2013 0 R ] endobj 2005 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 2007 0 R /Contents 2014 0 R >> endobj 2015 0 obj 2405 endobj 915 0 obj << /Type /Action /S /GoTo /D [2016 0 R /XYZ 72.0 720.0 null] >> endobj 2017 0 obj << /Type /Annot /Subtype /Link /Rect [ 199.311 506.902 256.842 515.782 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1968 0 R /H /I >> endobj 2019 0 obj << /Type /Annot /Subtype /Link /Rect [ 199.311 506.782 256.842 515.782 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1968 0 R /H /I >> endobj 2020 0 obj << /Type /Annot /Subtype /Link /Rect [ 234.0 473.6 297.05 482.48 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1798 0 R /H /I >> endobj 2021 0 obj << /Type /Annot /Subtype /Link /Rect [ 234.0 473.48 297.05 482.48 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1798 0 R /H /I >> endobj 2022 0 obj << /Length 2023 0 R /Filter /FlateDecode >> stream xœÅY[oÛ6~÷¯8ÈÐÕ b¤îZ k»bCw)lê>È6k“,G’ãÝòÛwxÑÅ¥Ð9â¡x» ‚3ñðCËtr§ç(ø lOO¹PÇb.¤ Ç.$bUkÀª>Ô"là÷ÉvBàíäÃG|¹‚ ‡ 銓Ìד÷-ýâ ùâúÛØ”ý/¼?Í‚Ï|«“Ém«9œQ‚Ä«D‡M?•T5TÆ©ç Q¤±‰˜ƒ¢ÍýrÊ ÜN¾»™|ó½ ”Àͺ)Z_0Rb,?7)|˜RÇ9ÿ7?NÞÜô²ù…£ÖK¤Ð]ûcÅÄ„zâ–L®¯R>ý¥\9eƒ -â¹b} Þýò˯ 8špy–GQñhŸaΘßYŒ­‡7%ßq¶…2ƒWYšâè]\ì ²3ìÚɵ! gÙnÐCÆÜaN¡?.y•²{žC”$Pn8”û] ÈÖÁÝžçG¸#'¨ –I´/¸U©ô Au¨EB‚мÆDx%ù*¶áz¡åR´Ù§:…×Çm= õ…¶Em‡æi–OQÃ:Ëÿ©ƒŠ\FŠ(Óã¼òAMÔf}ø0¢Á1h(;>+v|9¬'4¸ô<ÞÞÂ'-7èæéø”óe–¯TáµL^õ,pM¼E*[…Â#¤¯Qf~ÐHÏ6°À‡už¥cŠ|CWQ-¢¦6zº|fÐõñéR¢ !Î ñÕ•x•ßîS¾- ˆ¶+ø-Jö¼¶K Sh9ê%ÌéUHo»Q‰”]Ž+8‡™ø9N9£ö‹}ƒ„Õ µžM_u0*á²¶·F5\ñu¼å«šÆJ©†ªñm¥i”×4î«§=²I`ÙNXßžd µl›ñÎOÙ}õóõ5q]bÆ£|Õö¢Û2{®×ÑÖBh n6q!`2;^$Zî‹}”Hlœå÷ÞŠe¾_–û7¬5^^¾oùn?ÆÐÁ\c]¶+Ü#.L³]‰‡ šTÏ —g[‡5ãš„>m Ã7ÌßÀc TÞÐEœ jLn½k¢ÇW—Í´*ÛjI]·j"n¹¯+@­ÒUuÖMÑNá©£…J±ÏïqÔå‰V cdÖå'ª¦]R£åÁ(ž¤B›C](k£Ï£ŠÃ -Ú”‚×G ÜmŸPƒŒâ.i„ð‡]Î ÑÂŒÀ‘cÅÊÀ}Ô×È*7QÙP9’%@×sQËüë÷ïBµ&5yØÄx2Öd\œÌ—¥ª­6k+Åbk)‰šá|ºËÐÑEr4`cvÇ-žîÊãüùfyBr±OÊš,xyYܼ¦ä©^ꯨ,}5n Óh{læË2û’—טíR –Pæ¸Öûí²K³†cüGÑ_mÓªSø‰êGä·]ÕFsýw¹°üH,ÏÀYéƒlñ'ÖÏh—M£Mܾ}jb쮹"QX~îE"úì ýbV©¼°žno˜Ï,ŠzÅ®Uª^ób™Ç»Ñ”ÉKky¡<ãô!'-ĪÇ&‚ÁTXC·ß©Ý¨çååAÜdê©Uß+¤W´î1ÖñZ¡‰çxëF1˜16Æ{Ù¨¯ FQ‹x»*Ú/[ߢ-§°ùŠ£EÒZÐàBËõÖÁ%1 ’œhé ¦Ã&~Çèe¶-ør_¢bÓ MÌk¬T”W‹jô”H'ßU,I\”ÕëM¿­PCÓ² …_>U¥òM£¡´@ÂY=-´Öº8ê^lo NÓ°ã´Ð"ñ}ðL¡Õ½ºÏÿÔÑ8Ê Í™™:·Gîuxä‹z¥˜í°ƒè¸âuÌWã舗! ›}D[Ûtaëó1±ˆÊôQ™itlˆoÆjë±ÂÁ†®O`EΧ±Å­ËfBo*E<áË -´ìú:VOå|­ðCKÈšño1?4Ô«$* Q­-}qKvÝ(rüÄ0CIº¬žb¿Û%˜ ¨¡p‘íñùT"­“FaãW`»·Äùzcà–Ëu³!!ÓoÞ·s0$Ð6E9ÆV¯×±‹ÕŽ!RBý:Á£lŽ¥Ul²ƒÖ8Ÿþ÷˜ ¹èaRìJ8{tÈ`¹>º¯Ÿ\0`˜gˆ°VÖˆûúF„ì­Ð÷íã³Í¥¥úÆt€,Ð ÝWÏ[>41J ŒÙèÚøøìL„ÁÌA;CCZFìleÚN dNßÝæºwi×`G¨Q,ëféåKhåÄÀaw3€­€8œn”‘ã5|æ‹Íµñ@hýcæýä_% Ä¿ endstream endobj 2018 0 obj [ 2017 0 R 2019 0 R 2020 0 R 2021 0 R ] endobj 2016 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 2018 0 R /Contents 2022 0 R >> endobj 2023 0 obj 1990 endobj 913 0 obj << /Type /Action /S /GoTo /D [2024 0 R /XYZ 72.0 720.0 null] >> endobj 2025 0 obj << /Type /Annot /Subtype /Link /Rect [ 241.139 502.687 298.498 511.567 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1968 0 R /H /I >> endobj 2027 0 obj << /Type /Annot /Subtype /Link /Rect [ 241.139 502.567 298.498 511.567 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1968 0 R /H /I >> endobj 2028 0 obj << /Type /Annot /Subtype /Link /Rect [ 235.72 468.542 298.77 477.422 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1798 0 R /H /I >> endobj 2029 0 obj << /Type /Annot /Subtype /Link /Rect [ 235.72 468.422 298.77 477.422 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1798 0 R /H /I >> endobj 2030 0 obj << /Type /Annot /Subtype /Link /Rect [ 235.675 446.397 309.465 455.277 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1982 0 R /H /I >> endobj 2031 0 obj << /Type /Annot /Subtype /Link /Rect [ 235.675 446.277 309.465 455.277 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1982 0 R /H /I >> endobj 2032 0 obj << /Type /Annot /Subtype /Link /Rect [ 411.625 446.277 441.625 455.277 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 882 0 R /H /I >> endobj 2033 0 obj << /Length 2034 0 R /Filter /FlateDecode >> stream xœÅ]sܶñý~ž:¶Gb$ˆfÚµu:É$i«ét¢<@wÄäŽ<“<Ëú÷]|Iwîƒk?À~/v >lÂðÿZÿpAÑö°ùàæâ¥¹›ÊrDXB3t@nœ¡½Þ h?‚» Oèß›jƒÑ?6¿ü ‹;„áyƒ§ä òûÍ»€¿^Á_œ(AJèÿE‚wc/pÊ“‰o vjç`ÆÒK{g6÷k©Ú¡Îþ. …½L8n'î—cŽÑãæ¯·›?~!‚ÑíƒZ® N *ô?Šnè—W„ñ׿¢Ûo7oogÞüÂV›9RóôIÇc2RË8—;¥¬N?ȃ²JEÌÀ DE‚óLï/,Â÷7?^¿û×ÛŸþƒ,Ú°™`‘<)cs´;Jù¬! ïåIôpª¶]YW¨þ¨$÷{Ô=)ÔŽ{Õ¢‡¦>Àž'Õ¼ôJðˆŒ$X` [Ú_;¢=β½r‘d¤‚g¯÷/U'?õˆ"ÂL¤‰à9 ¤N“ƒ<^"£óͨ' „'´ ޝOÝñÔ]w/GuÝÕvQ2ŠÙgq£Ïö?L 7ç’Ed\ã’G¤2ƺVŸŽjÛ5ni‘ýáwõ²Â2…(˜!íd'ïe«–Ë>Ï|,‹ˆúœöÖYí"§ŒÆÂâÏAû|ÌJ“Œ18I„[ì›æñtPU×"YíÐÏròü#¢&r ŘÓõ0›¥ ’±9ö j8µÚÂÉ HS(J8ÐuƒªrŸ¬ ‡§—ÒxÆ¥˜¡Ý ×è:eIŽ ~f§Úò±’]Ý$~r%pXŸAf Pþ ©ÈÖð½ü2ÝJ?lËêq¯‚%çe?óüTnŸCÕ• 8‰Ðh?ì=‘ $¡4O˜€œCH„š'Õ=ÉÎCÒ„Múæd ýûwßy` lÁ²É«¶Úlëiwj&2âRªÛß‘ w¯Ž5˜à~ÿ‚ÔáØ½Ü½vYXwÆÁL$ ƒmÏã5%îØÚ ZqgšpªS>Äà2CTßÿ¦Yu#çZmÊ#dtû†~.¡ÙÚ©©ÕÓêŒaÏ?œª7náºçùæŒu8I² L-pº\ ãš¡ê<®/GkqŸ&9Ï0Nq!¥g¿ë‰˜ŠäÆCaZ¶]Ê–CqÍÓ˜hIOéöi ÚÛÐ&†GâÏ»(!ÀAÀ$?|óÝ¢x)4˘ƒtï•:+DšŠ$§1óúí¹ù^ÏÒf^k|o¦VdÕ•ÛÁ<&y»]e;¿E:áЗÀd²""!ÉäïB"ˆÀÝùÖoLpY^i tÐÑŒšˆ¸¸ƒ¢ðÉ(&Œä:ƒ 6š¡F.˜-àÛ¬~¦{{Òt5І]+ªŠPº¸ÞCÌ|ƒc™Í•MKVvQªºSm‚þ©ey.!]kÚØ”­vÉù7…:(°tý»j·My\í¹tÀÍžÓÐpßûÒö‚¯÷|ôÕÜQ ­äŒÐù¦4Åkø^[ÇÜØöihOÛ­.у9wà²Z@v…ÌS]¸hmïgî_üX}RÛSÍÙiWÁÏÙ¥PŠ…ëyç° Qää‚ÝÇ;/išp Ñ´öºqAîHÛ±SÆ+ršB`s¸ Ή_~ÂÓtŽÅq;îÏç qµ ¿÷³…ë@Q%m7e!©C+û{Ð|ûŠ+ ÖVVðˆ gÏËŠ5üБ€l²W¶[ÙìÔN›ò§¾ÓT»a¼Xãæ Ρ"PÍçd'/7±0ƒ;à A{¾ÚÖ—Þð™°Ÿ±íQ?-hüc‡Î›åg‚‘gè+Þ¥8•àÚ€cÖ>ïÝ1œO°L0“ÂÜêö}ç®a“±ô@ºß ÌhЈ¬®¸éáÊ!…K+£.²æR\~H9_£såy×õBY¯éÑoÝS¯­Ú+w)7º¶³½ƒGºjß½@Æ]íª)>×5"`¹—Ò—7žˆ~"èšòþÔ o¤O‘ÍNý~IW(–Õ–O\ÖW.݆[ÃvûÞÄ1j/d4ÑcžpX:­U[ó]£ÅÌÂ!{õ7µ9ú‰…Š5‘—e4)òBfC×jô^ !èÐ (C‚C»>G¿üÍ/çI¡Û4VÄÄнDíéÞœ_0¶~£¹2¢9O˜«æ½‚]z)¦˜bûŽtä4 z ¬hK“T·çúQuN0¸®tp¯d^xv,ý°·À0Q:|„p®›«‘RU@rIÝòp´ f(ãv~+`§:ÕÊJ-ñ9ª_¬0òBÁ':÷7 s³ðYÍŽ‹Vr6ôù˜B½I9p¹È5pÄý‹‰«™ÍݪóP¼Fð¬H®#¶S²iä‹m,¢Æy,>h0 ‘Gr¸êf1 ŽÜåb^’™H„¾|P–F„²ÊéX»^ˆ F`9…YÓ}À.œd#¸ßêV·4‹a·à‚ØA£(Én‘n\Äq§jÍnöÎ=:;ðÍÝë«1¿¹­2BlÕ'@ŸútÙÀYº¯PÝ·‚WtWMÜaÅ|šØWã7¸L .UyV©fWÛ¤,O ªß*ò…ËÞæh$ æ4Ðd0F‹3ïÃS‘$³Ÿ‚ç´Ö^¼HÆ×PÞº`÷c«Ÿ—Kš®_nÂnÑïk¡ª=lš¿`݆ŸûW? ÷ŸN,T{ýIžL×e¡ƒ’UH0v3–M´ÔŒ¡tM„Aµ}4Õ(Ý©¼ m}€ZZéôlî æ týÑ6ƒºžb†á’C>÷›…vÆ ]ŸÆôsüÁ¦J Ü+?vÌØ>c{Ø0àÝ«2QÉ•Ÿp§ß­Ò¢Ë'Žöðt˜jÔƒ}sj?þ¹TÏúÛ^¶­jÝñ·señ ¥ý' žpÓZå¡^d´'óµó3ágJ;ã¾€˜±œnwâÏ)ûG" Ûšcǃž2z쪶“ÐUSáS‘±OE¶áwˆ‘‘™©nJp J[ùà ýÇ#˜Î3×f¾ý$uiƒ?Ñy·ù/ÐÌò– endstream endobj 2026 0 obj [ 2025 0 R 2027 0 R 2028 0 R 2029 0 R 2030 0 R 2031 0 R 2032 0 R ] endobj 2024 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 2026 0 R /Contents 2033 0 R >> endobj 2034 0 obj 2460 endobj 1077 0 obj << /Type /Action /S /GoTo /D [2035 0 R /XYZ 72.0 720.0 null] >> endobj 2036 0 obj << /Type /Annot /Subtype /Link /Rect [ 187.72 553.412 250.77 562.292 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1798 0 R /H /I >> endobj 2038 0 obj << /Type /Annot /Subtype /Link /Rect [ 187.72 553.292 250.77 562.292 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1798 0 R /H /I >> endobj 2039 0 obj << /Length 2040 0 R /Filter /FlateDecode >> stream xœÅWKoÛF¾óW rhm#b÷Å]2@ ¨­S¤(8&ÚƒíÊ¢"Ö©”÷×gV|H"W´€®tàrw¾™oç±üâP øŸ˜‡ D+çK3GA1ಙò$Pá2VÐŒ=HÔÞ€µ#|ÔB8XÂ?NæøÃ¹½ÇÅ9<9¤¿Ý|ã\ïé7+äÕõï[À)û_,¸><Å”Û;›-š×s8Sod–Ò†¶æYïZkãêçQ£ÈÎ&b'¥1÷õ”øìü:?½÷€» UH‰ë³Àü„+¸=£=¿‡ðOç2œæ+³68H£»ó‡Ńõ !ôÀ­íáªÆ©Ú§+½Šk§,4Xàéy¿Ü„ÓOá$ü4½º™þ~øx5¼¡­.ñP7'Þ~ǘêä>®ã 4T…ÎJUIžÁ,Í£·5[YÌÔ%Á]d½ËûM¶…¶˜ã ÉÀõ¨Š6 Ý> endobj 2040 0 obj 1189 endobj 1080 0 obj << /Type /Action /S /GoTo /D [2041 0 R /XYZ 72.0 720.0 null] >> endobj 2042 0 obj << /Type /Annot /Subtype /Link /Rect [ 187.72 556.454 250.77 565.334 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1798 0 R /H /I >> endobj 2044 0 obj << /Type /Annot /Subtype /Link /Rect [ 187.72 556.334 250.77 565.334 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1798 0 R /H /I >> endobj 2045 0 obj << /Length 2046 0 R /Filter /FlateDecode >> stream xœÅXKoã6¾ûW öÐÆAÍ’”(‰ ´À6Í)º[k´‡$Z¢cue)+Éɺ¿¾”H="QŠÒø`Ššoß ‡ã|YÀ곪¾|N!Ü/¾˜=>Ç3[Ìâ"Ê`fÍ ©¤z Ú¬Ô—R‹ü½H~[ÜÜ©—`xZࡺüiqݳ_½Á¯n¿ïCèÿâÁõó,øÔGƒÜÔhGï©­¨z•ÚÌ·Öª—Ú9ý=éî|ÂvRŒ»¯gÃýâ—õâÇ÷ †õ¶+Z¿ŒÊ«? ë=Üœæ,ï`ýûâr=Êæ+³6Jde»Ç¢`ŒÉ³°êäú&(ÓG±—:( n”#ì±J>Ѐ‹??|¸ZƒÆ´’œ ({Ø#cÈ-¥þ@žà9\dû}\Â>‹âmŠ2ÎÒö"’§Pî$„‡<—i e.ÒB„•jÂð-a¸aŽ•O[xHkPƒ™fÌ㈑€sŸÆ>ÓR|m€ÜbŒ`¤Ræ Ô×"Ö‘٢ئô»Ïò#=©ÏÓ‰RlD!' ØæüôóÐJm¡~¼úãeR‰ã!U3 z—ßö*Ÿˆ4‚¿DrÅt`ÅA.÷0¦ÔÖ¨–•§cÔ»–>o$Oòi廞4Ùæ–ÓVýù*NìR¬Ázð' Dr+‰ªè¬.ðÇŠȶpn^¬“çè~9FÜqUÕ2Sð¿Ê"Ìã‡~Í[;Q‰Áç®oRsµ…%¨(œMg„yÈQ€1ú„´¸ÐZ»O»8ܵO†¢ÝPŒ5Ë1Y–¸C˜î‘;q¹S­¥U©2Ь‹0{èž²Žщw]¨³§Or184Ç4„îDz/M‡+â4”u ôÔÂFÞ‹ô„ÌSæ#ÏuÔÉr|­üò«Ø?$Ýy²u,Ê]Ä]Â7=û,NW=V·Ëq(Ž:þÏqªM´à™$ F ™¨³7çwðv›gjs›eÕ:–I´JÕÍT@'VÃ>Õ°KdžK‘—ýè¬&ØmbØ+QoHÉôùCR”‰µEŽ£­ôR‘Ë0Ë£ÞÆ©:†@ñ¸zq^À÷·Jòf#ò; ·K¨×ÿÞÁ›,•on—ÕglÌÅCÂÆ­¿¾QÇ%ó u©¥’*ïIç­匫JŸ;«4³-:o\5§dÔõíEc‘ Æ5ó-üqK)½È#CFú“Ê\Ÿa.FŽ‚u°Í\«æu¹Ýªй+†yL~jcÄ\ƒ¦ý-aåpäÂYÝÛ§¶7›gÝœÍCÓÍcÝžmrÍÀؽí5×vSä}H]H¥Œº­I7i$óä§÷Ý^;#têÓÈ’ßð1ìý‰|”I5 ÌÌzjÀ <£d¬ñåk8àsxP—g. YžpyØG˜qL‰™±ê’P,nŽseá99•BÊ \k‚Õ`0N—ÞÔÄ´:ùz=GCS±ºžc±ú2UÜ™Ãw.4c‹yŒÓ¨ú)£ë¼‘*×y·!^x'zè”i_}\ÆÂT«8Z5‡"é‘VfsƒçºƒøFwç4Q [ð½ù&E µ7Õ7ù{ÄQ|W…æ6ò,I6"ü<é Ȳ|Æ6gjTS'¸žÛÿ±f±ì8dzÿL¸^üÄqÙ endstream endobj 2043 0 obj [ 2042 0 R 2044 0 R ] endobj 2041 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 2043 0 R /Contents 2045 0 R >> endobj 2046 0 obj 1255 endobj 969 0 obj << /Type /Action /S /GoTo /D [2047 0 R /XYZ 72.0 720.0 null] >> endobj 2048 0 obj << /Type /Annot /Subtype /Link /Rect [ 187.72 556.454 250.77 565.334 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1798 0 R /H /I >> endobj 2050 0 obj << /Type /Annot /Subtype /Link /Rect [ 187.72 556.334 250.77 565.334 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1798 0 R /H /I >> endobj 2051 0 obj << /Length 2052 0 R /Filter /FlateDecode >> stream xœÅXÝoÛ6÷_qèÖ³FR¤(Ø€´K‹nA‡´Æöä–èX«,¥’œÔûëwÔw$Ú1P ‹$Q÷»ß§|Q ø››‹ „›Ù×f‚dàzÍ’ð€r‡ Ø@s/ 1RƒÖÞᥛ5ü=KgÞÏ®oñe32VW?Ï®öÍòâö‡¸”ý/\=Í‚dÒå¦B»õ®ÔŠÌ«¤¡­¹ÖZëÛÚ¹úº×)ÒûDì¤4qw³7‹ÙÏïP‹U_´Ò)q|˜?‹ \ŸP!Noañûìb1Éæ ³6I¤±ÝÅãÅÄú„ú$¬*¹² ªŽé£Úè:( Ü8ÄFÞ¯Ÿþ¼¼|sþö¨Q,%È€oÝ`ŠºaLŽô>eIK~MÅ«8Teœ¥lT¤!N¡\k·y®ÓÊ\¥… €Ó#-Ápꀠ¯6òn›V ³Ÿ7/pEg%mxû¼KKõ­c”xŽO2Ù` úÑàs‹dŽÁ›ØÇ”¹Ì¦ö‡/z­+èÈÈêÙœ‰T©–ªÐ{C`Ô³ûå×qŒ‹àÇ—ÏÓJ]ÏÁÊ DÔ óün»ÁŒ ÒþRÉVû3${ÔáGcö°&5žNQç}ÞDž G2ã; ï5Ùò–û­Jß‘'áLNµ8°XÇ<ÆXò‘^©m‚5U%þ`8€lgÍ‹ykòÌ9‚߀8˱nESò¿é"ÌãûaÕ[·=ÅÄ7¸lRóa§0ç¦1ìO‰ŽðОï¹G$G ^ 3œ[ð?õ.<®ãpÝ?6äý ò×ÝO¹hŠ ¦¡$»¡¸\c»éõbRº‡"ÌîÙ€#5€ôíi`×ìñb´• óÌE]5Áp­Ò;Ý´¿"NC]•Ç@5,õJ( †Iò¸‹›Î•µ…‹ojsŸô[ÍÖÎXÀ€SÌ,i{úIœÎÌïoN§ñ¸Øžâ°ƒtÍá‰$õ' à¶‚ë³[x½Ê3\\e™¹uÍS<¼ HãÄjØ%Çælj¸Ty9ŒÎjBŒ9©MŒ;¤õÆ4IŸ“‚&¹`­Ñ_h "×a–G¼ŽSÜ êa~¯â¼€oPòz©ò[ 7§PÝÿ{ ¯²T¿º95¿©1NÆ„MO…긖Ìw$”3K%ïiï­åN«ª=^­òÂ^6¶ø¼iÝ“S.íec‘ô§Uó= –b²tÌÂpx9Ô]v7á·s3*ÅØ².V+ôº8tæ`ãw<ŠÓ™ Í¹ø¶izØ3¥i™UókúÆ,}Y>i˲ïÊ¡vxìÞ Zi»¦ò^>׸›tÔ-ì1¾M#'»8½ë–º)¡Ó›FC¬…)G\ ÝKÐ•Ä †>ü´£ÂäG¸mÏŸÄR8”×ÃùxhæºÐåÇG¤CD@mf­ªÇåîP5x.s\£n \Ô$ãTÀ'Ùªk^ºÇ:ñõý¦¸p|áá‹3ËÔêóLî!|ïB7²Ôq™šº¼[ Õ÷ Ꙁ×j€^jÕÇe¬šzmvVÍ¡J¤•Ù¡)Àã|ßä ÜO” ü`˜ITQBåÞö~—¸È·)4îÛüyúédqƒùô²ü€í@àp†;rÏ‚ ³Í&ÞÿàºôÚüsájö&t¡ endstream endobj 2049 0 obj [ 2048 0 R 2050 0 R ] endobj 2047 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 2049 0 R /Contents 2051 0 R >> endobj 2052 0 obj 1277 endobj 1085 0 obj << /Type /Action /S /GoTo /D [2053 0 R /XYZ 72.0 720.0 null] >> endobj 2054 0 obj << /Type /Annot /Subtype /Link /Rect [ 187.72 558.779 250.77 567.659 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1798 0 R /H /I >> endobj 2056 0 obj << /Type /Annot /Subtype /Link /Rect [ 187.72 558.659 250.77 567.659 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1798 0 R /H /I >> endobj 2057 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 73.5 222.0 82.5 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1077 0 R /H /I >> endobj 2058 0 obj << /Length 2059 0 R /Filter /FlateDecode >> stream xœÅWMsÛ6½óWì©ãd*š¥u:îdÔ&Ö¤‡8š‚,¶©Tÿû.ø%Š„d'G<°xûÞ.ÐÅgf_*äo½/mÅAm— €ù„KØBÛ–ÚYƒïZøj&ac{™GáwïÓg\Eƒ{Ž—«¯½÷|;BŸè`ü‡xðþ8 Š+2ŠMm-š>ìi²Ci+[ûnVmšsÍû¤Sôàu‹Òºû|àî¼7KïÕ[ ŒÂr}HZe %š‡öÇa¹…OLªŸaù‡w¹œDó™U›Òb÷|0 ¬¦”²#ZupUKªá´ˆ¶¦!åÁ×ÀCBiçëÆàj1[~˜/®ç¿.¯þ\Ìþ‚ƺ·a¾@ÙZ >µ¾á\ ä9˜Ã®0«$Ž*뼀ʔU’ÝÁýÆTS@UeeWIžARB¼/ “Ué$Úæw…)KÒqTŽ>#4¤ˆ4˜o÷Y½ZgsZÎ $’é0T¬•óú!«¢¯aèc4 Ô·!થXÿFªhß13Éf²³ÝXIM]Ëÿô¯y€Î%FÇ>q8¬VQÝF¥9I….á—×€zïÓêqñ˜ðI „²±žwû-Æ®„([ÁÇ(Ý›ò´ãVL¦¥’K·ß“œFŸfó^ `bÀ$Q6?çg!¿ýÇÄÕi\¥‰%‹z)Ç2–LÞû$MaeÖ*U˜âðŸÕò5¼lfæKr^͈°[K¨v7‡Æ­ÍÄhoò<5QF)Ç¢Iý`@ì7SÆE²î'gÁd3Ið° ¶^ @׃ÊôM¬ýGWºïÓò0) çMXধâœýÏ—’xÓµ,]L¦á=¬’,õ­‡Hª Öº~ÉÍA¨2ÎwfT&¬Ú~0rÓ먒>%Ö %¤>eõ]äòk´Ý¥‡=몂1ÜN ‹­í™0©k7/¦. .FvXjWï3…œ ”UTTC'„¯œãÚl§âþ.jÌ!–ŽyzÌöæ"ηۤr®ŽŸÒƧcŠOóÛgc¾'Ęáð|;—OX6ˆf¥lóé:Y¸\¯±®–犇¯}¢¥ µ’mÕYä™yB K&ˆäõ Ô:;¯ÑÌ nÎ!J¡ e"ÄŠþˆA`½PiÉ»M›º> endobj 2059 0 obj 967 endobj 972 0 obj << /Type /Action /S /GoTo /D [2060 0 R /XYZ 72.0 720.0 null] >> endobj 2061 0 obj << /Type /Annot /Subtype /Link /Rect [ 205.72 536.148 268.77 545.028 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1798 0 R /H /I >> endobj 2063 0 obj << /Type /Annot /Subtype /Link /Rect [ 205.72 536.028 268.77 545.028 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1798 0 R /H /I >> endobj 2064 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 85.504 156.0 94.504 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1080 0 R /H /I >> endobj 2065 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 73.504 168.0 82.504 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 969 0 R /H /I >> endobj 2066 0 obj << /Length 2067 0 R /Filter /FlateDecode >> stream xœÅX[oÛ6~÷¯8h€-)fޤ(‘¶n“vÙÚ]Œí¡îƒ,ɱYJ%yi0ì¿ïP7;­¤/™DÅsûÎUþ2a@ñ;5©9›É—fäàxÍ–ë„»°fíBbNí-x»ÂK}køs’N(¼›|úŒC Hp7¡}vñÕäãž|ó„>»ü} Æÿ >>ô‚ä’ô|SQ;õîԌ̣¤­¹Ö\ëe­\}=¨ÝéDí 4ê>Ÿp ד×óÉo]`æ«]ÐJCÈ(Q\›‡ù>3WŸ|†ù¯“³ùÀ›ÏŒÚÀ‘Fvg «(¥ìY•secTmÓ…¿‰j£,0\ê¹æ¼ª f§§Óùﳋ«Ù›ùùåÅôÍå‡çóé/——¿Aͨ#çœO£\ˆ!£ç²OàŒÀÕmÄ«{XgÙMeËòm wë(… ÛlⲌÓkÖ~z¤µKZìŒPM‘¹W3»Mƒ2ÎÒ–æ0„ž&.SZKÖ@xuŸ–þ×–P[„1ê&÷šP‚êÓ3_ ËI? §eî§…_é7­íœ úè Ï&©U ÕêiÆ]n!°Øä0«QßÝD÷#ò×f`è—þÒ/¢ÃR›šðó+È£b›”»Œ9‚(åiíÖDq~½ÝDiY€Ÿ†ð‡Ÿl£â°âÆ…®&Ba8ráÄi@Œ å ¨ˆ¯S¿ÌrX៫&üà..×fhÚ—mœG!ø­¦d\?ň¢m×®W»r²Yç@o@à8Drƒ/ç#![þåa¹Ú#R"Á¥… ù:.ˆ$AœV>zØäz¹Žàoã'ÈVð²y0me¾G‡SA“˜í¼ Ÿ‡¡cÅfH4G’¸( Á6ÏÑ-ɽQ2NÑSu@4Õɸu$'Ž©> ûPΣ®s<:FOO Sj¦ÄiTy|»_­ Á•ýpÃN2¢áø°Í’!à VÌÂäIÙäÈ1?tJÜ­ã`ÝÝël›„Ý­ß­ö²°ÝZí­w»ìì˜,mo0[Ûe—µ6{wÊ•»ã&¦ÛuWíM¶êÕv¼×¯#u¤uð`ef8‘&Zp‚²©¡?Œº‹±fBH(›€¹øI‚FgéX³¡”h3ypÏÆæÑçBÑCíó¦.TÓÁH‘É ­pÎrkk+Îg_ýÍm²k¶ïT F˜öÔ ‹ã¢ôór¿u/N†Nu„×#Ķvqþ¾?˜£®ÈàèûÅqâo–¡‹ãÅ þ»Íã´„WÛ ˆŠbµM°x5cS’‹óµÆix ãâøè§ó´ŒòÛ> endobj 2067 0 obj 1364 endobj 1090 0 obj << /Type /Action /S /GoTo /D [2068 0 R /XYZ 72.0 720.0 null] >> endobj 2069 0 obj << /Type /Annot /Subtype /Link /Rect [ 217.72 536.148 280.77 545.028 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1798 0 R /H /I >> endobj 2071 0 obj << /Type /Annot /Subtype /Link /Rect [ 217.72 536.028 280.77 545.028 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1798 0 R /H /I >> endobj 2072 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 73.504 156.0 82.504 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1080 0 R /H /I >> endobj 2073 0 obj << /Length 2074 0 R /Filter /FlateDecode >> stream xœÅXÝoÛ6÷_qh€-)fޤ(‘¶N“nY³mŒí¡îƒ"˱VYJ$yi0ìßQ_V$ZI_2‰(‰w÷»ï£ï& (~§æ"5‡`3¹«Ÿ1¯~äzÀá.l ^»›]oVx©6áb N’ …_&Ÿ>ãË%P$¸ŸÐ>»’øjò¡#ß¼¡/.¿‹ÀaüAðá±$—¤ç›’Ú©žá“Š‘y×f«¯×jY«®{AÑ&j7J ÷å„S¸™Ï'?¾sQ˜¯vA+ !£Dqm>æøtÈŒHt¤ âÒ/ük?÷‘{6a?¿,Ì·qñ´Û˜#ˆRžÖŽ`u4g7ÛM˜9øÉþðãm˜ïnÜèj"%Έ¥©Ä°ã ig° óè&ñ‹4ƒþù°ªƒî£b IŠÊÝm£,\‚ß`%ã#ŠrÔ^»vËÚÁ Èf­ ½¦©äušîéõ_aPì•Ë©"Òd»àÒ†À|åhˆ8F;­|ô±ÉùbÂ߯S®àuýbÚÈ|=nNaLbÎó&ÒÕ6C¢9bˆ£¼0‚m–¡[â2JÐSMHÔuÊ8v$¸‡Åkœ¦Ì"éIç9RŒÑ“§Ó‚;¼—'adÑm·Z›ƒ+û½\æpœ÷ë,q´SÕÏ!“gf”ÐcL~haܯ£`ÝÞåët/Û[¿]u2±y´ê¬wÛ m˜Lmn0c›e›¹-&ƒwàŠÝv×ÍÚÄV¯°{{ý‚áWÅXÛ÷–OÆ]ÂM·ÓÔÆ©1ú~{K‡p†áãIf¡ÌÔÀcT7MÆÚ wˆ4M]¸66O†;ÇØ‘ÂÐRÚ`TÞ®«B9#Œ”ˆ‘œÐ ç-K“ª‡Ó¯þæ6Þµ[“wÊ#L{ªƒÅa^øYÑmß‹£¡gáõ±­]œ÷dzÕU£|¿8ŒýÍõÒ‡ÅáâÿÝfQRÀ««m„y¾ÚÆX¼ :Ï‘W‹#óµÇÉx€sqxðÓYR„ÙmÈ¢™£ðÅùì÷ã“ÀÊýG¨SG¾uØ¿o¬¼(Ö(bݯûÆQÈbHA÷ØÜ6—•ãbßðÝcÁ$„$Xµrq¼«æÅhÂéj…Ýq|Þ’ΙVByßTqXÒš$ÅXA«Ô}´éaßÔ±¸¦D˜C÷lŸîXŽ£Fvb^mFwé4ƒ\iKãŽåbtµqa#í"MÂçHtñ€g(•ÔM=²Cúx(‹Š­oÖù¨p©ˆv‘»T5ê³Vü)æ¾ë–®‰Ípæòxîüé"sd±áØ¡XûùîMÓ¹ÉvëMšuÞtú\ýäQ£kž%»u˜e]vå„×Þ]wX—-¹LãÝæ²Ëõ­6¬ÆL3i®Ç¬6ê/ŒóÇTm{FÄx@b©PZÖóìUÂ,ÎÓöG„Ý¥yè!sŃ|yˆhDAçÑAºÙDEç7 óý]¹ˆB endstream endobj 2070 0 obj [ 2069 0 R 2071 0 R 2072 0 R ] endobj 2068 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 2070 0 R /Contents 2073 0 R >> endobj 2074 0 obj 1366 endobj 1093 0 obj << /Type /Action /S /GoTo /D [2075 0 R /XYZ 72.0 720.0 null] >> endobj 2076 0 obj << /Type /Annot /Subtype /Link /Rect [ 187.72 537.964 250.77 546.844 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1798 0 R /H /I >> endobj 2078 0 obj << /Type /Annot /Subtype /Link /Rect [ 187.72 537.844 250.77 546.844 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1798 0 R /H /I >> endobj 2079 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 109.498 222.0 118.498 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1077 0 R /H /I >> endobj 2080 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 97.498 156.0 106.498 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1080 0 R /H /I >> endobj 2081 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 85.498 282.0 94.498 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 972 0 R /H /I >> endobj 2082 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 73.498 216.0 82.498 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1120 0 R /H /I >> endobj 2083 0 obj << /Length 2084 0 R /Filter /FlateDecode >> stream xœÅWIsÛ6¾ëWàÔ:™ÅJ‡vFiœN:‰=ŽÔöä“ņ"’Šíßn¢Dж/©å‚ Þö½ßføÍýC†Âíì[³G‘bˆÍ– ˜I´EÍZ¢ÄŸê-X»‚G}ôÏ,ôÇìÓø!w3rÌ®"^ήzòýòÃå÷5à”ý/\zA1…|SQózvjFþSÒÀÖ[¶Yäž¹€ )U53󢲘]?LuI8”­š¸»ÈÒ§”œÂ>6J¶>]Õˆ,\—ârgýº˜”-%Ö~1L?O¸˜jE(m›çÒ9´HЬ»)î/j (€ì‚Q×ßÖª›Ú üÒ˜Ü:!‰òr^æ6-lïÚrtõ¼¡Å<“wÿ¢1‰ç2´QÔWu^ ˜o²ìëI)> endobj 2084 0 obj 1298 endobj 1120 0 obj << /Type /Action /S /GoTo /D [2085 0 R /XYZ 72.0 720.0 null] >> endobj 2086 0 obj << /Type /Annot /Subtype /Link /Rect [ 187.72 562.187 250.77 571.067 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1798 0 R /H /I >> endobj 2088 0 obj << /Type /Annot /Subtype /Link /Rect [ 187.72 562.067 250.77 571.067 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1798 0 R /H /I >> endobj 2089 0 obj << /Length 2090 0 R /Filter /FlateDecode >> stream xœÅXMs›F¾ëWìäÚ™h»Ÿ,d&º©Óº“ºãZÓlVheÑ ÙֿﻆR.®}`Yöy¿¿V#ŠüíC …ËÑCµG‘bˆ{Õ–ô˜I´DÕZ¢Øžj-Ønò,èë(ôÛèæ>ÎÀÓˆtÉmÁ×£«û…¼:ÿ¶œ²ÿE‚«—^PLáŽo¶h^îÁNIÈ~Š+³UÏ’j¹,…+Ÿ{…"LÄm”JÜ×cNÐýè—ÉèÇÏQ‚&ó&h•R‚}Ø?†&KtsB=yz‡&ŒÎ'=o¾²ÕzŽ´¼k}8¢àXŸB_¨µu®ª”*uºÔKS*å0ƒð 0ñ¤=ï—€¯“ßÇ“¿Ï.¯Ï>M.þºD%ºÆPI°Pp^*ÞGß2¦ºo€ÎŸM¸. ÒhšÎ6(£0ô‹(Ý"ÓI®Ã"J¼SD9“€a¯$ü§³tØo0/À’úA he°ëMRèç0pp¢Dà€x€ñvJlÿ:zûÂqÒª5n©Ôµ•O\äß~3´‰’®LŒzÔLzªs³Wæ¹$Do3“Ü8qq³ÎÛˉs§ZBÀk‡ÝD9ÂU¡Ï²ûõÒ$EŽt2CÿèxmòýB[·I‰•ǸÜê嵪ö`gµq¼€Âafågl€!J§ÿš°ØÏWùX) dÊA£É"Ê!EâÍÌ\ƒQ‘¢baУµƒM¢wÕ‡ñŽç;=BòÌÂÖÌ«v¹{-ºh^Z´Þ¼˜!8£ KaÇ ¨Cß)9ãÞ¶æ®§iÀåkšµ”ÈÒ§üýrr¢0WÒÁæ`°q¨®nhÍ7j¤ËÒ8ÞæCù:Õá·F‘¤ùBjeOÑŽï‹HR¬ÃȦa;W_˜.—QQ˜ÙÅ:æ «ôeIðüY/WqÓ]C çÐU(4TWÅûjC{4¯nOûâs¡:8èâ—_'eÐã›úº1KÅwèÃÃæC”h, |îWÓå§…NîÁ’Mû·eoí¥œÃ5DRœ9¨ w7©†°h©7hjàºTî:™™,ÞØé®žX¢ùÐun’@©ï•KokË4ÔY;äë04y>_Çñ戚 tà¶ SM@ªßζ®cO÷‹cÝp,¤(ÂhuÁOsGÁÀëÃT&yÝ%B³8uŒ®£b­íz0V> endobj 2090 0 obj 1415 endobj 1624 0 obj << /Type /Action /S /GoTo /D [2091 0 R /XYZ 72.0 720.0 null] >> endobj 2092 0 obj << /Type /Annot /Subtype /Link /Rect [ 208.154 491.377 244.264 500.257 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1798 0 R /H /I >> endobj 2094 0 obj << /Type /Annot /Subtype /Link /Rect [ 208.154 491.257 244.264 500.257 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1798 0 R /H /I >> endobj 2095 0 obj << /Length 2096 0 R /Filter /FlateDecode >> stream xœÅXYoã6~÷¯ °@›,j•‡¨#hìn³E‹ @jc÷a³²DÇje)+ÉIüï;¯£§†1´#˜;/0d¬Ç}‹Êi^Jëý¨¥Œ»Sü­ie·õq“Æ›ŽJ³¬%JQïÊÎEQ– ªxYVú‘&,œiÀ5õÁºÚ‰¶Ðjr=ôxWBäÀ¥¹®Ñz"ÍGd‚ï; äU¦©eóÞ&QÙcŒ‹<‡ÓR“À3Êx2© ‡\ªãkg$ÈPb][UmLm?Ä€®DžwÝÀ¦Ò3šÓ;ôÔ«¢:­Ö{¥Ww`÷ƒ6éCÈ2—Y6ž<¯¸ÐÅ'xŸ‘Œ3Çû‰qõmï31~‚” †Ø!p¶83%àöà}{~T7ä÷¦Gíyt!½ù¦£í*‰ÀÅñí9ü—ÎÎD~Wo`Pí·«"›çð*H^MÀZùCL?- x/qÑs}oQÀ” DÿÍ÷ M„Ng—wJ >dÌÌ'-œÐÑÕz Åt¼æ€LÍ6€²çåæâ ÈÅ3›{òE_ä;% ªæjßÞ¦t—RVÀäUG¼¹œÁ(P¦»˜ù¬ ^¿#Õ T_jÚt!Y UÏ1­Æé]眸8ñ(vð뮞b¡úv”¡EZï"9žt¢çºs¢Râfö™¦ö endstream endobj 2093 0 obj [ 2092 0 R 2094 0 R ] endobj 2091 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 2093 0 R /Contents 2095 0 R >> endobj 2096 0 obj 1382 endobj 1331 0 obj << /Type /Action /S /GoTo /D [2097 0 R /XYZ 72.0 720.0 null] >> endobj 2098 0 obj << /Type /Annot /Subtype /Link /Rect [ 187.72 526.52 250.77 535.4 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1798 0 R /H /I >> endobj 2100 0 obj << /Type /Annot /Subtype /Link /Rect [ 187.72 526.4 250.77 535.4 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1798 0 R /H /I >> endobj 2101 0 obj << /Length 2102 0 R /Filter /FlateDecode >> stream xœÅÙnÛFð]_±èCá½—K*uJš"M`[hl£ D*bJ‘ IÕÑßwöà!rE}HåÎÎîܳ3³þ6!ÃßT~D@Ñj;ùfp Š˜gPÜCÄu(G[d`ŽRyªÐ‚>À}ždŒÞMnïa3B&¸ÏNßL®:òåþáò»0Bÿ ®Ž£ ¨pz±QÔLã£É­Ô¸Í|5W jåô÷¤R¸Õ ÛbÔýqÂ1ú2yµ˜\¼åˆ`´X·I+$!ÁŽOù£h±E·góg÷hñûd¾Dó{mH)»±‡!õ1ÆäÈ,\aŒÒ6} ·±6Êâ×G4p°Çåy_Ü,^^/¦7W¦×óן®ß¼ÿøi ñ<sÎ02¸£Tô ĺ©Â¢BE¼Ê‹(ɾ ŽVùvfQ‰òvÊ}Z•Nm‡°Øá˜zšéÛ}¶ª’<«iN»Ì Nü ĸìæUá÷š0°#˜;œ+ƒˆ±Aýzfû®åd)–ßÒicpß[UÂÏÇTk:õÔ¢Ì&­:ìâ“–Pn4"óɈÂ*\†åi9êþ å\þŠa̘`ìb¦é^_öÛ8«Jùþ Ó}\žVYF‹ `!€¹`C¯ .Áž…äS£ghÊ8”³|ÝÂÕ¦³±ÎÓ49Ü  jæQ¶Ë<-g-fV'ûóÎ$}GhÑÙ]æÕ¦s:Š×!œ>\åǦý4“vBòÛ©ôpÆýÇ•5†z¾=ì>½lâï w•ù@éˆ@”/¿Æ«ê´\á;BšçRaaã Å&)ÑC’¦È¸ÛÎ <­Åœ;'*%ãacê›—«"Ùu«µ»Ìñ½¸!TõPE>pÑY[ BgŸ„d¡4`S/ͺ„RÃ:$'.tiÎMŠéeµ/²8ª×ë"ßÖðé„`.DJs!‹-¦ Ø}­ÀÃ&Ymê…‰OÙØËméVÎ{¬,a” ³…ºÃÒ•PR ßW»}U/²¨I”?%°Í‹·,ò0Z…eMVVEnÕýV¼³¤JÂ4=˜õ×}sòúC…E4ÕrÏŸ[LóDÏ4Y ÁÔu¼¦"éÅÚôÁ²E¬Ó„b‡ÈKG· ‰"Õ·´1'J±ë:jáÒêq¤ôé&û˜ÃµeBXØEqWñSôbT! ØÀFõÚ†‡v±ìør_Æ]7çS¢Î†¾`ÖêµkK–AO›­qŽßV~ê+ÛYvjƒÂ˜Ls„Îm ×5®^ÿ#›g+fÝ€c#TT˜ã0 ˜EïÑÎJ:FÛHWWOƒ³n]S˜¦¨Õ6³v¯Ú„­q¦8*ø„Û¡! Ý®[®p:ET¯LCUðiA«s< ·ˆxÜ"áñVÉ!Q ™.¦úV…°ˆÛ…N„8rZÔûõSÔ¥”:® 2›¸ñxºÞm+>éøôh°Ñ~ÝÄY»2a«Íêíö(©»Ôc†ºÿ—p@š0ÜoJÒõ­Ç_Á,Ö¾WäÅ­Õ–•dÙEËÚ…e©îëé†Ê  {rPö<‹ìш0HžZ¤/<\t5@>aªaŒÀƒú³ËÌÌ4ÿnwi;rÛÞG ª«O]Œ91cåí݃fÒ­ËݳáýdP"ŽÙ4O†£cÕ4¨»« ݦЃ§¼ïÑLeÊm Úç‡CNðÆèqB–ßìaCÜ^jfItˆ•̰Oà¶Nâ4R:–(KR Ú÷¦OV;TÙé²¾#_¼€>Ý)S(3Ä›¹tí:‚‚wQÅeu!!ùB»™˜¿^ éÇ¿¤Žèíõ§?PíDôù·ùõÝiG KD¬òy?BO“ÿË%°þgIfåêõ£úÞý¤~²R{D¿2#æ=¢‡ô$ŠÑ|½†4+Ǫ‡èÂÄsƒLGæ¾4s{‹8Z´í¾^wú½FuGMƒ23@‡gYæ«$¬â뇤ڴ«±rÄ.û#ÂbÌãó½OÆè;Jq×P3#'e_éaX9¤÷1×<ƒÙz0J£°DÐl’BVëLðbõ¼ô„€É‡pÁ]ó~UÑWu}4`ì!ÜÇà“;Aö$z0ƒû¿S|W±zP†)ºIª}¨Fû1ážë: 2æ6o \ýŸójò/‡—}S endstream endobj 2099 0 obj [ 2098 0 R 2100 0 R ] endobj 2097 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 2099 0 R /Contents 2101 0 R >> endobj 2102 0 obj 1655 endobj 1341 0 obj << /Type /Action /S /GoTo /D [2103 0 R /XYZ 72.0 720.0 null] >> endobj 2104 0 obj << /Type /Annot /Subtype /Link /Rect [ 187.72 533.128 250.77 542.008 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1798 0 R /H /I >> endobj 2106 0 obj << /Type /Annot /Subtype /Link /Rect [ 187.72 533.008 250.77 542.008 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1798 0 R /H /I >> endobj 2107 0 obj << /Length 2108 0 R /Filter /FlateDecode >> stream xœÅX[s›F~ׯØÉCÇÉTë½Á‚Rw&M”KÇk[Ó<Øž–E‹@\Eÿ¾gY`¬'™¦ògœû·gÏúóˆ"cõ>CóõèsÅ£H2Ä݊师 Ì´Fí X}Õ"XMÁCÄ }%#‚ÞnîàåØŽHW])|=ºlÙWoÈw·ßö€Sö¿xp¹_É$îÔ¦”æš­H½Š«´UO­U“Ú9ý<è1>{R*w¿Ÿq‚F¿ÌF§oD š- h¥¤{ÌW?†fktsˆ|~‡f¿Ž¦³^5¿sÖz…T¶›x8¢PXB÷Â*‹+« tLƒu¨ƒ²¤Axˆù˜¸ŽúÞÓ׳‹ßÇ×—çã«éë‹«7>¾CZ¾‘¢Ž‡=®Œ{¼/Ë˜ì ¸CèºH7( çi¶ˆ’¶Ñ<]¯ƒd‘£4ƒ7ùc\与BZ¢Ÿ€NWë|û˜Ì‹(Mj™Ã s}ìPÏ÷%­v½KŠàK-è[ŒQ±OT’½:„ò׉Ú–/sˆuœŽÇM¼Ý\-~ø;Ü¡Ú)p©ãc6·ŠÝ&<s¬†l86‹ îƒü°N\›³ŸÑñâPN0÷%!œJ-÷*{x\‡I‘#€ú#ˆÃü°ËªXÃÒ¡„HbÉJoGPåmOä" Ñs4æô€“tièbÕz±Lã8Ý*7,¨ÚÊlùn}ŸÆùÄp&5Ölñ*Ì·Œf­·÷i±j}½—|½g¸H÷-Œ»0Sqº¢géΧ' k2B\Æí°ç´'öª©¿Û –L᱃(½ÿ+œ‡íJKLZÔ`4[E9ÚFqŒª"HÛ‹Š×f^àã@e”b. «q"´ö7a>Ï¢M» YÛ/çØUÍÐõªÿ@‡( ïKì£Ó– ¦U³lM×l89l³Ò Ð4|wªAUÛiW3ŠÇ, †³ÌÒµYF $»žJ5´À~€GñÂ}>$o\Ø®¢ùÊ,«Âåí€;°WWÞí)´T\©€3…¡“™ÞázQäaü£YêÊhz ‘RÕ ÄÇUßÁþĸ’5æ£ÜГ604«I^®Ã i½-VA+È czÑWUc¬MÛs$–zgÓ'ÂAÚ“* zX@$jÿ6«$5tœ&afÖ÷¡¡õ¶ ذ>, =tÒRì(pÉ-~ ê5 kÌWÅ+éöY 9pè$fUW§ «óm{kN½‹*¨á¼†á&’¯(›*6 WûRu±8Ãn],M›béµ.–¦÷Š¥YWí¶¨Yë`gW3×F§@3–iÛ¦fÕ†·æ¨9£å‰9—µtËæ&Èó=’+„%;ƒàQùôhGB÷h;åLð„ƒŠ3Æ¡gêÒ3ý¬7±™¢l/}TV†o!«AVì²h¢"оÜ>ï·^šf ÜûÌuûÖÂŽzty1NàNs‡&%’oBð>Ý…À°h‚ `_²ÿ&ÛU˜…èæLë‹wˆZúä‰ —Q/JOs”Dq_• ÝœTŶŒ ÚÍèË—Œ9† Sw"Ø®¯ hÒ§E˜§ŠRÓ÷õô|úz†TBÿTn¢·W¿¡:›èÓûéÕÝžèt 3D­öY·TO³ÿÓ¨>“(±jåݲ¿·'ÏJgV §[—[ËU«Ægµ‹­ŠÜnU¬²›÷¯…¨ðºüFˆ ÿ©˜? Q¸|;D¦2*á‚]ß°ûJÿ+ˆ:\tì“#ÜŽ„Žòxwu$Ç”P85e=ÍG‹M—K@F>ÔÚßÁÂQ·’Ôƒ§šðšS©Y·i æÖÒŒšsŸ¥Áb9l8y‘…Á:7êò~8?\"×}ÂÉëÂàèK˜¨ˆ¨ÿ—QÂb¸ß AÃsÎ}Úbåhš„¸õŸÊËÑ¿~ka2 endstream endobj 2105 0 obj [ 2104 0 R 2106 0 R ] endobj 2103 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 2105 0 R /Contents 2107 0 R >> endobj 2108 0 obj 1535 endobj 1334 0 obj << /Type /Action /S /GoTo /D [2109 0 R /XYZ 72.0 720.0 null] >> endobj 2110 0 obj << /Type /Annot /Subtype /Link /Rect [ 187.72 519.516 250.77 528.396 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1798 0 R /H /I >> endobj 2112 0 obj << /Type /Annot /Subtype /Link /Rect [ 187.72 519.396 250.77 528.396 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1798 0 R /H /I >> endobj 2113 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 141.186 234.0 150.186 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1331 0 R /H /I >> endobj 2114 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 129.186 228.0 138.186 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1341 0 R /H /I >> endobj 2115 0 obj << /Length 2116 0 R /Filter /FlateDecode >> stream xœÅWKsÛ6¾ëWì©cg"/„gÚ§q2Édœ8Ö´‡8J‚,¶©Ô(ú÷]ð-¤Ý‹k¸Z`÷Û7€3 ÿçæ#ƒÕnö£âQ ¸W±\¨p˜ ;¨h"³«C°šÂO¹ ‰-ü5‹gÞϾ}ÇÅ58ÎH_]!|?»ëà›òâø] 8eÿ‹wçYL:½ÜÒ¼ä!§Td–¢*lÕ·ÔZ’¥qåwÔ(ÒÚDìA©Ì}9p³7‹Ù¯ï\ ›¶h¥¤Äñ™2 ;øvÁˆºü‹³›Å ›/µA" vãЉõ !ôÌ­"¹²rªôé6ØéÒ)K„L9ÄsÍ~¿¸¿û4ÿzóÇç¯o?ܾŸR¸¡\9J 2b(üÀ˜ì ˆ)Xè,Ïà¸ÕùV§€à°Jv» ^g¤êìázjXê0~DÎ*I×zíÔNI‹S‚:DDñJ”w‡x•‡I\ËŒÇÏSŽK}¥$­âwŠóàg-¨,`”H‡ã”¬à øëÅÁ–Ùh^z„¾Í÷ýÐI› üò>AmÚÓ3‰¬¾T~ÚëQ/·M`Æ:ȃeMàøÖpýö{•è§óC9.ŽÕ¤x)}>v:6E¯áÏ :èlÜp“/9ÊCÝž¤ÃØ z„Ï"ò9Öp‰Ë”:>\$›Î,äίMEÉÑTnËÃü1åNvÚ-“(»ê°®ê>xÝeV qÆ[&ù¶kLÚ]ÔaÑX-g­7ª@‹úÕf•¢›Kœé¸*ß;ÝŲµÖƒ=¶±ë¦ð¼uÉL]06Éòo½ÊÇq¥ïH‰j“5,¶!¥0Š  `^Uô¼†y5ƨ£V±¨+ý¼Ê­á ]Û$‰t;O·s1ÇÜíäï­ÎVi¸ïN?ë1 ¥ã*F(qK¹/©^‡« 7µ,ˆã©„†Ä¡Ýü¨gw³¸meÌ<¯éfÎ5œl¯Wá&Ô놳<5äÄð‘ÜV)lhød33%'DlL~M®iŠÓ%j Óq°Œ:6o’ôFs5eô“"ðH{†áÇm¸ÚöúÚd×W=¼²’³b.Y%·$-eÞ¬ûGÑ&nJRø¼é¤:!Ú`ï‚SC/uC&q‡Þ4do|¬³áYpšÑYH§íB96Û£S£ËÑþso;3ó5$FÓ1Ä©4z.R—´óh îöçñ‘áù’€…œêüÆ Óøôàå©Âá**7?ƒÝ>jTÛý‡ãéü@¸Èò Íçg·¸2EÐæáÒIŸöTáÕÀ² {i€x~“zš îmaÙGû7–Q8SOV(ÖB5y=Û)ú!+kÔ çö4â™×@÷ê:U*B¹½{Ø}¸Öp³Ù๛M4.#ŃQ%«úÆ~FuºØ$¾/ ãÍÕ¯@ÃQ¼<5ï¶öÙd°°;8¾¥ñíT¼›åK7œ½-•k}í>ùïÚ“ý¨ò'žvõWås_ÕݹÒÅÉà³1Ì¡'ƒï |ÆíMÚ:Á/Œ¸›ý +î endstream endobj 2111 0 obj [ 2110 0 R 2112 0 R 2113 0 R 2114 0 R ] endobj 2109 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 2111 0 R /Contents 2115 0 R >> endobj 2116 0 obj 1177 endobj 1349 0 obj << /Type /Action /S /GoTo /D [2117 0 R /XYZ 72.0 720.0 null] >> endobj 2118 0 obj << /Type /Annot /Subtype /Link /Rect [ 187.72 536.148 250.77 545.028 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1798 0 R /H /I >> endobj 2120 0 obj << /Type /Annot /Subtype /Link /Rect [ 187.72 536.028 250.77 545.028 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1798 0 R /H /I >> endobj 2121 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 73.504 234.0 82.504 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1331 0 R /H /I >> endobj 2122 0 obj << /Length 2123 0 R /Filter /FlateDecode >> stream xœÅW[oÛ6~÷¯8À€")jN¤.$ƒ­€‹¥Ã†.Ejc{hú Ût¬M—D’áæßïP¢.–h%{É’“ÏíãwgüŸë.l’Ù£Y£À¸Yò a>$`Æ>ÄzWoÀšþÔ›p°‡¿féÌ_g_¿áÇ-8(pœ9Cu•ðrvÛ³¯¿8¯n¿ïKÙÿâÁíé)pÆÉàl*i·^ÕZ‘þØÌo­µÖÎÕ¿gr:Ÿ;(ÆÝ×3îÀýìÃjöãG¨«]GZ®©C“úÁ*¯ŒÒËo°ú}v½æ+£6:Hm»ÇŠ+Ç¡'aU‡ËMPuL7a¢ê ,0x˜$Nàëý¢XÞ~š/W_®@-×î¦Ô%ŒëÜ"wÇ °)ø¢ÊCžPî¬ó,Ün¢„¢ÌU˜À¡P[Øe9äj“åÛ(½ô 6Y’„é¶€êKqˆË‚4áqKx%ŽtÐhPýxH7e”¥Ìy$I|*¤äÔ ¹|JËð{#(-ƨê¡2FAõ7€Ex–Åc<¯C‚èٶÛÔ4Π+o¨p,RåÓƒ:s¬†ÎÛ`Ôfc–á:,&ìøV¤~~oôù£¡®G„¤t=ZK/òûC¢Ò²$üÆUœw\•/‰'ŽÌsÇØŒýµˆ|Nd»Š¿»,޳£f)žË ÅS²Îââ ®úœ½2¤}[µ q¤EʬÛD¦Ý”‡!$Ò·Ãmw}$¶hÏ5 PŸp¦agl dë¿Õ¦µÏôµ^”<Ï~æ²ûQÅ&úuÍZê}> pS/q'.4•ÛII»d°içU•ngº\·“®n·Kº€·“6+:å˜À=W²n|ª·J þ‚âÄ<ëù8Á׊fÞ|P„5zÁ0ý'Óoì±Då”ï`'qqÜG›}onx_ô– õÄ’½¯EÚu‰dy$|‹G“UOc#™»“É`’ƒ!I=]«Þ$KOf»Þäê„fCÞßÐVËPH,Ëa™ÄWc({ÆÞ5+úª0í*UžD©*š•ã^a2äÍ´I y’rÀ>œGE'–͸ÍÙe‰æˆì2DòCj`,ñJwï°':_F\ưáô±> Ó]“‡¸»8m-Žë ,>ž¾¸M[t‡€„y9× LÏ•&Vw«Ý]Žw± ?U…-€e›`c‹m³ô"CÒúá§my[VªÞ%=lSž·m0·™öè.4Ý^';Ý!ýÞqê =ìKðþÀ,ÅÆ²îT£­‚ëݯçbêBð>•¦=¾Ál}w|ʈ”Ôa\Þ-*kHòõÓ”EßåÄ—:Èÿj1ˆ«%— [7ªºòB|3Eå!ÔãÉpQœHµsÑ´)¨<Ç|Ĭ-¢{TcÑnª±Ö/ ïo—I‹Æé.2ð§dµiVBV·•Ö¾ñPTbÿH!¹éµ–JÁ".²öqÛ½-–Àõ‰~á³z\ŽÒÞAÜ“‡²%ã{gýÿ/mÉ3’ endstream endobj 2119 0 obj [ 2118 0 R 2120 0 R 2121 0 R ] endobj 2117 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 2119 0 R /Contents 2122 0 R >> endobj 2123 0 obj 1235 endobj 1351 0 obj << /Type /Action /S /GoTo /D [2124 0 R /XYZ 72.0 720.0 null] >> endobj 2125 0 obj << /Type /Annot /Subtype /Link /Rect [ 187.72 490.252 250.77 499.132 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1798 0 R /H /I >> endobj 2127 0 obj << /Type /Annot /Subtype /Link /Rect [ 187.72 490.132 250.77 499.132 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1798 0 R /H /I >> endobj 2128 0 obj << /Length 2129 0 R /Filter /FlateDecode >> stream xœÅX[oÛ6~÷¯ ú0$A­ò¢«‹ KÛ´@×ËÒŠ$d‹ŽµH¢#Éu½_¿C‘ºX¢íô%S|Hñ|ç~•‡AþÆòÇ (š§£½GGsõ–ã"b[ÔA)Ò´ƒyªCК‚uˆ%úk”0z7º¾…—ÂÀ°á>\Å|5ºìÈ—oð“ËïjÀý_4¸Ü‚G=«›Š›©=ØQ@òU¢Ý¦ª"•rêw¯R¸Õ ›¢Õ}:áÝ^MG/Þ:ˆ`4]´IëIF‚-Ÿò¡hš¢ëJØé-š¾]LÑ|b¯ )e7ö0D °>Ƙì˜U×ÓF)›>…)WFÜ`ûˆvyÞW çoÞŒ¯.?Œ¯¦_.Î?¢S4f”=Q +a¾åh@éä†R¯Ï`bhåœGQ»[r.Ò•ÈxV¶[¥èÐKÞ.f¹£yXtÎeÎôh7ÖïZˆ¼]ä|.ò(ÎîÚ-ðÈŽ*i˜EEÏBð¦MÀ.lôµû6çÅ:) «Ž‚gˆ‚Ã,`p‡«ØÞ®³y‹¬æÙpŸXH <¢%^m³2üQ3a„ø ¥1­“UOÏß6œ £h\<$cåÎ~ˆ]#x­ hÒS†x&]lƒTâ ¥ürÏ·DQÛ5p•Ûß/È3 : Ã3ɈÂ2œ…Å~9Œš¼€~ýM§Îñ$ ¶ky2 lªŠó»u ÅR HTô5Lּد¸L X”± `3…aÐ;v LçH±!YOû &Žê‚®G Óý2]rˆÑ:laÀ,['³é0úfû,Ÿ3Õf˜'bÑÒuÿ© ‘$bS7j ²sM¥Ý(¶éL$ŤݙÔ}åygOwŽÐ¼óv&ÊeçtÄ!œÞ¬›d#aÜ/Z°“b§gg¥ÇaB‹·ÜÀƒŽs¦}:d;o2Å0ÈŠõÐØ+‰Ù?|^î—ëù–çŒM=Œ…¦Ë¸@›8Iv!·iz\‹9;â;°9{©«§ÚnýšÝ1`šB&A›…é¤JÉ:^ÿìs‰˜êRxËy¯º3Ä4ýfaÒ1~=þ£H&¼Ó)-©b½Z%q5/«¥*qµ8ÐÝ¥i®®Ö¡¤cýÅwqké7ªºŠ û8&–LnÌ\×€´¿ÝPìbÔrgE eæÑX¬ËÕº<»9ÕoÂÚ§¡þíÞfäºj%»NïÞBäº¹Ô ¯ ÊÄä\à”M²ÖQÑJ‚¢ÕµFÑ]yú$ôÇfQ¬ø<^¨$P;³mC˜‰ŒYÌ…js¡‚‡zlÁÔñ€×DŽ؞·‘.²Ç(wþÀ†JcÄ5€í] &ôþFƒÍ2ž/›•n!EëSÑ?Û_4®Ÿðžü pÈY@\‹ “t­®Çj5ã--²îbÑÒ»JïéÕÙRJ¿n&”ZïN(µ§&Ô~_ñ,Úa©"®éÍ’CJwdÂÊP",0—4~P`V÷ÜEuc¯+AÖG«Q=‹áˆ4ë2ßò |ôP[_Ì.~„é*i/c¦ ºác¾Ž|‡é uÚ†yY]½[í&U6.»95}¸=(¸VŽQ q—KÝÈÆ¥7~)4‘]mˆ`コ»Ÿ ¨x”Ê5 ­@z9~Xó|‹® žÀ¸G×\G·èzçE9Îà[IØÒ< ãäM¹HÕy±åüöÖdÛ÷:Ú}&µ7§F½ý¾_¾„‚í1öƘBŽL˜?±¸bdå‹’å IÉ{þÕŇ‹×S¤Ìy^ó·4à¹4EQ•!èí—ÏQmÅPH´ÇDÛ!}?{zUißÛ¡¯IÅiœƒ³?ð,Î*·'’ú½ßc^Z"¿3}«VŸÐýL§½_¨è]•a¢‹Šê!í~<™TKd:¦¹(‹û-P¥¢v €n?:6BŸâû¸ +À?òu1_òïÝkjÑèõãè( ã¨|•󗙜iê ßŠ‹Ð·uk“ϳ(+€¡¦Žý x`§ÈäE †z nA÷Íkª‹8tq?(>Bãû¥L9xÞ‰|VN¼«©#€´”'r ÕóCǯòf«¨cQvY?(Ðà;‰ýçºÔ‰½’T?±Ÿmscêü¯òrô“ö endstream endobj 2126 0 obj [ 2125 0 R 2127 0 R ] endobj 2124 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 2126 0 R /Contents 2128 0 R >> endobj 2129 0 obj 1628 endobj 1353 0 obj << /Type /Action /S /GoTo /D [2130 0 R /XYZ 72.0 720.0 null] >> endobj 2131 0 obj << /Type /Annot /Subtype /Link /Rect [ 187.72 472.898 250.77 481.778 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1798 0 R /H /I >> endobj 2133 0 obj << /Type /Annot /Subtype /Link /Rect [ 187.72 472.778 250.77 481.778 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1798 0 R /H /I >> endobj 2134 0 obj << /Length 2135 0 R /Filter /FlateDecode >> stream xœÅXío£6ÿž¿ÂÒ¤©W-Ì6ØÆÕvR§ËMºÝnê%Ú4]ï ¤aƒ²\þû=ƦpH¶I]ûÛð¼ýžWçiB†ÿ©zIÑ2Ÿ<™3‚E>7GŒ#x”¡™5C™úÊZÐfý,Öè·Éf‚Ñ“OŸáeŒ0&¸Ï®&žOî,ùê ~qù¶>¡ÿ‹w]/*¼žojj_ŸÁ‰f¤^e6óÔ\õR+§Ÿ'•­NØ ŠQ÷å„cô8ùa1ùö-C£Åª Z¡ öB*ÕE‹}º¢„½úŒï&³ÅÀ›/ŒÚÀ‘Jö³=>"àØcL:fÕÎÆ(mÓ‡(O´Q‚QéaÎÔ÷¡&x3{?[̦ó»÷Óùâãìögô M}¯4ŸgjÂ/” 《!Ÿ{JEŸ€´r>&yñWÒî£v¹,òm±I6U{´Úy»«ÖáîˆâeTZ_—Õ.‰ò²=Ø—Il1+víf—,‹]œnÛ#€¥g`0…ƒ3B:h™G›¸DÀm—”û¬*½Æ Âáæ{Xb€‚kú·ûͲJ‹MCsÚß!hb¥ Fôü¸©¢/ ¡t#ŠSÒf¯ÿzv…ãË8É’*™–OÙTÙ÷pÈ]üu@™ž>roH`óvA©ÓНšý>"Šr—EÕq›œ:ÈNÔ¢*zˆÊÓrüÀ…úþµ‰žóq@!äcL}SÌnwû¥D‰è×(Û'åiÅU\ðÐ2€|$Âå†Aõ ˜;ˆn‘&S±Ò`˜'ØÁqðXœ–ÉÉ¡7n¡„K¨?Œ^ná€è_X8àq©…Âq )!÷¡þ3N†ñí´oHò˦.¡>ƒŽwU¬Úµ©­z³*²¬8˜â¨þLŽ(˜íAyÌЬ¼iOnšÒøufJ¤%tg½}(ªµõuœ¬"øº#¸*º¦ý²¤ì¤~ÏÎZ3xª´bòMžÈe7¦²ÛçHá‘BUNS:"$Ëê´\É °i®6Z¬ÓÒ,CB°]›õ´s}ν@…gèk¾ÝåF£O³€8Šâú®N$ï|}ƒÂêA•”¡À¦G¾IÊå.ÝÚmÒ5ßø$ô {0ñ#]Ou´ä9¨Õ²Üo·YªÇz¯ÓÜìFš—Z úÐ%ðL‘¡˜Q7â›1§§sgFQ™gh…pz\`¬9ɰ­ \}Ü7s›,Ó•¨{ (s´6#bâù! †PëœÇkec´–übs™2õ8—º« ž/P³Gè-ët¹¶ö&KëHW6³q$ëEù «> -Ågÿ^_c´–ü|¯c®q}Ò¾³[YW½Vñ^èŠjÛ“vÛ°ŽÌð.»}Cï»}CŸitÍ÷ÎÔÐl“MÜ!ÑA¤×‡u9dÉl.õ¦Í;½OK·à‹FWÅç-$«¸vu‘iSVåqkGÓWÆeÖ‡û„„r&isŸ˜}‰òmÖŽŽ®EìxʇfJ¹¿ÊÒ²²î %ºQa†j¯Ü¿rÜ¡à>ØåÓïýÕWßÍ5ŒªnŦäÃR¼F§_9ùÃ%­¯ãà6ƒ®Ë  ‹vñ´ØWÛ}uݨm tr†ÛÛ@óÓÊ9pößá}œÏÉ$ìûÀ¾ŽÅ ƒ$˜Š¦ÇÏÓ8A³Õ F–r¬?3ð \¥ô o§ƒ¶—´íL#qN@QYË4ªàƒCZ­Çnd„Iª±`Ü!ìl5§RŒÑ£h— ¼ˆke/H0ÆëŸ= [™ kŒ”¥ÇQœ$õ®¤f|ýEõ‰œB;òC ³!kRz™ÔsS”¡yZí#µuÔôœº¨ö…×?–ÝMþÒØ’ endstream endobj 2132 0 obj [ 2131 0 R 2133 0 R ] endobj 2130 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 2132 0 R /Contents 2134 0 R >> endobj 2135 0 obj 1415 endobj 1355 0 obj << /Type /Action /S /GoTo /D [2136 0 R /XYZ 72.0 720.0 null] >> endobj 2137 0 obj << /Type /Annot /Subtype /Link /Rect [ 187.72 507.516 250.77 516.396 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1798 0 R /H /I >> endobj 2139 0 obj << /Type /Annot /Subtype /Link /Rect [ 187.72 507.396 250.77 516.396 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1798 0 R /H /I >> endobj 2140 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 141.186 204.0 150.186 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1351 0 R /H /I >> endobj 2141 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 129.186 222.0 138.186 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1353 0 R /H /I >> endobj 2142 0 obj << /Length 2143 0 R /Filter /FlateDecode >> stream xœÅÉnÛFô®¯ @a3 ‡CmuŠn GB{ˆs $ÊbËÅ!©Êþû¾Y¨á2¢\píƒÞ<ÎÛ×ù:#Ãÿ\þˆˆ¢u>ûjp ŠX`P<@Ä÷(G920G™¼Õh Á¾Àý1+fý<ûü>n‚à Ù)âÅì®#_~Á¯.¿«#ôÑà®A…7ˆ¢fÍH~ÊŒÛ̯æªA­œþ=©¶:a·SŒº¯'£‡ÙËÙÛ÷Œ–[›´Bì…4’-sôù‚qù-™Ý,GÑ|e¯)eíaˆ@`CŒ1陥‚+ŒQÚ¦qžh£nðCD#\Þ5Áí‡År¾¸»/–Ÿn®] K4Ct¡™I‰ï{$ XŒ™ÜS*†|Š •r›ÖM 7»¤×eþXIÑÔ-¦Ü:®­ª2Þ¬cË¢nª$ÎDû:Ù´ð¶¬Z°JÖeµI‹‡æw$Ï–€×|úƒ1$4nÎãbS#`Y%õ>kj¯õ¹pøœ3GŒ4ñû}±nÒ²hiN‡7$™‘ Fîâ¹hâ§–0r#$ò–¾FR£Bßq3ƒhÌë¯ÙÜøqÒ»ØûWòŒZ•@¡N”ªæù19iõ‚&dø.›¸‰Wq=!'ryýð΄õ|€ˆy3ŒiÄ4õuõ°ÏUæBŠ ßãlŸÔ§—¾ÉB ûfTÃ’ß UŒC×2µ¢aS-ú°-³¬<˜Ä×(ˆÝŠÁ"êç|Ufõ•Å\AM¨|ÿ®ƒ3yßZu¾®Êf×¹½I¶1Üî nʾ„aÕ);Ã``§ÒÛô'…>ï3c.|w8}:&»>&\0" ÜTæ¥Q¹ú3Y7§åŠÐØøT8Øxh¹KktH³ "pÛÏ[1oÎ8„1/½~›áýìv»cDtd{ðÎ× ˜2?ŠˆoHJêu•>v{žs6…‘Ç#Š æšîSÒì«B·sáù¶÷«CÖÎu2BÁÇñaQÝÉ í<óíO•µ=÷'ˆBµ3¤U@OË¡§N~ ý·ã‰Ã0éûB« ®åè¢S|-B:J;ÙVenO§óƒøÂ>¤²Ï¢±Ðó•ñ r«Àa—®wöh2¸cöˆ† þSÌY»Pp1Öe²©2!&H­ð|¯³BŸV‰…Ë¢{ØZØÕÛd| ë 9vX £¶ÁZŒJó±í¯úØk¯¥Üi.wÛ·FÉÉd‰›¤ÊÓ"©¨Ã.‚°âtuhX]b©mYéóº„ý$-:¤e›==ë)ï[o JÖ‘Õ¸Ít0^Úü‚îÃ8°&tfßð¾yŠóÇÌNa×ÖÄ"6ØîGÛº’9„”óï/K"æ°H|üpëZ'ÅHZÝÄ•g}qN ®. Ðq ¶×ÿlúDÝ_|óýBwFÙM7¦Ë(Þ¡ÓŸœüƒ¡ïº[ëT¼}è@ý l‘nt³ÝÂä­§Æ §Xm”DÂ<ž Š_bœÃK2˜²ãÒ§¤A]¬ž/Jû “²‚ÐcðʇWzÑrv}Õìë4Þl:r>T%ãÿ[Æ›$ƒšwó>óÜ Hèq£µ¡›§u¢{ OÙ´ÙÇžt{/I&¹Û•¹@IUAnÀ²S§À*W¦Û‰…ŸÈ›À4Çé rm‚Vjñ×ò飿åþŽJÕ›]\ N7½ê4§«NwR޼›ýkËuC endstream endobj 2138 0 obj [ 2137 0 R 2139 0 R 2140 0 R 2141 0 R ] endobj 2136 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 2138 0 R /Contents 2142 0 R >> endobj 2143 0 obj 1322 endobj 2145 0 obj << /Length 2146 0 R /Filter /FlateDecode >> stream xœÅR=s£0íõ+¶L +« *“›$3×y޹+2)0È17b$ÇçÂ"€!´Zí¾}ûñ´gÐþ‹æ%AºcûÖ' $ð–­+X‚ð9°ƒÖ hPƒ>-{85¶ð‡• ᙽ¼Ú`hŽ Çtçä_l5¨ßDðêõÞØCÌîžñ¦_Ñ9‘/eä‡qdóÄ;x¹y.*­“útû ñOö_ â ú†AV=X1C ùHâs¶ç|Ö㈚PÑn¿=«3]sîœm ûžpØÒ¥ºW->/lØ$ äÑ…¤ä³j^yk!›ÚóóàäyþÎÕÑ Ó„ïO`÷p D\ÀIÖ…ênY®ß‹äÔÝÛJ÷QmêCjuïIʬ³Óª4ª4}l€ËT¨»©«Ý€¤3Õ¿\›¼|›iï#O¾Žp4]ûƒªO|„Eð‰{"ŠÈë×?ŠDë/x'èx« mÀàÐwOr¬ˆÅr)mRàË)6vaI-²õ¢ZÿU©ù$šHKRpÙ™¼)T5T¥‚j¹Ñ ës_JóÁK^±ÿú~I} endstream endobj 2144 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Contents 2145 0 R >> endobj 2146 0 obj 426 endobj 1198 0 obj << /Type /Action /S /GoTo /D [2147 0 R /XYZ 72.0 720.0 null] >> endobj 2148 0 obj << /Type /Action /S /GoTo /D [2144 0 R /XYZ 72.0 686.0 null] >> endobj 2149 0 obj << /Type /Annot /Subtype /Link /Rect [ 377.19 688.884 421.92 697.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 2148 0 R /H /I >> endobj 2151 0 obj << /Type /Annot /Subtype /Link /Rect [ 377.19 688.764 421.92 697.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 2148 0 R /H /I >> endobj 2152 0 obj << /Type /Annot /Subtype /Link /Rect [ 279.98 560.579 324.71 569.459 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 2148 0 R /H /I >> endobj 2153 0 obj << /Type /Annot /Subtype /Link /Rect [ 279.98 560.459 324.71 569.459 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 2148 0 R /H /I >> endobj 2154 0 obj << /Type /Annot /Subtype /Link /Rect [ 434.69 560.459 518.69 569.459 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1166 0 R /H /I >> endobj 2155 0 obj << /Type /Annot /Subtype /Link /Rect [ 238.238 538.968 274.348 547.848 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1798 0 R /H /I >> endobj 2156 0 obj << /Type /Annot /Subtype /Link /Rect [ 238.238 538.848 274.348 547.848 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1798 0 R /H /I >> endobj 2157 0 obj << /Type /Annot /Subtype /Link /Rect [ 251.91 441.399 296.64 450.279 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 2148 0 R /H /I >> endobj 2158 0 obj << /Type /Annot /Subtype /Link /Rect [ 251.91 441.279 296.64 450.279 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 2148 0 R /H /I >> endobj 2159 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 73.489 204.0 82.489 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1166 0 R /H /I >> endobj 2160 0 obj << /Length 2161 0 R /Filter /FlateDecode >> stream xœÅÛnÛ6ôÝ_AlÀ–3GR)[,M†½ µÑ>4}P,ªfK®%7 †ýûIÑ’-ZÍ6 ‹ˆ‡ä¹_¥Šü¦æ!C‹õäc»G‘d(íV,å˜ÅhÚuŒVæVoÁü î,–èí¤œôÛäÝ{8Ì„» 9&g‘g“W=þæ„|uþ} "Êþ ^zA2‰|c±#·;Ž9ZµfkŸŽª[:áÜó¤P¤“‰„ÒŠûõ˜ôaòë|òãuŒ(Aó¼ Zi)Á Sæ¡ù½;£’œ¿Góß'Wó7¿²ÕŽ4¼÷úDˆ‚cB=PË:W¶J9^¤kí” ˜'ˆ)LDlî'áòõÕÅüjúæéÕÛéõë—ϧ—Ï.f3ähì1i±â ã|Hã†1yŒ ÆÐåV§F)š½z†šôv¥Q¾­Ö°á…ÇÂG$ÆT¢ø¦Ðwèr•ÖõIí#®°b`ÈGCØãÉ€Õ8ÅD¸,Üåë]¹hŠªô8§$Ži¢”¤­ƒf÷e“~öˆ*ÀŒ‚¢œG@L¶8ÈþY8á› k×é'°ÆÔtºèL²ÇdT„˜x™@¢#¡cËÄÒŸ–½¨¨dÓiÈî»?ôýÏ(h‰,…`IëfêêÆIHºf›–uj}\Ÿö• ¹ýò}9.ha.%!±ÃºØ~Ø­uÙÔ(-3ô&]ít="4Ø&–8’Òºc4„<_jd°P•å #+ yËhHä9Èb† ’  f™6h™ÖèVëe:/J¡»¢Y¢Ó _$Æ´³ÌéÊÈÅ<î ™`•P¥¸ˆÂQöÁÍ8᎜ ³“> B`ALAùú7¼a’ –Ð;в[ß-‹Å²›ª[»ŠÓ;ë+aª{wbÊ<îàù²¨{,ŠÕªƒÀménÕ„Y°ødR¥«ü¸S+r¤æ£–ÁÔ›ëѸe8Væ,b§+DÐÏCÔ·KmlË8ŸqM%ÇЪO¨‘OŸf«Øêžw½Ñ‹"/t½ß± è´Û¶zÝo:À‡†ƒ²ªG¬¬:Zõn³©¶Ü7_wiYíVYÀ Îu¸ÕhWë ¹Òš’#b-X´­þ‰®ÛbÓoàÁQI ÇÐõy"ÛYÉÆ:”èvdBåkÔí=²ay2k% ¦ðEB(?¤tEfb‰T€Âhû–'1Ú8"°0… ¢\Ä!LÁ8ÝÎYø ±jERŽá? "ö£\)"‡tõ9]oVz¤Á'0†Àè)«u;ìõ”Wº9»97ÿ g~²éqsV7Û¢ü€rsî~GqmˆCh‡ÙáÛŸg Ìé6›>¹Ú˜@×/_¢?¡fËkyùä¯ÇJ‚Ä Ï‚è{7(Œ1ê‘0[I2`´*êfj3¢†jysö (õMð>=¶Jþs17Î’ð:”ø±jVd]å¹^4#Íx‚ý¸„zÄËÊK—éÐ~ â8‹f&ÒM²›îæ÷饄 j@œ´z]XÁlõ.¦sÆU"ýŒù¼ªmo„a×÷X³ôÂx¸¾¯½®=è[¬=*>”éJK¿ÒÛmµõ@‘ï/ø…ï°ö€*º¿¿g•6ÀxcTó¼]Ï!榼ö`©‡q³äÈ µ™X^ï´›(]pÙ}·¡?C˜Ö¸ÛhÇ-´Vt¸~ûCTÝ­}Ë̺-7(¹uÓ§Ùw‡ÛYTe©mÓë‘_ïœ3´L?õê]ž‹^ ö€h?´ÇFo×E]äàEg^ï¤Dh,À‰‚"+¤/‘ m%Äʬhvéø¼c¤‚(Ì'‰XÐ6ʨ6PlB&¹ð3©”ÛTjE…84CÃN5ÁÀ4\f†W´F«ºÚðé¾·À L(5]ì—A' (ÁÑÁǣЋ…ýŽd~“ÞÊ endstream endobj 2150 0 obj [ 2149 0 R 2151 0 R 2152 0 R 2153 0 R 2154 0 R 2155 0 R 2156 0 R 2157 0 R 2158 0 R 2159 0 R ] endobj 2147 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 2150 0 R /Contents 2160 0 R >> endobj 2161 0 obj 1492 endobj 1166 0 obj << /Type /Action /S /GoTo /D [2162 0 R /XYZ 72.0 720.0 null] >> endobj 2163 0 obj << /Type /Annot /Subtype /Link /Rect [ 162.537 379.622 207.314 388.502 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 2148 0 R /H /I >> endobj 2165 0 obj << /Type /Annot /Subtype /Link /Rect [ 162.537 379.502 207.314 388.502 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 2148 0 R /H /I >> endobj 2166 0 obj << /Length 2167 0 R /Filter /FlateDecode >> stream xœÅ]oܸñÝ¿BOExUñC¤d ÒÜ]‘"½C`#y¸Üƒ²Ëµu·+m$m|þ÷~ˆä.)zÝ©ý°Šó=ÎPúz…²þWò‡×8[ﯾš9”qœf¦J–!šã2Ûgf\f;¹Êày?z ²OWÝU‘ýóê×ßàá&+áñª8'§o¯>xüå“â»ó÷% ÿ_$øpêŽy~æ…MôÌhBòÑΘÍüjªz¨…Ó¿‹BN¦"n#î÷c^d÷Wÿ¸»úëOe†Šìnë‚–KDTä®åÎîöÙ¯¯ǯËîþuõã]àÍïlµÀ‘’·Õ‡d[ENÔRÎåF)­ÓÏÍ^h¥"f U†ë¼`¥\_i„~üiõñÝŸVoß¿¹½Í4®Å@„ä˜cŠyˆûc~Ž@SÙbÛvbÌÞ¾ÿå6[ïšqà±²}s8´Ý}6õÙí‡÷Ù¦™š/Í(òYQ†¢¼¨ Ï4ù7롟–Æê¼DU]sdŒvûÔMÍŸ3bá„ šW„¥Fõw¦}E#+7b»úÖŠÇ•Ò÷Ü^,J|–$9ñÎs{ ?ª_È1ãñ ã³E^˜³òªpŒ×®Ÿ–™¨ 2ùË Æ)ÁŠ”1µ”F«þ0µ}·Ì’’(Ë¿ý=ó¼šÜ©ç˜1Ø ØDÝ›áþ¸Ý4fM·É>6»£³k(¼ ²ÌËRî'ÎB·»Á¡¢Ü=-r&‘ó4CÎò’!Ø_”-Ç@œq€*ûèÙ¶² &7*'l´TÏTs   ˆE%.I€ãL ±5ÿV¹?Í£*/9-Š/v²³Ø‰Jâ:) þ3Ì d-X•Ï<Í4À¹[´÷räbÆó‚Ôð`vå­4Û/Ïh­›"'’&®‰=1Êe5ËÊÍæËê¶Û,kZ°Zö:[•²äzµrÃñ Öí¶…à³S2- ù8¨ßºñ|¹™ùÀ²íúÁ­Ç¢¢}/<â2ú=!üÕ**-Ôø"ïšãnòåï“ö$>·§TcјU ErÃ4¯=5æj×Í¤í©§¦‡fò!á€Y/ ý|´Þ›ÎûaÓvÍðäfÖýî¸÷WlØù.3›/;‘;ø&ö.bV|.*¥íey‚õM&y`ZVye$×Ãeö5Ê+D%:Bðæñ´¼1P™ÂµÌ}/êãÄhÝãCƒèæ·Bî±fga³§^ 2æuN8:*õˆÎÉ&E9®ÈÖ2‘i$îThžki£0F =¯òd0`v&JßÉP@Ħ=Ô1¬ÇÇ®ýzt 8{´€N !Žö桌úëèÚ95”òH•3^Õô-¡"7¿÷m—pH ×2÷ƒp´u€q—q€RO•NóTcGRg×nÎ'¾ Õ™M׃]TF†ŽÊ™‚Û:9ý –Úd>B™oi¼}æ|.s‚ NK£d©ØŒ« 5(Ô´Ýh'BŽê¿ü.ÖÓxm'ÌI¢Æ&Sªñ§ªGêg’V %ôt‘o¾µÃtlvË‘P±¾•àäTÑ’ÛÑ8Ͱ‰8µmçu£ÿÌÔAoNuáL$81 ÙuÓ-¨—<1Çy Ð¬9Oë™JHeÎJE$jâg2RùÚ“Àl“¸IuÝ~‘¼„C•Ap¡ÿMDPŒèž~~˜c"²U*rFâ0ôP£NOÙ®çíâŠei…®™Žƒ˜wŠ´ožÉn’G»ÉöbÿE v#)*Í nBÞšhBä ¡—l!CQþ]=×Ñf¶˜Ù¡a‚#ÄÐ÷éN»B9…©(iã¹2Ü[ûéÆ2:­úî<×HCa8 ÀçEuQïÄ"7ý^¬’%"Æ!ZÂFXö‚ÜÏXˆ`°††R[M!qikÉ‚Gš š®ˆµ(T%ª«š——š+@¹¢½ïÒ&£E5a3Š¥ÍŒ Œa匲LYM¤®Üjèôe£1ŠYá‚ÍEÀŸ ÏøŠqX'5âèR_(7S3Ü‹i%UNû*@•ɱf~ÂŽ8ä¡5T­4Bá"ÞU™#èFjÆ“2¬Üp¾Ð?Ö-±ëcGuXfæÐ “r7÷nëÆö¸¿öy‰îr€© gdsèæÛ¤3çJOÉæíDU}¿¦nJP­ŠXS¦jè±ÝíÜ#}~YŽ2(øÖÂ-×R­kØÖÍk—Xpî04¦¸Ÿñš.NOØñÜE8s Þù|×­/ÿ8Šíq1ôó§æyÔŽ \÷ÚÂŽï €©1dhB‚ŽPDÔXv5°2(Eõ°qR¶ÄÚ^lZ(ÒíäìÕy‰C 4 ¶†‚¤"´®åc(ξéžVS¿’¿Ë)‰¢¼¬K•“R* bר›Ë‡öà)·‰ú 9v²õ¡/Ë‚œ1s5kÙíž2e$1NPdƒ1ÒqžsY2 ’½(×aZ§hD*ŒNs  $¢.ËÃ!ÊÍ ¦¡ß}Â1Diã§r0)rZòºÆeÁŸÚÔÑ îc\^úC±Ì{5î´ÏåÐ\±ÎàÜ+@o_êÈéJx¼@쨹€¼‘h ti‡km`Hàz–`¾˜…–å·¶RuÂU É“jlò¢»©Ý¹EâDåH¸C|*Ëœl”5$éQlr;s7o#Ï—+Ò-ƒÝJdÂĨÈ9•ùD¤ºi÷&7%ZPI€ÔUUÐ+‚µ±‚Ì-¾“pòT”/­çñ×£P7Ö3‘9ÁŸ¡Ì‡[ÄÔ´:é¤o%ñ @A0÷»ÎÔÈÍ(®Ÿ+ü0TmÔô)!›Q¤Ò OáJ™šãÔï!W®Uþb²ÁY~‰K _É>©À$BðçwïSwë%ƒ2ƒv‰ð¥¹+@I*\ã†,~X™ÓÔ !”}¥ÔKg@ Å,ÇL¢Ö4É{冦1,Ÿ†~çÍ<š×1ò׎4;ïYçÆ¦ÔÀ\4H ¹Ïß[éR§™°7‹!û帀®‡á2b€»ÄÍ"_ÀñDýd*ÞgüGqá.f_æ@J uÃ&AÇ|ÿBCPJá *Q,–­AË"…èX7î–.0ƒÜ0à‰SÔ‹úž¢Îåwu…x„„jôËÃÑy+}íææžD¶'9y“¨!ÓAȵf¢qCu/e!Ó˘7™®Ñˆ†’KÏBßÝÛER{Õ´éuú#µWv½ãÒ ÂOÊ3 )á›&±ñèöã ß; æIMA¥•Vßd¸ú‰  endstream endobj 2164 0 obj [ 2163 0 R 2165 0 R ] endobj 2162 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 2164 0 R /Contents 2166 0 R >> endobj 2167 0 obj 2916 endobj 2169 0 obj << /Type /Annot /Subtype /Link /Rect [ 158.84 494.123 203.275 503.003 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 2148 0 R /H /I >> endobj 2171 0 obj << /Type /Annot /Subtype /Link /Rect [ 158.84 494.003 203.275 503.003 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 2148 0 R /H /I >> endobj 2172 0 obj << /Length 2173 0 R /Filter /FlateDecode >> stream xœÅY[oã¶~÷¯àc‚ƪDÝóvšdrd»Ûà .d™ŽÙ•%¯$¯›"?¾C%R7oÚ{`Å¡8ÃsãŒöÓÌ!6üÍÅ#Œ)Iw³OjÎ!!%n ¦ü€8žE}²#jì“L¬2´ÁÁ`KgùÌ&ÿžýò+¼\Ž3»/N2?Ì>û‹7öWßß&O³ï³oßùıÉb£UäVàø¶í‰,—ÆâGÉbG~9»¾y7ÿùöæq~u÷¯‡‡ó_Éâ?³›Eç8®CÿÇùÐÁ& ihõ -¹]œƒ$^eÊê‰Rqˆàð9 ÊÖ˜lRׯ_uóió†‚ѱ­¨cX'ô&­ù•µ60¤Ø{ú<ÞÐK—”úxšoßÁêƒ?d¸\¯æÇ’׬lØÛ8Μ“9u¬˜œÍõðv£Ç‰VuÉó§ =QoY®©c‡*Y²†Õzâs’X¥éMYì:¢Œ²¢6åĺuR'«¤bSr$`!Ï2M­jÊÔ*µ{ú9Tl-XÂÐ Z(H$ù]RkÚÐNy½Õ”‰D‘gÏš’ZÒ䊩Œ0ö–›‰uB›–&æ»’U‡¬îì¡•Ö@G¥5€†Js©åº6dÛÈí*͉­ôT鱆DZd‡]®éö@Hò|‚¯1»¥§ÐcÕ~z¸9äiÍ‹® ƒâµ7çTë’ÆŽEnIùtر¼¾˜€×;F±é¬ªÏózê“ÂòÌY’¯5Q²úPæšV;#ÑîܼCŸDªÚ‡Ì´2VîÆBž×ÅÄÍãj^!5v{Þ­Šì¢#g 6®7ÆjÈz ÈH¤åà8Âí¬&û¹ÄÛ3\$h“6Â8=¥]eIU‘÷{±y5™=!I;pça`Ûê_—¥—B}sÐbƦó4õ†ŒB]¾ õ&jV{–ò Ç´ŠSJ³HäÉΠÐG–=|¸ÓDccc­@kizaò®Ù&¢'Z'D’OaK¥Ö;P­¡éJ»z¸ã˜ò‚ÕÙ>ïY^ÈBª„£ä—fm<^ÇÕÂãMt*“"µKöãÀý#¥\’ÆGÄ=Å( +ÅJ'þ­à9œµÎK²/ù.)ŸÉGö\ ¿~bµôýÍò`z{&¼d+"J‰OJ~EštâÈ Ý(Ž#OA»fUZò½ÎÑãY’R*ó ŽýHÅ샵Ô'›{Gœ /' ¬È…2,p½?svleÈô}"Ä‹†^»ñˆ VHšd™ô§.®a°;>, ·¤Þ2‘y¦±Dî)Þv÷ã¶Þˆ”HvÕ+Q׳ì,ºtDº3 '™ =åíãÇ H`žW¶®¡ž\LóË{¨ï 2äZŠç#KÚêc˜²©ë÷«&:­3‘—> endobj 2173 0 obj 2105 endobj 1200 0 obj << /Type /Action /S /GoTo /D [2174 0 R /XYZ 72.0 720.0 null] >> endobj 2175 0 obj << /Type /Annot /Subtype /Link /Rect [ 287.76 563.636 332.49 572.516 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 2148 0 R /H /I >> endobj 2177 0 obj << /Type /Annot /Subtype /Link /Rect [ 287.76 563.516 332.49 572.516 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 2148 0 R /H /I >> endobj 2178 0 obj << /Type /Annot /Subtype /Link /Rect [ 220.0 543.044 283.05 551.924 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1798 0 R /H /I >> endobj 2179 0 obj << /Type /Annot /Subtype /Link /Rect [ 220.0 542.924 283.05 551.924 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1798 0 R /H /I >> endobj 2180 0 obj << /Type /Annot /Subtype /Link /Rect [ 253.22 493.124 298.768 502.004 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 2148 0 R /H /I >> endobj 2181 0 obj << /Type /Annot /Subtype /Link /Rect [ 253.22 493.004 298.768 502.004 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 2148 0 R /H /I >> endobj 2182 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 135.404 252.0 144.404 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1198 0 R /H /I >> endobj 2183 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 123.404 204.0 132.404 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1166 0 R /H /I >> endobj 2184 0 obj << /Length 2185 0 R /Filter /FlateDecode >> stream xœÅXKSÜF¾ï¯è‫4™‡FCR…mHÅå˜[p0>íˆU¢•ðJËãß§Gï•Fç@–ÃÎŽæëþú1Ý-¾/Pü³ô—ës7‹ïõ—ƒpê-é³ —°z-!ѧz Þ¬ð«:„‹5\/Ò…ß_¿áÃP<.èP\ ¾\œ÷ôë'ôÍõ÷ÆÿçûQp¹K±)Ñ¢ÚÃJ~”Ôn«¿+©Õ²"W}O’¢'jvJM÷í”S¸[¼_.~9•À(,£.i] d”xÜ×Ë |=d=úËO‹“å(šoìµQ µîÖ ëQJÙžYepÝڨʦ/ÁFUFÜ`{À}B©Ï{àãÅÙ_ÖÕ'×ÖéÅÙŸÖ‡ÏÇ——PIhqÌåÄåZ=çc 7œ»C€7€*Q…‚"¸MDÛl—çŸaàF+Òðw ümF¨OQ–SÉ:Ý¥agiƒ™v•ãÉ<ßwYíªËç´ž oPƨMlnS*jmP~Æzöøàj›Ý[±z´´yV˜y>€qjÀACÉ øðrkp¾TQJ·Ò^äGÆjÃOÿ¨çŽ-«£4­Êäøõ7x9DL0b Œ‘lpÇÛ»ÝF¥EAº‚« Ù©|š°™Ä‹ËDOÄ„‹F—ƒÑ˵ ƒ,‚× Ü‡GWg¹-™Aβ€]p‡÷) dÞn×&>u(•ÞD FŒÙ, ²Û¿UXL³ex%QPiC`¹ŽsxŒ“V* vIEVºðAGQûó]ýÀjt¾#/ç§Œø’QjSQW0•‡Ûø¾_Œ•ÛXÿðBm²•ÃX#ݲªMíOd§jÕmÜ>÷ή{'§ÝÏy[GdÊi¥¼)Ü!®ƒÞ‘Â5ˆ“1TA õ0_=iD¼öÒ>+¦cRVùWð¶C˜Ã|ÏyÜóñíxGàq‡ë½ðêDì¥B‘Í^7.œìq2OWìþc¯É}GÏÅÜçõsòlî“®$šš÷=⺨‰¶ û0‰óÂ*S<¿9ô%„•ö!X¾oNÏÎààýñÅÅùH‘©ÂÏQ–{¤Öp 3äGí‘CTöLZâíï7þ¹ ß%.Î'žd¬ž2â•‚“(ÂZ:}¡õ`ƒ7ÉÁ1©CVSv¾þ ¤kqXšædÛȉÑêŽV]µ¤ƒåìöy–’››Ë]¯× lKù½ ã(F)=õ„AÈ!NÿGô›ƒiÇX3Ø<…ª¬éÎÈq± ôzÖƒ=()zÙ²¶ï³„Áa˜¥«XKhw6Ás»¾Uí2ïPcR–új'ŽÚeUèëuÝ ª_«¬ì#Õ4+Úué•NVj”¥ÕJjúo³‘m_¢Ò‡£¡© ÷,ÕÜÆ9.xKÓ^Ù]ÅaŒcÜ«í&ÎsízݾW½Á=EX¥Ä¡›5—¢º•‚ã$ÏÚ¯î½G“Â9‚úåÿÊŸQ=£à±÷nUP(ó¬=x¯Ó <çG`]·ºvØü«™Ãq˜ÕÅÚ« ü—¬P³ ìØ8óÙN‘6—§Ôx¾ø’ºûÕ endstream endobj 2176 0 obj [ 2175 0 R 2177 0 R 2178 0 R 2179 0 R 2180 0 R 2181 0 R 2182 0 R 2183 0 R ] endobj 2174 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 2176 0 R /Contents 2184 0 R >> endobj 2185 0 obj 1210 endobj 1519 0 obj << /Type /Action /S /GoTo /D [2186 0 R /XYZ 72.0 720.0 null] >> endobj 2187 0 obj << /Type /Annot /Subtype /Link /Rect [ 495.835 511.321 540.0 520.201 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 2148 0 R /H /I >> endobj 2189 0 obj << /Type /Annot /Subtype /Link /Rect [ 495.835 511.201 540.0 520.201 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 2148 0 R /H /I >> endobj 2190 0 obj << /Type /Annot /Subtype /Link /Rect [ 408.0 466.13 540.0 475.13 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1249 0 R /H /I >> endobj 2191 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 454.13 156.0 463.13 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1249 0 R /H /I >> endobj 2192 0 obj << /Type /Annot /Subtype /Link /Rect [ 161.0 454.13 299.0 463.13 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1254 0 R /H /I >> endobj 2193 0 obj << /Type /Annot /Subtype /Link /Rect [ 312.33 454.13 456.33 463.13 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1257 0 R /H /I >> endobj 2194 0 obj << /Type /Annot /Subtype /Link /Rect [ 120.0 73.496 288.0 82.496 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1249 0 R /H /I >> endobj 2195 0 obj << /Length 2196 0 R /Filter /FlateDecode >> stream xœÅW[oÛ6~÷¯ ú²$ˆ8^$Q\Ÿ’4Z‚x-†º²MÇZeÉ‘ädޯߡI]lQNú’É€ER:—ï\>‘#Šü<}’¡Ùjôh×( ñÐ.!¢>fZ!;Pªßê X=‚›y Kôu”ú}ôí;<œ#Ï#r¨n'|?ºëØ×OÈ›ÛïzÀ)û_<¸ÛÏ‚`äf'ÍͬEúQjÃfïF«çÌ}Ð)ÒúDÜA±î¾q‚F—ãѯD /Ú¢Z1©/†Æ+ôí„Fþéw4þ<º÷²ùÆQë%RÛnðpD!±!„îÁÚ%WXPÓm¼R”# ~„˜Ä$ ôû‘8ûpé]ü9þûÿëöê ÙF‚òû ¾ìËN‡þ1tÅÓT•èþî•U^Ä Í7E’= ›¤\£|ú·šUhV¨¸Jò ×P„ŠO1‘”‡Fù—¸H´öZf8j¡Ä¤TÖ¢éF¡ñv}4v’áHpPGÔež§*Î^¶GÁ\ B8FôS–TIœ¢áZtؤ>Ç" „bcxûéæÅLøRr‹ðƒ*gE²ÖA=‘J‡L‡ÆZûºT:EÃ>:©–IÙLžl¸›…γADºž8Ñ%!¾±ñ k’=,ר[_“¬¬âlætOWžšw^í ltÖãy\ÅÓ¸l>ïÇE½Ê;†§Û—#æs¡€´€¶zÈWñå´ îrî¿W{5`h¢žï‚˜ëä㦌ŠÂvÞ,Ôf¯×E¾†‚¨ÚµNÌÌB¡fy1/[¡¢}¶YÏmhÌ\ÇW=©Âi­LóªU“/ZͨöâÉ8Ž8tõ¿$ê¹Ñq•Æey”Liä3ÒÐVùy¦ñ½E‘¯¼$sñU_9“Xûm}®"ß!sŽÝ‹¤ã}‡wšYÂnÇ¡é$ ÙeМë÷#þz†I‡G°/…ý^N_tµÌâ4mXçØ&IÈ)´‚”Äÿ‰WëT•Çv$œgÐ{ kur’ª þ'-Ņ©™ÿ²ÈóÉ©þõ³Ïyt¨‚½à”uõX}õ`@cÈ5¾€–Ôã&ÂQY…ªÜ!Áv6Ÿzñ¦Ê½r›ÍÎP5`Z:Á¸£Ñ÷á”Ò·—ãmÖÃi/€gs—ˆßƒh¯É |Ã2—LàÀÔH•ªZè®·#sÔâœÆÅä½›Æÿ¾s¢Ãh'CÝq¨Þ©Xo”†sXÄþ²'„úˆÐºõsõp2 é§bçTí3§ê—;?€¸SBa[),S_,pð‚ÏÇåöØŽ'ûìÃyXo!òL½‚kB8IÄE|{ºW ]¤eÞÁÛ0 yˆ ñõ1xwî1AÑŽ Ûãü1¾èœóõï?¡"M¹ endstream endobj 2188 0 obj [ 2187 0 R 2189 0 R 2190 0 R 2191 0 R 2192 0 R 2193 0 R 2194 0 R ] endobj 2186 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 2188 0 R /Contents 2195 0 R >> endobj 2196 0 obj 1274 endobj 1236 0 obj << /Type /Action /S /GoTo /D [2197 0 R /XYZ 72.0 720.0 null] >> endobj 2198 0 obj << /Type /Annot /Subtype /Link /Rect [ 184.05 562.217 228.78 571.097 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 2148 0 R /H /I >> endobj 2200 0 obj << /Type /Annot /Subtype /Link /Rect [ 184.05 562.097 228.78 571.097 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 2148 0 R /H /I >> endobj 2201 0 obj << /Type /Annot /Subtype /Link /Rect [ 160.754 499.351 206.421 508.231 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 2148 0 R /H /I >> endobj 2202 0 obj << /Type /Annot /Subtype /Link /Rect [ 160.754 499.231 206.421 508.231 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 2148 0 R /H /I >> endobj 2203 0 obj << /Length 2204 0 R /Filter /FlateDecode >> stream xœÅXmoÛ6þî_qH5`Ž¤Þ‹¶X¶¸Ý†¶k›¬Ãçcѱ6Yr%%i0´¿}GQ”‰vRtëœ:R¼÷çN'½Ÿ0 ø7U— â°XOÞ7{ Žßly>0—pÖÐФêTà†Â‹>„Ä ~Ÿd Ï'§gx3Š ×:W3OÞôô«;ô«ëï[à0þ¿XðævAnjnGïᎤn¥MØš«–ªImœ¾n5Šv6Q{Ps¿žr “N&ß=ó€Q8Yv  #£$ä‘úq8YÃé> Ã38ùe2;eó+Gm”H¥»õdž‰ )¥ì–[urƒÆ)íÓ+±–Ú)KÜxD¨ï©ó¡føùÕñÉá«gÓ·³gogÇ?ÍŽ@ó·\ÌWÖçœÓõ$üVÊVyþT9,DšBžA~þ§\TPÈe!Ë1F£]FhDQ ¯>—™,’,/³E•ä™áÝ'?" £(`MœŽo²J|0Œ‘E)£. £€R‡õoàsèZN&YY‰l!§w2F 1hQ`ìAk±Èf‘ŽáV/¸c3ž<…»#ÆNœÐ"×cšï°¸¸\ˬ*Ad1¼é¥,·¬"èy$p”0›½#|F®…çd%[sýQX'ÔCóêYxß%ò~LEYnÕ‰¥H‚@5°Yl`z½J+HJ8—Ivm^É=":XêŒÒ€6q$ËE‘lúеÖ*õ‰!j#Út¬×E~•IJ„Õ"öEs­KK“ÚNM'æœ*9›IµJ2#Á›Í¢H0Ï-G]±šÄúÕÄvÌE!á\…s‹¥Lw!ÀqÜ]Ü=!Èòlš%ÆÌ+NãÌr`²«Ü·(kr¼3C,0]¯¤ é4rH€áRØ5‹­ Cx6'›À­Œ;°ŒÑs9"ÍÃGËXT'Æô§±q–θªŸSÊ]×"ôŽ’Fkvqw¬DÙ-Îe?Š—›Xh46Ë"_o 2ž碔¤Û:ìȵ¬VyOP¹‘‹D¤IÙ—nŠòV¢:20E<ϧmñL]5u§É.ظÝ0õ©WÓ5å-)—K”W’vãemwwv`w½—gVQTÉâ2E»e`T/jÉNÜBØ\vùÀåsg/$ S¢5ëEÝ4Y¶¼i×"ëè|# ¡z^Ùq®DÕ.2i—ÙS»q·¨Ödã^tÞéµ{·c’ W+q%{Êd'¶ž%6ž;ˆ vTÕ&K5álía„T59‘EÄ­‘qo÷=D<ä„áŒF]§™‚fÄz“vqÛ„sq#<Ö¨šï—i^Mu“•( ¿‘’ÁC¹I:?‡ËÁ‘ð¶AöR™%Ù÷%ˆ¬H^\ìYqòêŽå²)ãñ”s<ÐÙ4?°Zã9¡8ÕÍ÷—y±F4V°÷é›#Y¡+%à|:Tÿ5Hjp˜nT7!Õ{Ú–csÀ÷ƺÌïváá2)Êjšáo5;æa‡(,#iKBKJ<>6]Mw°¼Ì÷g/_¿øõÙl~»!>Ž¢£OÇ:\:Ξ¹ÂŠN<Â'f!áô œö\èî×TŸ;ƒGËTT¨l¹l˜Uth¾ÿà±±¶¶ïGÞǧV|˜ª[Ac—,à[ôy;Î]g˜¢{âÜu‡Ù˜7ͱ½È lý§&"q5Ý > endobj 2204 0 obj 1474 endobj 1294 0 obj << /Type /Action /S /GoTo /D [2205 0 R /XYZ 72.0 720.0 null] >> endobj 2206 0 obj << /Type /Annot /Subtype /Link /Rect [ 424.94 688.884 469.67 697.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 2148 0 R /H /I >> endobj 2208 0 obj << /Type /Annot /Subtype /Link /Rect [ 424.94 688.764 469.67 697.764 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 2148 0 R /H /I >> endobj 2209 0 obj << /Type /Annot /Subtype /Link /Rect [ 233.76 560.768 278.49 569.648 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 2148 0 R /H /I >> endobj 2210 0 obj << /Type /Annot /Subtype /Link /Rect [ 233.76 560.648 278.49 569.648 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 2148 0 R /H /I >> endobj 2211 0 obj << /Length 2212 0 R /Filter /FlateDecode >> stream xœÅXKsÛ6¾ëW줇ڙ’@ •ÇŒ+i2iR[šäçIÌF"’r¢vúß» HŠ¢ Y§T–Kìß>ío= ý%"“eï[Å£ xAÅò Üe>,¡¢}XèS-‚Õ~™CHÜÁ§^Ò#ðº÷ù ¾œAï=ÒUW {×-ûú ùéöÛx”ý/\ïFA0ávbSJ{†‡£H¿ZT°UßF«!sæû Sd뱃R¹ûóŒ˜÷.G½'¯| F³mÒ -H‰²HŒ–ðùŒFäü ŒÞö£½hþdÔö©m7÷ñ€b`CBݹV\Q]ÊÜé½\*s) <¹$ðõùÐ\ Þ FçÍûáèâýËs3xùáæjFI#ŠX¹ÉâU;Y­‚`YP,2á‹ZPgRçx‚¹!œwjûPWq‹±-熉uÝЇcEÃÐ …‡·¡?cüˆðÖ|œ¸‰\­²t•Ųh1 9^´1ðvá©Ä“2o«Ëót¢•µ`øw§ÁyäbèpbaÒÛp:u¬ÇhçØQ¸pÔìK¸ðfv¤øÃÀ¥&›‡9µ/ü@|(cǤ!Î!I بZЕˆI¨áý kT–¥™>ŸÇóD.jzBA0^¢ˆUéUýwðC.W‹mï°u`ê¤B¯©GvÖ™s5ìLt :·g·çÝ®\Ý # ú虄~œÄ…ÌæÐGºØ¬ö–BÍUýéØùccëU«V„{ZQí¸¥t\)Í‹,Næ·çúÇ¢ˆ‘Ž"ìÈ¿<b›Êlê\²MÁèâþáÑ%¡!÷ÿ}aÑä±=˜&™Â¤fYº¬àúñ²:ûH7ãaç˜ß…´ ȽÌôôF°W•?FåºH|“LCq‚À‚eës{¶”_·S´ô^ÇÌ×?ÒÀ@üè Æ¡ã—o-'£} ÑjV8ù·E5¾ÑRÙþ8-îl99 GNm8ZW ¬59ë‚÷ô©Þÿ¸C„Cq{¢}"ú¸îÌÒôÉXføû·úfõ„W7þ(«çÓ¦\ ÏÁ·â]O0ôì9Œ,ªü.Êvx‚.ŠíÍëXŸá:Œ<ˆBVƒwO f3lއ'>Úô1$‘}¶;yu÷]C 3NïÎu?<¡ñùXXˆn%´ÚdJ_Êmû¨?X>E‘¨zôŸ*[ÆyŽDóLÖ{×)(Ò’·Î±Ÿá¸Õtón’&‰*WæS|ÇŠ.àãyuÓž¨r‡‘ø'T\¬¥¦Â`—ó8Åý±Þó/ôàS7€3U«k8K¹iè±jH3jÊYnñ¬!Í"`èÖ`Ûû6¬—F -W+ó `MßÉû–ùõlObܪn*÷ñgÆVqo®‘NãÙf?±ìÔ»hTkŒG\±ußݲJ´*ÚLÞæÑlC†.»Ró¤[V­ËéHÅyë\=Á[¯[J¯"ñ\ŸøØBÛ¥ØE> endobj 2212 0 obj 1447 endobj 1249 0 obj << /Type /Action /S /GoTo /D [2213 0 R /XYZ 72.0 720.0 null] >> endobj 2214 0 obj << /Type /Annot /Subtype /Link /Rect [ 245.76 557.675 290.49 566.555 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 2148 0 R /H /I >> endobj 2216 0 obj << /Type /Annot /Subtype /Link /Rect [ 245.76 557.555 290.49 566.555 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 2148 0 R /H /I >> endobj 2217 0 obj << /Type /Annot /Subtype /Link /Rect [ 178.0 535.096 241.05 543.976 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1798 0 R /H /I >> endobj 2218 0 obj << /Type /Annot /Subtype /Link /Rect [ 178.0 534.976 241.05 543.976 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1798 0 R /H /I >> endobj 2219 0 obj << /Type /Annot /Subtype /Link /Rect [ 215.079 481.202 260.55 490.082 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 2148 0 R /H /I >> endobj 2220 0 obj << /Type /Annot /Subtype /Link /Rect [ 215.079 481.082 260.55 490.082 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 2148 0 R /H /I >> endobj 2221 0 obj << /Length 2222 0 R /Filter /FlateDecode >> stream xœÅXKsÛ6¾ëW`rhO„âII§nâdÒ™8M¬¤ÛZ‚,¶©”ÿû.R¤Hˆò)±Ç^»ûí·ËÅÒß&øÚ/¥š¯'ßê5ŠC<¨—d€¨ÀL¢5ªÇ%öTgÀš|¹C0X¡&é„ w“«Ø\ ÒWW _N>uìÛòÃíwpÊ~ ‚OûQPLá^l*iîÖ`Å)²[IM[ýí´º¡ç¾‚"-&â'¥†ûãŒt7ùs6ùõ­D” Ù²MZe)Á!Óö‡¡Ù]PÍ^Ü Ù_“óÙ š?˜µA ­í?QlH¡{nUÁUµSΧ‹hmœSDˆ˜Æ$ö|è¾üýælv>ý|þúãç7—Ó·Ÿ?~˜¾¿¸œ]¼>GNÓNž1ŽCna„|¨éš1ÕàcèËf•ÁGt-ólîcó€æIT(»ý×ÌKÜø£<þЉ& 3p:ßnÓygi#s˜º@cIC­­©»|LËè{#¨=Æ( ° ”NiíBõÓó:ž“ÛÊ×inæY¾(¦ÖÕiœe”ÎMŸ5É|¦d€«I6ÇÞA˜öÁD¿ügGLqNn @Êœ¥¨ Ê–(ÚAâŠce3]H:ÔóÕ&øk›àí3b¡ )ôP÷5d8”hÖ¢3ÄkÝ=(†Ž‘O‘–éQƒÑlè!N´0Ëh›”¨ÌP¹2èÞFÎryZoL›§øx^0Jq°!kbÞ˜bžÇ›îóï­<ÀJ€Ê&¿qz‡^ ©˜¢“(mÇ»ˆïVn{²&WpL¡äÐt• ;%ãYAÈ覗C,Ãü úM­5Tq$ÐŒ“áŽ}WëÚ¹u;‰n“½½¨lgE™å¦èÐ_c±°é‚Ÿâ· C©'D3Oüûˆ7iD¸/TlÌ<^Æ-Üs|ç§›ìŸÝJœ¶ã‡U<_lé«å:&ÖÑ¢³“¥Écçܲ\!pÅ©Cɇ^IÎȈ°rš•íò;›ÇàÞ¢ÃE\v¨ˆ†âvé}Ú»,mh @*¡t(áæ­€”«€Â ÌAÅËvµCw·ó=©Üì`ºÍ´7ñr 7›<Ûäq4w¢Is7uUÃGb£„С†j7tëhžÚðŒÈ·¶MÅsÓªw|¯1¿³ER‡Ó+˜-Gï&ëß>¤#ùdž2/«k¤È‰5\A„ Ÿø±ë ZÊit 9³Ÿ;™ìøpT…Ä¡íQ´ýCG£Ê4“ÂUÉ ÅJÙÎ[Õ-Ôù÷h½IÚ¶É×îrâÚc¨›ªnñO “yèʬ£8¹A¿U™³M’= +“tõÊ-Æ‹Dí±Ø$‹iYâÒ8…$*7¨¼~1|œ¹$=³Ð&^ŸÜx‚I =üJT]v>d ×þØëawS?C ±  qZ¿³ŸU桎Þ>ŽBÐ û¿ÔEì"ƒ‹>½{‚Ñú?JÒ¦þÍMõ¢%è2.·‘2÷*æŒkzêצÃ3yžåîü3éÓä³ní endstream endobj 2215 0 obj [ 2214 0 R 2216 0 R 2217 0 R 2218 0 R 2219 0 R 2220 0 R ] endobj 2213 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 2215 0 R /Contents 2221 0 R >> endobj 2222 0 obj 1411 endobj 1254 0 obj << /Type /Action /S /GoTo /D [2223 0 R /XYZ 72.0 720.0 null] >> endobj 2224 0 obj << /Type /Annot /Subtype /Link /Rect [ 245.76 564.587 290.49 573.467 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 2148 0 R /H /I >> endobj 2226 0 obj << /Type /Annot /Subtype /Link /Rect [ 245.76 564.467 290.49 573.467 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 2148 0 R /H /I >> endobj 2227 0 obj << /Type /Annot /Subtype /Link /Rect [ 187.72 524.037 250.77 532.917 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1798 0 R /H /I >> endobj 2228 0 obj << /Type /Annot /Subtype /Link /Rect [ 187.72 523.917 250.77 532.917 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1798 0 R /H /I >> endobj 2229 0 obj << /Type /Annot /Subtype /Link /Rect [ 131.155 462.751 176.21 471.631 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 2148 0 R /H /I >> endobj 2230 0 obj << /Type /Annot /Subtype /Link /Rect [ 131.155 462.631 176.21 471.631 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 2148 0 R /H /I >> endobj 2231 0 obj << /Length 2232 0 R /Filter /FlateDecode >> stream xœÅXKsÛ6¾ëW`rh…âII§NlwÚIâ&VÒƒí-A[ŠTHÊŽÿ}_"!ʽ$ÖŒ…×·ûí @_'øLÍ— š¯'_«1ŠCÜ«†¤‡¨ÀL¢5ªÚÅfU§Áê|ÙEÐX¡¿'É„ ß'×·0¹@ÒW‚¯&;úÍ ùîú» 8e?„ÁÇÝ((¦p/6%šÛ1±‚ÌT\¹­ú¶RmÓ’³ß{I‘–q;¥¢ûý”t?y3›ü|!%h¶l“V %Øgùch¶F×G4¯nÑìÏÉùlÍïìµA îÆŽ(Ö'„гÊàªÊ(kÓ‡p­­Q7±Ošõ¾|þëìtv>ýtþöòÓÙôâÓåûéջ˲B( 8ö¹aàó¡ÆTÀÈ}Þ,ÂBçþ‡wa®Ñ2K×(Ó=„ñVãÚå0BPLÒ<+íb›Ì‹(MjÌ~y–ÔE+]=%Eø­e”L‰"„±J*ÿzöú±r[Z9Íô<ÍScâÔ˜Øwc.-5) ÔcŘ‹Vz÷ž{Maž‹á˜E€–¿KGàÔñÓ¿úiDç.EufìUÆ•38¯E‡ó€r(D@)ðªŒ<Íî·k9 “úbr0ßOÙä…ä˜{áØ® v%žtš (É‹0™k”.QØ÷xű2›HHêô%Òèmæù^ŒúXà)‡µû£¹cNÍÞ|$|hÁñ9¨®…ê0trK $ý²ô¶K“ ý¦¡§@Öw²ñI±Dûµ£øY1¼CÊv@Eßs7û~Y8è¯ïØæ¹¼³Lý$¾;ÉŸëâ ïâî/5c¥@2óÌäð «Þ1W\sΗK°xÿýTJ!ÍË .Œ¤zT¾OöVÖ\/ž¡Ü 7j¸Õ›±T UôÍÓ¨ú@b"¡„y~ü'(ÏPêAU¾§¢.s]>ÝÂ]EÅ64íQó=!0à7%«·æY}ëÔY–f9îüÀúqòC’žb endstream endobj 2225 0 obj [ 2224 0 R 2226 0 R 2227 0 R 2228 0 R 2229 0 R 2230 0 R ] endobj 2223 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 2225 0 R /Contents 2231 0 R >> endobj 2232 0 obj 1568 endobj 1257 0 obj << /Type /Action /S /GoTo /D [2233 0 R /XYZ 72.0 720.0 null] >> endobj 2234 0 obj << /Type /Annot /Subtype /Link /Rect [ 245.76 564.293 290.49 573.173 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 2148 0 R /H /I >> endobj 2236 0 obj << /Type /Annot /Subtype /Link /Rect [ 245.76 564.173 290.49 573.173 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 2148 0 R /H /I >> endobj 2237 0 obj << /Type /Annot /Subtype /Link /Rect [ 187.72 523.547 250.77 532.427 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1798 0 R /H /I >> endobj 2238 0 obj << /Type /Annot /Subtype /Link /Rect [ 187.72 523.427 250.77 532.427 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1798 0 R /H /I >> endobj 2239 0 obj << /Type /Annot /Subtype /Link /Rect [ 131.751 462.065 177.402 470.945 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 2148 0 R /H /I >> endobj 2240 0 obj << /Type /Annot /Subtype /Link /Rect [ 131.751 461.945 177.402 470.945 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 2148 0 R /H /I >> endobj 2241 0 obj << /Length 2242 0 R /Filter /FlateDecode >> stream xœÅXËrÛ6Ýë+0^4¶ÇBñ"Ad&º‰“I'iêXI¶4EYl)R!);þû^I‘•n\g&ÂëÜ..ømBSý#CÑjòÍŽQ$â¾ò|DfZ!ÛöPªWulÛ‚³Kô×$›ônr} “sDð8!}q5øjrÙѯgȳëïZÀ)û_,¸ÜÝÉ$îíMæf FŒ =•Ú°Ù_#Õ4qæw¯Q¤µ‰¸ƒbÍ}>åÝO~›M~~ë!JÐlÑ’Vj %8`Jÿ14[¡ëcªü“[4û}r1ìæ3Gm°‘ZwãG66 „зêÍ•Ö)ãÓá*6N9 Ä&¾§×ðåÏ7糋éç‹×Ÿ>¿™¾ýüéãôêçÙ2R,U ó@¹J¹aLöŒŒЗõ<¬bÿ…wa£E‘¯P™æU‰òzHâG¥a ½»¿ã¨Â[§¤Ã)A1Q„ûFøb“EU’g[Ìþøù {Œ”ÔÆ¯|ʪðû¨Ê(#H<pëKý×s?Ž•›ÚéiGy1Ÿj—§µËýÐ1§š­U`SÏ,Æ]ÚLäöúÂ$ùZ¤ïtp(áÄ…A?ý?hâ‚9P[®ìW¦œ½úfå@"B ‘ÄRô¼¸ß¬â fsô5L7q¹ßdÍ cßóM~àÚÁy¤:8Ðy†’¬¬Â,ŠõQãý^r,õ©uúªÑk}ˆöZÀh€…‚pxB9$àq¥ÀD'Ÿ@.¸Ý`ÎQš”•öT£Q ¬„Œ°ò6ö´ÛÒs <tÆÙú€ËJ`a›”n¯°ó‘]¥–LS”±…è¹d€¥1‚I‡ŒfˤDIš¢y¼7i…ªUË=hªë 9µÓ­ÎS|ø 1F1cÀ)®¨Qõ&.£"Yw3²ój0l6wS.Kt‚ô:ÖÆmÛµ‘íTYåEø:T8‘ð¢C£; ¿¾ ;Ïœ·ýD¥>^]#Q‡Äƒ”¾Ãÿ@át–î¿Àtñ=\­Óxÿcv‹CÍ”eœZU7ÇeœBðÐ5Ü‘ÕTW·è:^…Iz‹^ÖT‚Þ:ÍŸb˜xù›£ëWf0™ß"ª—%q:ŸšŠ"KÒ›“!O8»šá]tê>ÄY’¡£TÿþZæðø®p^ÜÝœ8I9pXõè4¦§ 3‚fãÖ‹­ñ]Û5—§¦Îlç_ìx”†ÕUÚ§zszê‡k¡Ã˜·ÔF¿h‚ïÒ&h×@››c5ëGÚ¡¯Þ`§.Þ¯Ö5ØPôC¢÷ Z qoÑÑû‡0ÁÑòÈißž¶§Å8ÒÅq·!6 èè'[‘»tÈLÞ'ÀWCþîû0c­¼9®íD°¹ 󈃔ŽeLGÔW’ùþóæóžæmh÷sd+œ"…×Ùý6–@= ®‚:S‹¼J ¢¼X, #Ð ¯Ù@èo‹Ä~Êý˜ÏM¬ïЫËÍwÅHä>l‡/… ¤´Ïkàº{3Ãs7¤Vûõn]¸dqç³òåä_ií endstream endobj 2235 0 obj [ 2234 0 R 2236 0 R 2237 0 R 2238 0 R 2239 0 R 2240 0 R ] endobj 2233 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 2235 0 R /Contents 2241 0 R >> endobj 2242 0 obj 1651 endobj 1288 0 obj << /Type /Action /S /GoTo /D [2243 0 R /XYZ 72.0 720.0 null] >> endobj 2244 0 obj << /Type /Annot /Subtype /Link /Rect [ 245.76 557.675 290.49 566.555 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 2148 0 R /H /I >> endobj 2246 0 obj << /Type /Annot /Subtype /Link /Rect [ 245.76 557.555 290.49 566.555 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 2148 0 R /H /I >> endobj 2247 0 obj << /Type /Annot /Subtype /Link /Rect [ 187.72 535.096 250.77 543.976 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1798 0 R /H /I >> endobj 2248 0 obj << /Type /Annot /Subtype /Link /Rect [ 187.72 534.976 250.77 543.976 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1798 0 R /H /I >> endobj 2249 0 obj << /Type /Annot /Subtype /Link /Rect [ 242.265 481.202 287.282 490.082 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 2148 0 R /H /I >> endobj 2250 0 obj << /Type /Annot /Subtype /Link /Rect [ 242.265 481.082 287.282 490.082 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 2148 0 R /H /I >> endobj 2251 0 obj << /Length 2252 0 R /Filter /FlateDecode >> stream xœÅXÛnÛF}×W R qŒˆÝû’AÔ‰•"AnŽ•…íZ¢,&©”£è¿w–7Éä’rûJ°µ¼ÌÌ™3³³³ûmDàwl~´Ç`¶}«îQÐ ¸ªnIT8L ª±„ȼµ3`õÊ—p°„?FñˆÀ |8‚7#ÒVWŸŽNvì›'ä‡ÛßEÀ)û_œÜ‚fÚiŦæå=¼S*2¢Š¶ê·ÔZKpåo/(²ÅDì¤TpœqW£çÓÑ//%PÓÅ6iµ¤Äq™g> ¦+8; žû覯G“i'š?˜µN íÆëBè·Šàêʩҧwþ*(²Ð \`žC”4ﻥÀ§ÇGÓÉøÕ»ÓéÑ»“ñËïߎ?N^¼ÿx| ¥¦Fž1î¸ÜÀpyWÓ9cº-À‡àÓzîçdQ’õm‚ i²¼ë_úYàÔžh‹'‚:Ä#¨M•Ú^nâY&q-ÓOšòI]ÏÓ´"íô6Îýïµ g1F‰r¥„pJ+ðŧå¯+,on /Çaœå~< ÆÆÅqÌ’tžµù’ÌfªF†¸ZИ´aK.¿³¼×æÙ`ÂÏ_ƒÛSœ‹Tª^c\[Ù{ú î¢Èq.Q“\ð*qŽÒ«Í*ˆó üxŸ‹Ìén§p¶iáyܳ1Ô™(¸+sCCHà7\©Ž¸æŽ6™.$íêù7ð"ò³¬×>£®#<äB ¯«ÀöÕeŽ+’íõÄÈînGìhÀA*ÍL¬0ûhÖ®£5ªL[Ô80]†Ü„Qó`áo¢òòePV …ÃêÁ¸¶yèìÏ(F©ãº ÈŠÒã ›¥áz·~X«'Wލ²Î㲂eðÆ }®¹( [sUU¸æÑÛÅò 3Aa&˜Tè`)òªQ²/Á$RC±*‹W[-MÂwÀÙjwSXÞ-àöds=”Õ„ ª†ðl²0¾ê¡ÍÏó4¼ÜäÁ Ü_¯Ód†ÌVI6Qî]<˜i‘v±G(u£~j\â(‚L™e°­mÿôDŒýâµõ›e8[ÖÕ¬Èêkœ6õhÙ o¦iu “Ì óFg˜/÷{ÇqžqÁ®‡á=øæZ;’3,O¸Ôý[D‚òáFÃm\Lòǖ®…ö\‰-B¡§¢Yp“~Ïå…ߌê=nîô.³”3ì®p‰JX¬uËdÿTdH“Ó`y„qsaJ]¶u! šqÙþl}ÅÚŒëò²•,fS9,3µÏL5Û¾´µ[d½…oÍZ¸¶/1nåÏ0Mè*|÷X68¡¸\™þUWÈ仿ZGÛæÃÖ:r޳W›RKtÕ(›éyí§pÐC8?˜áðü "ÌJx Æä6àÉÍ2@ŒgOá̰;.×¼íóbÎ/€^À“EäçkÈÏ™o—.I 6`‡4oyW±àh´í‡‘Õ’]K¢ ãß²ä: r'I¯X]Õ1[µÎU³ gµï6Ø^›gh}žø×㵦<> endobj 2252 0 obj 1477 endobj 1285 0 obj << /Type /Action /S /GoTo /D [2253 0 R /XYZ 72.0 720.0 null] >> endobj 2254 0 obj << /Type /Annot /Subtype /Link /Rect [ 245.76 562.187 290.49 571.067 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 2148 0 R /H /I >> endobj 2256 0 obj << /Type /Annot /Subtype /Link /Rect [ 245.76 562.067 290.49 571.067 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 2148 0 R /H /I >> endobj 2257 0 obj << /Type /Annot /Subtype /Link /Rect [ 187.72 520.037 250.77 528.917 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1798 0 R /H /I >> endobj 2258 0 obj << /Type /Annot /Subtype /Link /Rect [ 187.72 519.917 250.77 528.917 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 1798 0 R /H /I >> endobj 2259 0 obj << /Type /Annot /Subtype /Link /Rect [ 418.057 469.151 463.934 478.031 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 2148 0 R /H /I >> endobj 2260 0 obj << /Type /Annot /Subtype /Link /Rect [ 418.057 469.031 463.934 478.031 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 2148 0 R /H /I >> endobj 2261 0 obj << /Length 2262 0 R /Filter /FlateDecode >> stream xœÅXÝoÛ6÷_qè€5 jŽ_Åb-–6n"]šÚí0$yPl9Q'K®$' †ýï;J²äH”졳DQ¼»ß}òÈo#ÿcóPšÃ|5úVÍ1P„[M9.0I¸+¨ÆDfÕ΀oGø(áàþÅ# ïFç—øq îF´Í® žŽÎvä›/ô‡ËßE ÿ_œ=ô‚⊴|SP‹rgJFæST™­z–\Ëa ®|ö‚¢ &j7J÷Ç §p=z=ýòÖFa¶l‚VBF‰Çµùq˜­àü€SúìfïG“YÇ›?ØjGÙµ>:Ö£”²jÎU•R¥N¿û« TÊbéׄºŽY?Í&ãéÉélüöÓé‡ñ§É›ÓOÇP2©I™Ä'ºL.8W-N‡àózáç$W_ƒyžA%9,Ód8í_ùY@¶Z(‹’ª)²sKvo7ñ<“xKÓo0W‡yZ+Vlzçþ÷-¡¶cTM]¤q·è‹_KaOZVn 5ÇF½±Qoœó$]´mŹMÊBj¡âÜ«4f¯*ܵ!’¢¨…ÀèÒ/C[eüüWp? H› m$ô Êꜗ¯à¡%ÒGp"©Ä°TõQz½Y1†¤/à‹m‚¬¸‰Ç!Ê5.µÍ $dÔµÅÆYîÇsLŠ%øµµÜ½D™\’³0úwð&ò³¬g‘i$êr Ãú*óZ¡Á¥ì„]ÛÉì&€+U©j‘üa< ¦úp†]Å,ìöXœcù Þ£¯VD3,±RôÄ¥]çÙÑ€Kú€›ø4… W ì‹,奌'¹²°!0» 3¸ £ÁÒßD9ä äè‹[çÆ‡Õ‡ñVæ!ÙŸEœ;DJ,Ç’Wõø8Èæi¸Þ-ÉÖÍH"`ÕØÑªÚŠz™Á3\aö680ðš·"Tš×÷óÝïë`.Ã`±3wußËîÍÉé´Ÿ{¡Íë@¡ô<³¿QÊ1¦ºJ &6C´»Ê¡úé -!]B ׳±/ªÅŽ=ë†ÐŒh!´¦Vßíð©KÙc¬'²5œ86f]¶{‚Þ@q)ÒhÊÕ¶›…ñ5 Ç«2”ùyž†W›|û^DOV½Æm­_¯Ód†~M9m‚¸p$ñ”¨4ë Ü[HåCô•ü»›p~S«ôÝ*…éÝVª.&•ŽY–̆ížÄØUñ–Ä»07’Æ.aCz» ®ÜÂdïþ(‡¨kñIú¼‡ËG bÜ#ÚÅÍÞò?Àråu%«‡qYMŠqcçzê1ýz´uÐóŽJÝãÃÑN¹ot1u‹yááh€©±¼OÌF]½˜ÂÖ¨ë§%†<ÙÎÍ¢Ä/±ny2³÷˜›I eP›©¯F"Zuå/@`ÌZ1yÄædê«àØ :žS˜|÷Wë¨iël=¿Š(Vy»<â˜ÜºõS8 Ø!\Ìqxq < crðâî&@Œç/á¼hú˵ù^ŒÂÅ%°Kx±Œü| ùÅ3óïÚN8º[ÛÃ Š·¬U¬x@eûad•䉮¤'Q‡ñoYr9IÒë'BítÄVgžò¤“ÁùV÷K lIÛv†Öï…;^ûašÁÓ d~^èp OnIžÝŠ’µ­ØÑø¬ñŽ••hÍdY&ÛÖ¼è;îsŒtÚöE‰?ý:ùðñäôÏÉþ–u_;âøŸWb·Ä ©,Ñg3»…T·í´{bÊV‡™V]`ªvÿiˆY?Y.Í-ÁPàH,…ŠjOxÕ1æC²0`V‘¢³«»\3S–ûGäJ¨éH4­îŽ 8¦„Ý×÷GÍõã9Äh0_õÜGQÀòÁ]Ô1–hsšž´¯@ŠÛ©=÷@.§D{R{ލ«Ü<(p?‚i˜o|34¡+ÍÆ‹¶WŽ×€*z… M“4ÛÅs6ú a endstream endobj 2255 0 obj [ 2254 0 R 2256 0 R 2257 0 R 2258 0 R 2259 0 R 2260 0 R ] endobj 2253 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 2255 0 R /Contents 2261 0 R >> endobj 2262 0 obj 1507 endobj 1299 0 obj << /Type /Action /S /GoTo /D [2263 0 R /XYZ 72.0 720.0 null] >> endobj 2264 0 obj << /Type /Annot /Subtype /Link /Rect [ 282.21 556.052 326.94 564.932 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 2148 0 R /H /I >> endobj 2266 0 obj << /Type /Annot /Subtype /Link /Rect [ 282.21 555.932 326.94 564.932 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 2148 0 R /H /I >> endobj 2267 0 obj << /Type /Annot /Subtype /Link /Rect [ 282.21 394.212 326.94 403.092 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 2148 0 R /H /I >> endobj 2268 0 obj << /Type /Annot /Subtype /Link /Rect [ 282.21 394.092 326.94 403.092 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 2148 0 R /H /I >> endobj 2269 0 obj << /Type /Annot /Subtype /Link /Rect [ 180.874 280.116 225.246 288.996 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 2148 0 R /H /I >> endobj 2270 0 obj << /Type /Annot /Subtype /Link /Rect [ 180.874 279.996 225.246 288.996 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 2148 0 R /H /I >> endobj 2271 0 obj << /Length 2272 0 R /Filter /FlateDecode >> stream xœÅX[oÛ6~÷¯ 0`M‚H#©{°HšthQ´ëì¶M±Ò2«ÓÅ•ä\6ì¿ï"%Y¢Ü:)žÛÇs>Rþ<#ß%¾‚ˆ¢8›}Vs9¾šò|D\›z(CJöP*Võª%øj°Aïfù £Ÿgï?Ààp7ÃCsRy>{Ýó/žàoî¿CèÿÁëý]h`öFj;ÍÌ4†Ä£TÁ¦¾«Ø×|O…»˜°î·sŽÑÍìb1ûᩇF‹uW´P$Øi$>-2ôþˆbzü-žÏ®£Ýüƨ6Rønóq 1Æd/-¹¹JªÉé%Ëx“”7D4²±ï‰õa£ðæ—ËóÅ•õêâùÕ“ÅÜzþêÙË9j,´zÄ÷mì{{c ×”C…àz³]±šWèS‘ä|…ª´¨+T¬Q±üÄ㺲u!—Ø8Â`ÌoŒ=Ýåq¹Ö™ÆÊl„Q…Õü!¯Ù½VŒ ÎöíÈ£‡«c—ŸAº¡kX¹“IZ*'KäZ ô(6)"Ä3‰Ê©¡‚r1™õ¨ÉÍ÷¿ó‡C¾BSþr¯&=9Ĉٴ‡šXeÌ­í´ßÿJ7 8eUe彎×€c„nÚ“ë˜Èؽ•òü@©™öýô}¹¬‰ãÛnäF‘G¯—7»ŒçÐS,_¡·,Ýñê@İOì0 À„± Fþ¡l×â@݈/y—ɶ)6½ ¸@¡ãb↪côµ'”ØQ‡ƒ*¨Õ¨äqQ®ú˘‹Ùv[ÛR•Ýl‹YO-Ó½öíȃ¨6‡Eo¼åq²NïnnùÐÌ_¼ZÌ{ã=kã­89Á§j·…³JúpCt$¹O$8I~Ž÷0Üåy’ü´‘Ã$H<Ǧ®$H †Z#+ëõÂg·ç­T%Ù6•ÍÓŒ3^oŠ•)Á˜íª†Kš1k%±O–<|õŒlµF\òV,¹h¼>˜Éð-Iì 2“Ö(–áòº•“Nì­ØåËb—¯N»gÀ`í@†Pm°–äv;\4Ö Öêųذî!_¯á2Ã󸡦ºw^òv$Ñê¨I9ï-¨6l|ƒÀˆkï0,+ä†ÛÕ½#ÅÊüG=qÝP^Ò­Ü£Ä~@§=ky»¶®Y¼Iö\eíîÙ%©7 -q&I]ʲ˜&c½>þ0¡‘º ^Ý3QÀÓ¯©œG¡¡©*Ú”ø[V¢¶Z•âTªNàV_ñBAô-Úâ`»xàÜRËа /- ™÷œý& Š©gÉê:[§¬–¿>ÖÙìÅáâAðÒwr~yùëÕ|~5?1hxt¹h4KÖøBŽ÷“€’GjdŒÀwÇ´7½•?òlú•cß¹ÁN8ľ}Ñí/RûOõÉ8p»0¬£C@”ß[ñ&ýõn!jàö»Õ£?áÝÿ?%—=6ý´$ ¸C¸ú?BÉß._Ïþ¨ážd endstream endobj 2265 0 obj [ 2264 0 R 2266 0 R 2267 0 R 2268 0 R 2269 0 R 2270 0 R ] endobj 2263 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 2265 0 R /Contents 2271 0 R >> endobj 2272 0 obj 1683 endobj 1828 0 obj << /Type /Action /S /GoTo /D [2273 0 R /XYZ 72.0 556.12 null] >> endobj 1831 0 obj << /Type /Action /S /GoTo /D [2273 0 R /XYZ 72.0 207.984 null] >> endobj 1834 0 obj << /Type /Action /S /GoTo /D [2273 0 R /XYZ 72.0 172.981 null] >> endobj 2274 0 obj << /Type /Annot /Subtype /Link /Rect [ 130.0 477.244 190.0 486.244 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 675 0 R /H /I >> endobj 2276 0 obj << /Type /Action /S /GoTo /D [2144 0 R /XYZ 72.0 720.0 null] >> endobj 2277 0 obj << /Type /Annot /Subtype /Link /Rect [ 130.0 455.244 152.22 464.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 2276 0 R /H /I >> endobj 2278 0 obj << /Type /Annot /Subtype /Link /Rect [ 130.0 455.124 152.22 464.124 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 2276 0 R /H /I >> endobj 2279 0 obj << /Type /Annot /Subtype /Link /Rect [ 291.493 433.004 363.493 442.004 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 576 0 R /H /I >> endobj 2280 0 obj << /Type /Annot /Subtype /Link /Rect [ 430.82 337.364 466.82 346.364 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 909 0 R /H /I >> endobj 2281 0 obj << /URI (http://odbc.postgresql.org) /S /URI >> endobj 2282 0 obj << /Type /Annot /Subtype /Link /Rect [ 382.539 97.505 428.495 106.505 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 2281 0 R /H /I >> endobj 2283 0 obj << /Type /Annot /Subtype /Link /Rect [ 433.891 97.505 536.671 106.505 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 2281 0 R /H /I >> endobj 2284 0 obj << /URI (http://www.mysql.com/products/connector/odbc/) /S /URI >> endobj 2285 0 obj << /Type /Annot /Subtype /Link /Rect [ 247.79 85.505 291.12 94.505 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 2284 0 R /H /I >> endobj 2286 0 obj << /Type /Annot /Subtype /Link /Rect [ 297.79 85.505 494.45 94.505 ] /C [ 0 0 0 ] /Border [ 0 0 0 ] /A 2284 0 R /H /I >> endobj 2287 0 obj << /Length 2288 0 R /Filter /FlateDecode >> stream xœÅYKoÜ6¾ï¯à­Ó|é•[S7EŠ8‰a=$A¡•h¯­¸–´Ù,Ðß¡H=)) ¤Éa9çÁo†3CúiCÿ—ú'ˆJö›';GQÀ÷í”ç#*0óÐÙ±‡r½j0`í~Ì"ìЛbCÐo›ŸácŠ0œ6d*®a¾ÛÜôë/ä‡ë'èqóò~sõÊC” û‡"`N#øçG(Äœé!`v¿G/®ã:ÞÆ•D/ãäË¥,ÒêÙgtÿûæ×ûÑ–8eÿÖnG6€[à‰³nnæ`ÆÒŸrëûk¤š¡1Îü.Ez›ÈФ±Ÿ¨òeš‘ŽœËx¸èÍŒšãH­»Û׿ˆÑŽ`!ÓaKaÂÆª¬’2;Ô™*z@‰* ™hê²:ÈÄìôê 3G„ˆ{8h ñ¬¬ªê–ÃA“ß師ˬxDÏÐ%| ÑE)¥¬dQfëì ­¤ˆ÷ƒUöã×ïûqœ¦ ¬Zss¾»}Ó“•,¿ÊrhI•¥rÀ¬Šçó*‹,¨Pý8+. # D0Á Í’¸–H—«$Îõñ*ð~„CBXÛUØõöÚZƒ+D§mƒÀд6hc†ëfFG„eöèAƪ¡GÁfÖúÕZIOµ‘bªÑºžxPžøA¸%³^7†‹¬×¿#wdYr,KÛO|(²o3B Ÿ½¾^‡›2“PW$n#ëWÕI•é*æ.[:cØw07“fcf|,d‘”çC-Ón®UÝ3¨~}ÕóàÍØÅÝÌ–ÔÍ8{˜µÆH™;y”‡“¶ºà$$ÚØ]\¡¸@r¨Ï¨ÛÂC&óô;Øû˜)¸Ì¨Å^•ë¹ÐeY:•Z”>w7W¢öûcÑš~Êê]³Ì$4sL;k¡@uu0M+Aâ 䄈À7úߪZVF·z0FN<ÃóêúúÍâ6& ˆ…äž6Ý}bÌk9¢)‡7Ç‘–êp™©ü¶ (c(ŸŽ€‰bÉ,—Å-¤2¨lx5íÁ{H~‘çÆß‡¸„¬Qw(Žöã3PÂ}ÏÝ?·‡ãk&OÕâVB f¿Ë‹âÒ´ªQu<踀=lÏÆõsÖ†º/ à ˜Z;²ÑYwoŒ‹uUÜ4U;Ùbeɸ|<îmn]BÔ£EW3aA%ôõF’RBU¼lܶˆƒ‚!"N(U®ŒÖ(Xu©òÎøÓN‚ÏË–TÝHÛî À˜ÒíÕD’%²jÍÈŸ9åuQ¨ë—6 O»,Ùµ.¬Ðà/râHø„ ç Õ:ˬ#¡›‘êT˜-zà@31t¡™1N´ã¡,}è{êáXô±a§Ô@SžUm¹¶šŠZH9ã¯#Þ® éfÔö/è=ºæ<À9C‘=ª”)^ÍnÜ 0ñ Qb~Øf·›ÕìÆá° ߇|(تkœuïËL5Í$ëJ§qés›ÂSkpÆQAüUÇíÓQ–|Í "D´öÑÒ ã^q©$àlÆ„Jæ€äâö¸†w™{JA|ìA¡€$Ö·ó~«ò,Az‡w碎—³9 +X„#Ì™àkȺë0lx )øØ×µ˜øtFäß/¨¢+œºWÖÝ}ajµ:È2®U‰Ñ‡jŨ®Ø£PÈ"2'ÔÈ\vœ kÜ;Mq:“h„Ç0…ržSÜF ;ëþ;èŽHˆöª^¾.0¸É®pÿ[¨YÚ#J¢hÑÈOËh3oMÀÚ€JI ÷*Úκÿ޶#2+ ß©Öòƒœº"5Y}f¸ðè›ÆÑe–ßyXQÂò2ÔÓhNu%këï… * "s¨$\O&ÓeÝAèaŽ.>]´Ùº›˜ô„-l†ÈáØ—Ÿžõ¿:ʶ†h=ØOt÷^Cw=‡U”gPÒŽEn_:ìúÝ`uÿ´aè¬*ŠKÛÛ˜ Ý»Èx$#óóÛ»×Þ~xwÿë‚ìÖ ‹+ƒë-÷'5Áㆃaøß]¿üåûwNg"܆m'õ&Û–±.kÅÃÓ~dÃêcZ!ŸcŠÕ±µ/´ÝDweh'â$1вiŠì—b^fZfoCîã"~Ðq/ì$ó|n~F\ÿÑ4HÖšÁ¾ŽpC*óóôæ«ß‹´÷Fx˜àò"ý 1è±Ì„½Bvôâ톲‡"ÐoYÁŒ’_ÞÀéY®œÐm…žÎœpÿu™;í»3ÞJYtDmº¢–l®r-×ãoD31"®[ò¦s¡ ­ƒœù›,)U¥꟦ݧ†Â¼«]ph”ÚxÀÝgƒ¾¡ºè­®º‰]üµ_l1Dˆ!- öÛ®gšXÌ)Ü›yŽþŒí¶™0àºCvoJ +àP=åÃãî–Pχ[äw²5>N ÷)†&'Š(,uùvu}xqu¥Òm‚ªªáT?åX•S—ùû‰ôÓÐŒœÏ3æl²¨óÚe(º;Œ¾7šÛ:"ú*!ú4í:…´AœE3êÆ\sG3ˆ0åRE8gîÍyÕ#únNõ_·,jŸ:ŠêšÑÖ!§Ó ïÏÚ‰Ú_J•áBwe_•UÙxìj :cXxÄHsE;>Ò–èÄsÛo7àxmÆÕB8Øõ-Í߀n7ÿ ‰Þ± endstream endobj 2275 0 obj [ 2274 0 R 2277 0 R 2278 0 R 2279 0 R 2280 0 R 2282 0 R 2283 0 R 2285 0 R 2286 0 R ] endobj 2273 0 obj << /Resources 3 0 R /Type /Page /MediaBox [0 0 612 792] /CropBox [0 0 612 792] /BleedBox [0 0 612 792] /TrimBox [0 0 612 792] /Parent 1 0 R /Annots 2275 0 R /Contents 2287 0 R >> endobj 2288 0 obj 2038 endobj 2289 0 obj << /Type /Action /S /GoTo /D [8 0 R /XYZ 72.0 720.0 null] >> endobj 2290 0 obj << /Type /Action /S /GoTo /D [23 0 R /XYZ 72.0 720.0 null] >> endobj 2291 0 obj << /Type /Action /S /GoTo /D [23 0 R /XYZ 72.0 657.113 null] >> endobj 2292 0 obj << /Type /Action /S /GoTo /D [1632 0 R /XYZ 72.0 118.883 null] >> endobj 2293 0 obj << /Type /Action /S /GoTo /D [1641 0 R /XYZ 72.0 696.0 null] >> endobj 2294 0 obj << /Type /Action /S /GoTo /D [1641 0 R /XYZ 72.0 130.562 null] >> endobj 2295 0 obj << /Type /Action /S /GoTo /D [1772 0 R /XYZ 72.0 708.0 null] >> endobj 2296 0 obj << /Type /Action /S /GoTo /D [1772 0 R /XYZ 72.0 119.854 null] >> endobj 2297 0 obj << /Type /Action /S /GoTo /D [2273 0 R /XYZ 72.0 720.0 null] >> endobj 2298 0 obj << /Type /Action /S /GoTo /D [2273 0 R /XYZ 72.0 525.264 null] >> endobj 2299 0 obj << /Type /Action /S /GoTo /D [2273 0 R /XYZ 72.0 385.384 null] >> endobj 2300 0 obj << /Type /Action /S /GoTo /D [2273 0 R /XYZ 72.0 335.864 null] >> endobj 2301 0 obj << /Type /Action /S /GoTo /D [1775 0 R /XYZ 72.0 576.832 null] >> endobj 2302 0 obj << /Type /Action /S /GoTo /D [1775 0 R /XYZ 72.0 526.704 null] >> endobj 2303 0 obj << /Type /Action /S /GoTo /D [1775 0 R /XYZ 72.0 366.144 null] >> endobj 2304 0 obj << /Type /Action /S /GoTo /D [1778 0 R /XYZ 72.0 466.496 null] >> endobj 2305 0 obj << /Type /Action /S /GoTo /D [1778 0 R /XYZ 72.0 393.098 null] >> endobj 2306 0 obj << /Type /Action /S /GoTo /D [1781 0 R /XYZ 72.0 643.83 null] >> endobj 2307 0 obj << /Type /Action /S /GoTo /D [1781 0 R /XYZ 72.0 595.116 null] >> endobj 2308 0 obj << /Type /Action /S /GoTo /D [1781 0 R /XYZ 72.0 515.949 null] >> endobj 2309 0 obj << /Type /Action /S /GoTo /D [1781 0 R /XYZ 72.0 421.518 null] >> endobj 2310 0 obj << /Type /Action /S /GoTo /D [1781 0 R /XYZ 72.0 339.087 null] >> endobj 2311 0 obj << /Type /Action /S /GoTo /D [1786 0 R /XYZ 72.0 699.264 null] >> endobj 2312 0 obj << /Type /Action /S /GoTo /D [1786 0 R /XYZ 72.0 651.06 null] >> endobj 2313 0 obj << /Type /Action /S /GoTo /D [1786 0 R /XYZ 72.0 469.734 null] >> endobj 2314 0 obj << /Type /Action /S /GoTo /D [1786 0 R /XYZ 72.0 376.068 null] >> endobj 2315 0 obj << /Type /Action /S /GoTo /D [1786 0 R /XYZ 72.0 294.402 null] >> endobj 2316 0 obj << /Type /Action /S /GoTo /D [1791 0 R /XYZ 72.0 520.528 null] >> endobj 2317 0 obj << /Type /Action /S /GoTo /D [1791 0 R /XYZ 72.0 471.248 null] >> endobj 2318 0 obj << /Type /Action /S /GoTo /D [1791 0 R /XYZ 72.0 335.232 null] >> endobj 2319 0 obj << /Type /Action /S /GoTo /D [1791 0 R /XYZ 72.0 241.952 null] >> endobj 2321 0 obj << /Title (CLSQL Users' Guide) /Parent 2320 0 R /Next 2323 0 R /A 2289 0 R >> endobj 2322 0 obj << /Type /Action /S /GoTo /D [307 0 R /XYZ 72.0 720.0 null] >> endobj 2323 0 obj << /Title (Table of Contents) /Parent 2320 0 R /Prev 2321 0 R /Next 2324 0 R /A 2322 0 R >> endobj 2324 0 obj << /Title (Preface) /Parent 2320 0 R /Prev 2323 0 R /Next 2325 0 R /A 308 0 R >> endobj 2325 0 obj << /Title /Parent 2320 0 R /Prev 2324 0 R /Next 2343 0 R /First 2326 0 R /Last 2334 0 R /Count -17 /A 312 0 R >> endobj 2326 0 obj << /Title (Purpose) /Parent 2325 0 R /Next 2327 0 R /A 315 0 R >> endobj 2327 0 obj << /Title (History) /Parent 2325 0 R /Prev 2326 0 R /Next 2328 0 R /A 318 0 R >> endobj 2328 0 obj << /Title (Prerequisites) /Parent 2325 0 R /Prev 2327 0 R /Next 2334 0 R /First 2329 0 R /Last 2333 0 R /Count -5 /A 321 0 R >> endobj 2329 0 obj << /Title (ASDF) /Parent 2328 0 R /Next 2330 0 R /A 324 0 R >> endobj 2330 0 obj << /Title (UFFI) /Parent 2328 0 R /Prev 2329 0 R /Next 2331 0 R /A 327 0 R >> endobj 2331 0 obj << /Title (MD5) /Parent 2328 0 R /Prev 2330 0 R /Next 2332 0 R /A 330 0 R >> endobj 2332 0 obj << /Title (Supported Common Lisp Implementation) /Parent 2328 0 R /Prev 2331 0 R /Next 2333 0 R /A 333 0 R >> endobj 2333 0 obj << /Title (Supported SQL Implementation) /Parent 2328 0 R /Prev 2332 0 R /A 336 0 R >> endobj 2334 0 obj << /Title (Installation) /Parent 2325 0 R /Prev 2328 0 R /First 2335 0 R /Last 2342 0 R /Count -8 /A 339 0 R >> endobj 2335 0 obj << /Title (Ensure ASDF is loaded) /Parent 2334 0 R /Next 2336 0 R /A 342 0 R >> endobj 2336 0 obj << /Title (Build C helper libraries) /Parent 2334 0 R /Prev 2335 0 R /Next 2339 0 R /First 2337 0 R /Last 2338 0 R /Count -2 /A 345 0 R >> endobj 2337 0 obj << /Title (Microsoft Windows) /Parent 2336 0 R /Next 2338 0 R /A 2290 0 R >> endobj 2338 0 obj << /Title (UNIX) /Parent 2336 0 R /Prev 2337 0 R /A 2291 0 R >> endobj 2339 0 obj << /Title (Add UFFI path) /Parent 2334 0 R /Prev 2336 0 R /Next 2340 0 R /A 348 0 R >> endobj 2340 0 obj << /Title (Add MD5 path) /Parent 2334 0 R /Prev 2339 0 R /Next 2341 0 R /A 351 0 R >> endobj 2341 0 obj << /Title (Add CLSQL path and load module) /Parent 2334 0 R /Prev 2340 0 R /Next 2342 0 R /A 354 0 R >> endobj 2342 0 obj << /Title (Run test suite \(optional\)) /Parent 2334 0 R /Prev 2341 0 R /A 357 0 R >> endobj 2343 0 obj << /Title /Parent 2320 0 R /Prev 2325 0 R /Next 2351 0 R /First 2344 0 R /Last 2350 0 R /Count -7 /A 360 0 R >> endobj 2344 0 obj << /Title (Introduction) /Parent 2343 0 R /Next 2345 0 R /A 363 0 R >> endobj 2345 0 obj << /Title (Data Modeling with CLSQL) /Parent 2343 0 R /Prev 2344 0 R /Next 2346 0 R /A 366 0 R >> endobj 2346 0 obj << /Title (Class Relations) /Parent 2343 0 R /Prev 2345 0 R /Next 2347 0 R /A 369 0 R >> endobj 2347 0 obj << /Title (Object Creation) /Parent 2343 0 R /Prev 2346 0 R /Next 2348 0 R /A 372 0 R >> endobj 2348 0 obj << /Title (Finding Objects) /Parent 2343 0 R /Prev 2347 0 R /Next 2349 0 R /A 375 0 R >> endobj 2349 0 obj << /Title (Deleting Objects) /Parent 2343 0 R /Prev 2348 0 R /Next 2350 0 R /A 378 0 R >> endobj 2350 0 obj << /Title (Conclusion) /Parent 2343 0 R /Prev 2349 0 R /A 381 0 R >> endobj 2351 0 obj << /Title (Connection and Initialisation) /Parent 2320 0 R /Prev 2343 0 R /Next 2375 0 R /First 2352 0 R /Last 2374 0 R /Count -23 /A 384 0 R >> endobj 2352 0 obj << /Title (DATABASE) /Parent 2351 0 R /Next 2353 0 R /A 387 0 R >> endobj 2353 0 obj << /Title (*CONNECT-IF-EXISTS*) /Parent 2351 0 R /Prev 2352 0 R /Next 2354 0 R /A 90 0 R >> endobj 2354 0 obj << /Title (*DB-POOL-MAX-FREE-CONNECTIONS*) /Parent 2351 0 R /Prev 2353 0 R /Next 2355 0 R /A 113 0 R >> endobj 2355 0 obj << /Title (*DEFAULT-DATABASE*) /Parent 2351 0 R /Prev 2354 0 R /Next 2356 0 R /A 139 0 R >> endobj 2356 0 obj << /Title (*DEFAULT-DATABASE-TYPE*) /Parent 2351 0 R /Prev 2355 0 R /Next 2357 0 R /A 87 0 R >> endobj 2357 0 obj << /Title (*INITIALIZED-DATABASE-TYPES*) /Parent 2351 0 R /Prev 2356 0 R /Next 2358 0 R /A 166 0 R >> endobj 2358 0 obj << /Title (CONNECT) /Parent 2351 0 R /Prev 2357 0 R /Next 2359 0 R /A 79 0 R >> endobj 2359 0 obj << /Title (CONNECTED-DATABASES) /Parent 2351 0 R /Prev 2358 0 R /Next 2360 0 R /A 109 0 R >> endobj 2360 0 obj << /Title (DATABASE-NAME) /Parent 2351 0 R /Prev 2359 0 R /Next 2361 0 R /A 229 0 R >> endobj 2361 0 obj << /Title (DATABASE-NAME-FROM-SPEC) /Parent 2351 0 R /Prev 2360 0 R /Next 2362 0 R /A 207 0 R >> endobj 2362 0 obj << /Title (DATABASE-TYPE) /Parent 2351 0 R /Prev 2361 0 R /Next 2363 0 R /A 408 0 R >> endobj 2363 0 obj << /Title (DISCONNECT) /Parent 2351 0 R /Prev 2362 0 R /Next 2364 0 R /A 120 0 R >> endobj 2364 0 obj << /Title (DISCONNECT-POOLED) /Parent 2351 0 R /Prev 2363 0 R /Next 2365 0 R /A 144 0 R >> endobj 2365 0 obj << /Title (FIND-DATABASE) /Parent 2351 0 R /Prev 2364 0 R /Next 2366 0 R /A 192 0 R >> endobj 2366 0 obj << /Title (INITIALIZE-DATABASE-TYPE) /Parent 2351 0 R /Prev 2365 0 R /Next 2367 0 R /A 155 0 R >> endobj 2367 0 obj << /Title (RECONNECT) /Parent 2351 0 R /Prev 2366 0 R /Next 2368 0 R /A 189 0 R >> endobj 2368 0 obj << /Title (STATUS) /Parent 2351 0 R /Prev 2367 0 R /Next 2369 0 R /A 194 0 R >> endobj 2369 0 obj << /Title (CREATE-DATABASE) /Parent 2351 0 R /Prev 2368 0 R /Next 2370 0 R /A 254 0 R >> endobj 2370 0 obj << /Title (DESTROY-DATABASE) /Parent 2351 0 R /Prev 2369 0 R /Next 2371 0 R /A 257 0 R >> endobj 2371 0 obj << /Title (PROBE-DATABASE) /Parent 2351 0 R /Prev 2370 0 R /Next 2372 0 R /A 259 0 R >> endobj 2372 0 obj << /Title (LIST-DATABASES) /Parent 2351 0 R /Prev 2371 0 R /Next 2373 0 R /A 267 0 R >> endobj 2373 0 obj << /Title (WITH-DATABASE) /Parent 2351 0 R /Prev 2372 0 R /Next 2374 0 R /A 289 0 R >> endobj 2374 0 obj << /Title (WITH-DEFAULT-DATABASE) /Parent 2351 0 R /Prev 2373 0 R /A 300 0 R >> endobj 2375 0 obj << /Title (The Symbolic SQL Syntax) /Parent 2320 0 R /Prev 2351 0 R /Next 2386 0 R /First 2376 0 R /Last 2385 0 R /Count -10 /A 435 0 R >> endobj 2376 0 obj << /Title (ENABLE-SQL-READER-SYNTAX) /Parent 2375 0 R /Next 2377 0 R /A 438 0 R >> endobj 2377 0 obj << /Title (DISABLE-SQL-READER-SYNTAX) /Parent 2375 0 R /Prev 2376 0 R /Next 2378 0 R /A 452 0 R >> endobj 2378 0 obj << /Title (LOCALLY-ENABLE-SQL-READER-SYNTAX) /Parent 2375 0 R /Prev 2377 0 R /Next 2379 0 R /A 481 0 R >> endobj 2379 0 obj << /Title (LOCALLY-DISABLE-SQL-READER-SYNTAX) /Parent 2375 0 R /Prev 2378 0 R /Next 2380 0 R /A 484 0 R >> endobj 2380 0 obj << /Title (RESTORE-SQL-READER-SYNTAX-STATE) /Parent 2375 0 R /Prev 2379 0 R /Next 2381 0 R /A 471 0 R >> endobj 2381 0 obj << /Title (FILE-ENABLE-SQL-READER-SYNTAX) /Parent 2375 0 R /Prev 2380 0 R /Next 2382 0 R /A 465 0 R >> endobj 2382 0 obj << /Title (SQL) /Parent 2375 0 R /Prev 2381 0 R /Next 2383 0 R /A 560 0 R >> endobj 2383 0 obj << /Title (SQL-EXPRESSION) /Parent 2375 0 R /Prev 2382 0 R /Next 2384 0 R /A 563 0 R >> endobj 2384 0 obj << /Title (SQL-OPERATION) /Parent 2375 0 R /Prev 2383 0 R /Next 2385 0 R /A 565 0 R >> endobj 2385 0 obj << /Title (SQL-OPERATOR) /Parent 2375 0 R /Prev 2384 0 R /A 994 0 R >> endobj 2386 0 obj << /Title (Functional Data Definition Language \(FDDL\)) /Parent 2320 0 R /Prev 2375 0 R /Next 2410 0 R /First 2387 0 R /Last 2409 0 R /Count -23 /A 997 0 R >> endobj 2387 0 obj << /Title (CREATE-TABLE) /Parent 2386 0 R /Next 2388 0 R /A 576 0 R >> endobj 2388 0 obj << /Title (DROP-TABLE) /Parent 2386 0 R /Prev 2387 0 R /Next 2389 0 R /A 587 0 R >> endobj 2389 0 obj << /Title (LIST-TABLES) /Parent 2386 0 R /Prev 2388 0 R /Next 2390 0 R /A 589 0 R >> endobj 2390 0 obj << /Title (TABLE-EXISTS-P) /Parent 2386 0 R /Prev 2389 0 R /Next 2391 0 R /A 597 0 R >> endobj 2391 0 obj << /Title (CREATE-VIEW) /Parent 2386 0 R /Prev 2390 0 R /Next 2392 0 R /A 621 0 R >> endobj 2392 0 obj << /Title (DROP-VIEW) /Parent 2386 0 R /Prev 2391 0 R /Next 2393 0 R /A 632 0 R >> endobj 2393 0 obj << /Title (LIST-VIEWS) /Parent 2386 0 R /Prev 2392 0 R /Next 2394 0 R /A 634 0 R >> endobj 2394 0 obj << /Title (VIEW-EXISTS-P) /Parent 2386 0 R /Prev 2393 0 R /Next 2395 0 R /A 642 0 R >> endobj 2395 0 obj << /Title (CREATE-INDEX) /Parent 2386 0 R /Prev 2394 0 R /Next 2396 0 R /A 672 0 R >> endobj 2396 0 obj << /Title (DROP-INDEX) /Parent 2386 0 R /Prev 2395 0 R /Next 2397 0 R /A 675 0 R >> endobj 2397 0 obj << /Title (LIST-INDEXES) /Parent 2386 0 R /Prev 2396 0 R /Next 2398 0 R /A 677 0 R >> endobj 2398 0 obj << /Title (INDEX-EXISTS-P) /Parent 2386 0 R /Prev 2397 0 R /Next 2399 0 R /A 685 0 R >> endobj 2399 0 obj << /Title (ATTRIBUTE-TYPE) /Parent 2386 0 R /Prev 2398 0 R /Next 2400 0 R /A 713 0 R >> endobj 2400 0 obj << /Title (LIST-ATTRIBUTE-TYPES) /Parent 2386 0 R /Prev 2399 0 R /Next 2401 0 R /A 716 0 R >> endobj 2401 0 obj << /Title (LIST-ATTRIBUTES) /Parent 2386 0 R /Prev 2400 0 R /Next 2402 0 R /A 727 0 R >> endobj 2402 0 obj << /Title (CREATE-SEQUENCE) /Parent 2386 0 R /Prev 2401 0 R /Next 2403 0 R /A 740 0 R >> endobj 2403 0 obj << /Title (DROP-SEQUENCE) /Parent 2386 0 R /Prev 2402 0 R /Next 2404 0 R /A 748 0 R >> endobj 2404 0 obj << /Title (LIST-SEQUENCES) /Parent 2386 0 R /Prev 2403 0 R /Next 2405 0 R /A 750 0 R >> endobj 2405 0 obj << /Title (SEQUENCE-EXISTS-P) /Parent 2386 0 R /Prev 2404 0 R /Next 2406 0 R /A 768 0 R >> endobj 2406 0 obj << /Title (SEQUENCE-LAST) /Parent 2386 0 R /Prev 2405 0 R /Next 2407 0 R /A 752 0 R >> endobj 2407 0 obj << /Title (SEQUENCE-NEXT) /Parent 2386 0 R /Prev 2406 0 R /Next 2408 0 R /A 771 0 R >> endobj 2408 0 obj << /Title (SET-SEQUENCE-POSITION) /Parent 2386 0 R /Prev 2407 0 R /Next 2409 0 R /A 788 0 R >> endobj 2409 0 obj << /Title (TRUNCATE-DATABASE) /Parent 2386 0 R /Prev 2408 0 R /A 1044 0 R >> endobj 2410 0 obj << /Title (Functional Data Manipulation Language \(FDML\)) /Parent 2320 0 R /Prev 2386 0 R /Next 2423 0 R /First 2411 0 R /Last 2422 0 R /Count -12 /A 1047 0 R >> endobj 2411 0 obj << /Title (*CACHE-TABLE-QUERIES-DEFAULT*) /Parent 2410 0 R /Next 2412 0 R /A 854 0 R >> endobj 2412 0 obj << /Title (CACHE-TABLE-QUERIES) /Parent 2410 0 R /Prev 2411 0 R /Next 2413 0 R /A 848 0 R >> endobj 2413 0 obj << /Title (INSERT-RECORDS) /Parent 2410 0 R /Prev 2412 0 R /Next 2414 0 R /A 869 0 R >> endobj 2414 0 obj << /Title (UPDATE-RECORDS) /Parent 2410 0 R /Prev 2413 0 R /Next 2415 0 R /A 861 0 R >> endobj 2415 0 obj << /Title (DELETE-RECORDS) /Parent 2410 0 R /Prev 2414 0 R /Next 2416 0 R /A 864 0 R >> endobj 2416 0 obj << /Title (EXECUTE-COMMAND) /Parent 2410 0 R /Prev 2415 0 R /Next 2417 0 R /A 888 0 R >> endobj 2417 0 obj << /Title (QUERY) /Parent 2410 0 R /Prev 2416 0 R /Next 2418 0 R /A 882 0 R >> endobj 2418 0 obj << /Title (PRINT-QUERY) /Parent 2410 0 R /Prev 2417 0 R /Next 2419 0 R /A 920 0 R >> endobj 2419 0 obj << /Title (SELECT) /Parent 2410 0 R /Prev 2418 0 R /Next 2420 0 R /A 909 0 R >> endobj 2420 0 obj << /Title (DO-QUERY) /Parent 2410 0 R /Prev 2419 0 R /Next 2421 0 R /A 911 0 R >> endobj 2421 0 obj << /Title (LOOP) /Parent 2410 0 R /Prev 2420 0 R /Next 2422 0 R /A 915 0 R >> endobj 2422 0 obj << /Title (MAP-QUERY) /Parent 2410 0 R /Prev 2421 0 R /A 913 0 R >> endobj 2423 0 obj << /Title (Transaction Handling) /Parent 2320 0 R /Prev 2410 0 R /Next 2432 0 R /First 2424 0 R /Last 2431 0 R /Count -8 /A 1074 0 R >> endobj 2424 0 obj << /Title (START-TRANSACTION) /Parent 2423 0 R /Next 2425 0 R /A 1077 0 R >> endobj 2425 0 obj << /Title (COMMIT) /Parent 2423 0 R /Prev 2424 0 R /Next 2426 0 R /A 1080 0 R >> endobj 2426 0 obj << /Title (ROLLBACK) /Parent 2423 0 R /Prev 2425 0 R /Next 2427 0 R /A 969 0 R >> endobj 2427 0 obj << /Title (IN-TRANSACTION-P) /Parent 2423 0 R /Prev 2426 0 R /Next 2428 0 R /A 1085 0 R >> endobj 2428 0 obj << /Title (ADD-TRANSACTION-COMMIT-HOOK) /Parent 2423 0 R /Prev 2427 0 R /Next 2429 0 R /A 972 0 R >> endobj 2429 0 obj << /Title (ADD-TRANSACTION-ROLLBACK-HOOK) /Parent 2423 0 R /Prev 2428 0 R /Next 2430 0 R /A 1090 0 R >> endobj 2430 0 obj << /Title (SET-AUTOCOMMIT) /Parent 2423 0 R /Prev 2429 0 R /Next 2431 0 R /A 1093 0 R >> endobj 2431 0 obj << /Title (WITH-TRANSACTION) /Parent 2423 0 R /Prev 2430 0 R /A 1120 0 R >> endobj 2432 0 obj << /Title (Object Oriented Data Definition Language \(OODDL\)) /Parent 2320 0 R /Prev 2423 0 R /Next 2439 0 R /First 2433 0 R /Last 2438 0 R /Count -6 /A 1281 0 R >> endobj 2433 0 obj << /Title (STANDARD-DB-OBJECT) /Parent 2432 0 R /Next 2434 0 R /A 1213 0 R >> endobj 2434 0 obj << /Title (*DEFAULT-STRING-LENGTH*) /Parent 2432 0 R /Prev 2433 0 R /Next 2435 0 R /A 1177 0 R >> endobj 2435 0 obj << /Title (CREATE-VIEW-FROM-CLASS) /Parent 2432 0 R /Prev 2434 0 R /Next 2436 0 R /A 1198 0 R >> endobj 2436 0 obj << /Title (DEF-VIEW-CLASS) /Parent 2432 0 R /Prev 2435 0 R /Next 2437 0 R /A 1166 0 R >> endobj 2437 0 obj << /Title (DROP-VIEW-FROM-CLASS) /Parent 2432 0 R /Prev 2436 0 R /Next 2438 0 R /A 1200 0 R >> endobj 2438 0 obj << /Title (LIST-CLASSES) /Parent 2432 0 R /Prev 2437 0 R /A 1624 0 R >> endobj 2439 0 obj << /Title (Object Oriented Data Manipulation Language \(OODML\)) /Parent 2320 0 R /Prev 2432 0 R /Next 2451 0 R /First 2440 0 R /Last 2450 0 R /Count -11 /A 1662 0 R >> endobj 2440 0 obj << /Title (*DB-AUTO-SYNC*) /Parent 2439 0 R /Next 2441 0 R /A 1519 0 R >> endobj 2441 0 obj << /Title (*DEFAULT-CACHING*) /Parent 2439 0 R /Prev 2440 0 R /Next 2442 0 R /A 1667 0 R >> endobj 2442 0 obj << /Title (*DEFAULT-UPDATE-OBJECTS-MAX-LEN*) /Parent 2439 0 R /Prev 2441 0 R /Next 2443 0 R /A 1319 0 R >> endobj 2443 0 obj << /Title (INSTANCE-REFRESHED) /Parent 2439 0 R /Prev 2442 0 R /Next 2444 0 R /A 1236 0 R >> endobj 2444 0 obj << /Title (DELETE-INSTANCE-RECORDS) /Parent 2439 0 R /Prev 2443 0 R /Next 2445 0 R /A 1294 0 R >> endobj 2445 0 obj << /Title (UPDATE-RECORDS-FROM-INSTANCE) /Parent 2439 0 R /Prev 2444 0 R /Next 2446 0 R /A 1249 0 R >> endobj 2446 0 obj << /Title (UPDATE-RECORD-FROM-SLOT) /Parent 2439 0 R /Prev 2445 0 R /Next 2447 0 R /A 1254 0 R >> endobj 2447 0 obj << /Title (UPDATE-RECORD-FROM-SLOTS) /Parent 2439 0 R /Prev 2446 0 R /Next 2448 0 R /A 1257 0 R >> endobj 2448 0 obj << /Title (UPDATE-INSTANCE-FROM-RECORDS) /Parent 2439 0 R /Prev 2447 0 R /Next 2449 0 R /A 1288 0 R >> endobj 2449 0 obj << /Title (UPDATE-SLOT-FROM-RECORD) /Parent 2439 0 R /Prev 2448 0 R /Next 2450 0 R /A 1285 0 R >> endobj 2450 0 obj << /Title (UPDATE-OBJECTS-JOINS) /Parent 2439 0 R /Prev 2449 0 R /A 1299 0 R >> endobj 2451 0 obj << /Title (SQL I/O Recording) /Parent 2320 0 R /Prev 2439 0 R /Next 2459 0 R /First 2452 0 R /Last 2458 0 R /Count -7 /A 1688 0 R >> endobj 2452 0 obj << /Title (START-SQL-RECORDING) /Parent 2451 0 R /Next 2453 0 R /A 1331 0 R >> endobj 2453 0 obj << /Title (STOP-SQL-RECORDING) /Parent 2451 0 R /Prev 2452 0 R /Next 2454 0 R /A 1341 0 R >> endobj 2454 0 obj << /Title (SQL-RECORDING-P) /Parent 2451 0 R /Prev 2453 0 R /Next 2455 0 R /A 1334 0 R >> endobj 2455 0 obj << /Title (SQL-STREAM) /Parent 2451 0 R /Prev 2454 0 R /Next 2456 0 R /A 1349 0 R >> endobj 2456 0 obj << /Title (ADD-SQL-STREAM) /Parent 2451 0 R /Prev 2455 0 R /Next 2457 0 R /A 1351 0 R >> endobj 2457 0 obj << /Title (DELETE-SQL-STREAM) /Parent 2451 0 R /Prev 2456 0 R /Next 2458 0 R /A 1353 0 R >> endobj 2458 0 obj << /Title (LIST-SQL-STREAMS) /Parent 2451 0 R /Prev 2457 0 R /A 1355 0 R >> endobj 2459 0 obj << /Title (CLSQL Condition System) /Parent 2320 0 R /Prev 2451 0 R /Next 2472 0 R /First 2460 0 R /Last 2471 0 R /Count -12 /A 1705 0 R >> endobj 2460 0 obj << /Title (*BACKEND-WARNING-BEHAVIOR*) /Parent 2459 0 R /Next 2461 0 R /A 1511 0 R >> endobj 2461 0 obj << /Title (SQL-CONDITION) /Parent 2459 0 R /Prev 2460 0 R /Next 2462 0 R /A 1396 0 R >> endobj 2462 0 obj << /Title (SQL-ERROR) /Parent 2459 0 R /Prev 2461 0 R /Next 2463 0 R /A 1408 0 R >> endobj 2463 0 obj << /Title (SQL-WARNING) /Parent 2459 0 R /Prev 2462 0 R /Next 2464 0 R /A 1415 0 R >> endobj 2464 0 obj << /Title (SQL-DATABASE-WARNING) /Parent 2459 0 R /Prev 2463 0 R /Next 2465 0 R /A 1422 0 R >> endobj 2465 0 obj << /Title (SQL-USER-ERROR) /Parent 2459 0 R /Prev 2464 0 R /Next 2466 0 R /A 1436 0 R >> endobj 2466 0 obj << /Title (SQL-DATABASE-ERROR) /Parent 2459 0 R /Prev 2465 0 R /Next 2467 0 R /A 1461 0 R >> endobj 2467 0 obj << /Title (SQL-CONNECTION-ERROR) /Parent 2459 0 R /Prev 2466 0 R /Next 2468 0 R /A 1469 0 R >> endobj 2468 0 obj << /Title (SQL-DATABASE-DATA-ERROR) /Parent 2459 0 R /Prev 2467 0 R /Next 2469 0 R /A 1559 0 R >> endobj 2469 0 obj << /Title (SQL-TEMPORARY-ERROR) /Parent 2459 0 R /Prev 2468 0 R /Next 2470 0 R /A 1581 0 R >> endobj 2470 0 obj << /Title (SQL-TIMEOUT-ERROR) /Parent 2459 0 R /Prev 2469 0 R /Next 2471 0 R /A 1584 0 R >> endobj 2471 0 obj << /Title (SQL-FATAL-ERROR) /Parent 2459 0 R /Prev 2470 0 R /A 1570 0 R >> endobj 2472 0 obj << /Title (Index) /Parent 2320 0 R /Prev 2459 0 R /Next 2474 0 R /First 2473 0 R /Last 2473 0 R /Count -1 /A 1732 0 R >> endobj 2473 0 obj << /Title (Alphabetical Index for package CLSQL) /Parent 2472 0 R /A 1735 0 R >> endobj 2474 0 obj << /Title /Parent 2320 0 R /Prev 2472 0 R /Next 2546 0 R /First 2475 0 R /Last 2536 0 R /Count -71 /A 1636 0 R >> endobj 2475 0 obj << /Title (How CLSQL finds and loads foreign libraries) /Parent 2474 0 R /Next 2476 0 R /A 1740 0 R >> endobj 2476 0 obj << /Title (PostgreSQL) /Parent 2474 0 R /Prev 2475 0 R /Next 2483 0 R /First 2477 0 R /Last 2482 0 R /Count -6 /A 1743 0 R >> endobj 2477 0 obj << /Title (Libraries) /Parent 2476 0 R /Next 2478 0 R /A 1746 0 R >> endobj 2478 0 obj << /Title (Initialization) /Parent 2476 0 R /Prev 2477 0 R /Next 2479 0 R /A 1749 0 R >> endobj 2479 0 obj << /Title (Connection Specification) /Parent 2476 0 R /Prev 2478 0 R /Next 2482 0 R /First 2480 0 R /Last 2481 0 R /Count -2 /A 1752 0 R >> endobj 2480 0 obj << /Title (Syntax of connection-spec) /Parent 2479 0 R /Next 2481 0 R /A 2292 0 R >> endobj 2481 0 obj << /Title (Description of connection-spec) /Parent 2479 0 R /Prev 2480 0 R /A 2293 0 R >> endobj 2482 0 obj << /Title (Notes) /Parent 2476 0 R /Prev 2479 0 R /A 1755 0 R >> endobj 2483 0 obj << /Title (PostgreSQL Socket) /Parent 2474 0 R /Prev 2476 0 R /Next 2490 0 R /First 2484 0 R /Last 2489 0 R /Count -6 /A 1758 0 R >> endobj 2484 0 obj << /Title (Libraries) /Parent 2483 0 R /Next 2485 0 R /A 1761 0 R >> endobj 2485 0 obj << /Title (Initialization) /Parent 2483 0 R /Prev 2484 0 R /Next 2486 0 R /A 1764 0 R >> endobj 2486 0 obj << /Title (Connection Specification) /Parent 2483 0 R /Prev 2485 0 R /Next 2489 0 R /First 2487 0 R /Last 2488 0 R /Count -2 /A 1767 0 R >> endobj 2487 0 obj << /Title (Syntax of connection-spec) /Parent 2486 0 R /Next 2488 0 R /A 2294 0 R >> endobj 2488 0 obj << /Title (Description of connection-spec) /Parent 2486 0 R /Prev 2487 0 R /A 2295 0 R >> endobj 2489 0 obj << /Title (Notes) /Parent 2483 0 R /Prev 2486 0 R /A 1812 0 R >> endobj 2490 0 obj << /Title (MySQL) /Parent 2474 0 R /Prev 2483 0 R /Next 2500 0 R /First 2491 0 R /Last 2496 0 R /Count -9 /A 1816 0 R >> endobj 2491 0 obj << /Title (Libraries) /Parent 2490 0 R /Next 2492 0 R /A 1819 0 R >> endobj 2492 0 obj << /Title (Initialization) /Parent 2490 0 R /Prev 2491 0 R /Next 2493 0 R /A 1822 0 R >> endobj 2493 0 obj << /Title (Connection Specification) /Parent 2490 0 R /Prev 2492 0 R /Next 2496 0 R /First 2494 0 R /Last 2495 0 R /Count -2 /A 1825 0 R >> endobj 2494 0 obj << /Title (Syntax of connection-spec) /Parent 2493 0 R /Next 2495 0 R /A 2296 0 R >> endobj 2495 0 obj << /Title (Description of connection-spec) /Parent 2493 0 R /Prev 2494 0 R /A 2297 0 R >> endobj 2496 0 obj << /Title (Notes) /Parent 2490 0 R /Prev 2493 0 R /First 2497 0 R /Last 2499 0 R /Count -3 /A 1828 0 R >> endobj 2497 0 obj << /Title (FDDL) /Parent 2496 0 R /Next 2498 0 R /A 2298 0 R >> endobj 2498 0 obj << /Title (FDML) /Parent 2496 0 R /Prev 2497 0 R /Next 2499 0 R /A 2299 0 R >> endobj 2499 0 obj << /Title (Symbolic SQL Syntax) /Parent 2496 0 R /Prev 2498 0 R /A 2300 0 R >> endobj 2500 0 obj << /Title (ODBC) /Parent 2474 0 R /Prev 2490 0 R /Next 2509 0 R /First 2501 0 R /Last 2508 0 R /Count -8 /A 1831 0 R >> endobj 2501 0 obj << /Title (Libraries) /Parent 2500 0 R /Next 2502 0 R /A 1834 0 R >> endobj 2502 0 obj << /Title (Initialization) /Parent 2500 0 R /Prev 2501 0 R /Next 2503 0 R /A 1837 0 R >> endobj 2503 0 obj << /Title (Connection Specification) /Parent 2500 0 R /Prev 2502 0 R /Next 2506 0 R /First 2504 0 R /Last 2505 0 R /Count -2 /A 1840 0 R >> endobj 2504 0 obj << /Title (Syntax of connection-spec) /Parent 2503 0 R /Next 2505 0 R /A 2301 0 R >> endobj 2505 0 obj << /Title (Description of connection-spec) /Parent 2503 0 R /Prev 2504 0 R /A 2302 0 R >> endobj 2506 0 obj << /Title (Notes) /Parent 2500 0 R /Prev 2503 0 R /Next 2508 0 R /First 2507 0 R /Last 2507 0 R /Count -1 /A 1843 0 R >> endobj 2507 0 obj << /Title (FDDL) /Parent 2506 0 R /A 2303 0 R >> endobj 2508 0 obj << /Title (Connect Examples) /Parent 2500 0 R /Prev 2506 0 R /A 1846 0 R >> endobj 2509 0 obj << /Title (AODBC) /Parent 2474 0 R /Prev 2500 0 R /Next 2516 0 R /First 2510 0 R /Last 2515 0 R /Count -6 /A 1849 0 R >> endobj 2510 0 obj << /Title (Libraries) /Parent 2509 0 R /Next 2511 0 R /A 1852 0 R >> endobj 2511 0 obj << /Title (Initialization) /Parent 2509 0 R /Prev 2510 0 R /Next 2512 0 R /A 1855 0 R >> endobj 2512 0 obj << /Title (Connection Specification) /Parent 2509 0 R /Prev 2511 0 R /Next 2515 0 R /First 2513 0 R /Last 2514 0 R /Count -2 /A 1858 0 R >> endobj 2513 0 obj << /Title (Syntax of connection-spec) /Parent 2512 0 R /Next 2514 0 R /A 2304 0 R >> endobj 2514 0 obj << /Title (Description of connection-spec) /Parent 2512 0 R /Prev 2513 0 R /A 2305 0 R >> endobj 2515 0 obj << /Title (Notes) /Parent 2509 0 R /Prev 2512 0 R /A 1861 0 R >> endobj 2516 0 obj << /Title (SQLite version 2) /Parent 2474 0 R /Prev 2509 0 R /Next 2526 0 R /First 2517 0 R /Last 2522 0 R /Count -9 /A 1864 0 R >> endobj 2517 0 obj << /Title (Libraries) /Parent 2516 0 R /Next 2518 0 R /A 1867 0 R >> endobj 2518 0 obj << /Title (Initialization) /Parent 2516 0 R /Prev 2517 0 R /Next 2519 0 R /A 1870 0 R >> endobj 2519 0 obj << /Title (Connection Specification) /Parent 2516 0 R /Prev 2518 0 R /Next 2522 0 R /First 2520 0 R /Last 2521 0 R /Count -2 /A 1873 0 R >> endobj 2520 0 obj << /Title (Syntax of connection-spec) /Parent 2519 0 R /Next 2521 0 R /A 2306 0 R >> endobj 2521 0 obj << /Title (Description of connection-spec) /Parent 2519 0 R /Prev 2520 0 R /A 2307 0 R >> endobj 2522 0 obj << /Title (Notes) /Parent 2516 0 R /Prev 2519 0 R /First 2523 0 R /Last 2525 0 R /Count -3 /A 1876 0 R >> endobj 2523 0 obj << /Title (Connection) /Parent 2522 0 R /Next 2524 0 R /A 2308 0 R >> endobj 2524 0 obj << /Title (FDDL) /Parent 2522 0 R /Prev 2523 0 R /Next 2525 0 R /A 2309 0 R >> endobj 2525 0 obj << /Title (Symbolic SQL Syntax) /Parent 2522 0 R /Prev 2524 0 R /A 2310 0 R >> endobj 2526 0 obj << /Title (SQLite version 3) /Parent 2474 0 R /Prev 2516 0 R /Next 2536 0 R /First 2527 0 R /Last 2532 0 R /Count -9 /A 1879 0 R >> endobj 2527 0 obj << /Title (Libraries) /Parent 2526 0 R /Next 2528 0 R /A 1882 0 R >> endobj 2528 0 obj << /Title (Initialization) /Parent 2526 0 R /Prev 2527 0 R /Next 2529 0 R /A 1885 0 R >> endobj 2529 0 obj << /Title (Connection Specification) /Parent 2526 0 R /Prev 2528 0 R /Next 2532 0 R /First 2530 0 R /Last 2531 0 R /Count -2 /A 1888 0 R >> endobj 2530 0 obj << /Title (Syntax of connection-spec) /Parent 2529 0 R /Next 2531 0 R /A 2311 0 R >> endobj 2531 0 obj << /Title (Description of connection-spec) /Parent 2529 0 R /Prev 2530 0 R /A 2312 0 R >> endobj 2532 0 obj << /Title (Notes) /Parent 2526 0 R /Prev 2529 0 R /First 2533 0 R /Last 2535 0 R /Count -3 /A 1891 0 R >> endobj 2533 0 obj << /Title (Connection) /Parent 2532 0 R /Next 2534 0 R /A 2313 0 R >> endobj 2534 0 obj << /Title (FDDL) /Parent 2532 0 R /Prev 2533 0 R /Next 2535 0 R /A 2314 0 R >> endobj 2535 0 obj << /Title (Symbolic SQL Syntax) /Parent 2532 0 R /Prev 2534 0 R /A 2315 0 R >> endobj 2536 0 obj << /Title (Oracle) /Parent 2474 0 R /Prev 2526 0 R /First 2537 0 R /Last 2543 0 R /Count -9 /A 1894 0 R >> endobj 2537 0 obj << /Title (Libraries) /Parent 2536 0 R /Next 2538 0 R /A 1897 0 R >> endobj 2538 0 obj << /Title (Library Versions) /Parent 2536 0 R /Prev 2537 0 R /Next 2539 0 R /A 1900 0 R >> endobj 2539 0 obj << /Title (Initialization) /Parent 2536 0 R /Prev 2538 0 R /Next 2540 0 R /A 1903 0 R >> endobj 2540 0 obj << /Title (Connection Specification) /Parent 2536 0 R /Prev 2539 0 R /Next 2543 0 R /First 2541 0 R /Last 2542 0 R /Count -2 /A 1906 0 R >> endobj 2541 0 obj << /Title (Syntax of connection-spec) /Parent 2540 0 R /Next 2542 0 R /A 2316 0 R >> endobj 2542 0 obj << /Title (Description of connection-spec) /Parent 2540 0 R /Prev 2541 0 R /A 2317 0 R >> endobj 2543 0 obj << /Title (Notes) /Parent 2536 0 R /Prev 2540 0 R /First 2544 0 R /Last 2545 0 R /Count -2 /A 1909 0 R >> endobj 2544 0 obj << /Title (Symbolic SQL Syntax) /Parent 2543 0 R /Next 2545 0 R /A 2318 0 R >> endobj 2545 0 obj << /Title (Transactions) /Parent 2543 0 R /Prev 2544 0 R /A 2319 0 R >> endobj 2546 0 obj << /Title (Glossary) /Parent 2320 0 R /Prev 2474 0 R /A 1912 0 R >> endobj 2547 0 obj << /Type /Font /Subtype /Type1 /BaseFont /Courier-Oblique /Encoding /WinAnsiEncoding >> endobj 2548 0 obj << /Type /Font /Subtype /Type1 /BaseFont /Times-Roman /Encoding /WinAnsiEncoding >> endobj 2549 0 obj << /Type /Font /Subtype /Type1 /BaseFont /Helvetica-BoldOblique /Encoding /WinAnsiEncoding >> endobj 2550 0 obj << /Type /Font /Subtype /Type1 /BaseFont /Helvetica-Bold /Encoding /WinAnsiEncoding >> endobj 2551 0 obj << /Type /Font /Subtype /Type1 /BaseFont /Courier /Encoding /WinAnsiEncoding >> endobj 2552 0 obj << /Type /Font /Subtype /Type1 /BaseFont /Times-Italic /Encoding /WinAnsiEncoding >> endobj 2553 0 obj << /Type /Font /Subtype /Type1 /BaseFont /Times-Bold /Encoding /WinAnsiEncoding >> endobj 2554 0 obj << /Limits [(add-sql-stream) (add-sql-stream)] /Names [(add-sql-stream) 1351 0 R] >> endobj 2555 0 obj << /Limits [(add-transaction-commit-hook) (add-transaction-commit-hook)] /Names [(add-transaction-commit-hook) 972 0 R] >> endobj 2556 0 obj << /Limits [(add-transaction-rollback-hook) (add-transaction-rollback-hook)] /Names [(add-transaction-rollback-hook) 1090 0 R] >> endobj 2557 0 obj << /Limits [(aodbc) (aodbc)] /Names [(aodbc) 1849 0 R] >> endobj 2558 0 obj << /Limits [(appendix) (appendix)] /Names [(appendix) 1636 0 R] >> endobj 2559 0 obj << /Limits [(attribute-type) (attribute-type)] /Names [(attribute-type) 713 0 R] >> endobj 2560 0 obj << /Limits [(backend-warning-behavior) (backend-warning-behavior)] /Names [(backend-warning-behavior) 1511 0 R] >> endobj 2561 0 obj << /Limits [(cache-table-queries) (cache-table-queries)] /Names [(cache-table-queries) 848 0 R] >> endobj 2562 0 obj << /Limits [(cache-table-queries-default) (cache-table-queries-default)] /Names [(cache-table-queries-default) 854 0 R] >> endobj 2563 0 obj << /Limits [(clsql-index) (clsql-index)] /Names [(clsql-index) 1735 0 R] >> endobj 2564 0 obj << /Limits [(commit) (commit)] /Names [(commit) 1080 0 R] >> endobj 2565 0 obj << /Limits [(connect) (connect)] /Names [(connect) 79 0 R] >> endobj 2566 0 obj << /Limits [(connect-if-exists) (connect-if-exists)] /Names [(connect-if-exists) 90 0 R] >> endobj 2567 0 obj << /Limits [(connected-databases) (connected-databases)] /Names [(connected-databases) 109 0 R] >> endobj 2568 0 obj << /Limits [(create-database) (create-database)] /Names [(create-database) 254 0 R] >> endobj 2569 0 obj << /Limits [(create-index) (create-index)] /Names [(create-index) 672 0 R] >> endobj 2570 0 obj << /Limits [(create-sequence) (create-sequence)] /Names [(create-sequence) 740 0 R] >> endobj 2571 0 obj << /Limits [(create-table) (create-table)] /Names [(create-table) 576 0 R] >> endobj 2572 0 obj << /Limits [(create-view) (create-view)] /Names [(create-view) 621 0 R] >> endobj 2573 0 obj << /Limits [(create-view-from-class) (create-view-from-class)] /Names [(create-view-from-class) 1198 0 R] >> endobj 2574 0 obj << /Limits [(csql) (csql)] /Names [(csql) 360 0 R] >> endobj 2575 0 obj << /Limits [(csql-concl) (csql-concl)] /Names [(csql-concl) 381 0 R] >> endobj 2576 0 obj << /Limits [(csql-creat) (csql-creat)] /Names [(csql-creat) 372 0 R] >> endobj 2577 0 obj << /Limits [(csql-del) (csql-del)] /Names [(csql-del) 378 0 R] >> endobj 2578 0 obj << /Limits [(csql-find) (csql-find)] /Names [(csql-find) 375 0 R] >> endobj 2579 0 obj << /Limits [(csql-intro) (csql-intro)] /Names [(csql-intro) 363 0 R] >> endobj 2580 0 obj << /Limits [(csql-rel) (csql-rel)] /Names [(csql-rel) 369 0 R] >> endobj 2581 0 obj << /Limits [(database) (database)] /Names [(database) 387 0 R] >> endobj 2582 0 obj << /Limits [(database-name) (database-name)] /Names [(database-name) 229 0 R] >> endobj 2583 0 obj << /Limits [(database-name-from-spec) (database-name-from-spec)] /Names [(database-name-from-spec) 207 0 R] >> endobj 2584 0 obj << /Limits [(database-type) (database-type)] /Names [(database-type) 408 0 R] >> endobj 2585 0 obj << /Limits [(db-auto-sync) (db-auto-sync)] /Names [(db-auto-sync) 1519 0 R] >> endobj 2586 0 obj << /Limits [(db-pool-max-free-connections) (db-pool-max-free-connections)] /Names [(db-pool-max-free-connections) 113 0 R] >> endobj 2587 0 obj << /Limits [(def-view-class) (def-view-class)] /Names [(def-view-class) 1166 0 R] >> endobj 2588 0 obj << /Limits [(default-caching) (default-caching)] /Names [(default-caching) 1667 0 R] >> endobj 2589 0 obj << /Limits [(default-database) (default-database)] /Names [(default-database) 139 0 R] >> endobj 2590 0 obj << /Limits [(default-database-type) (default-database-type)] /Names [(default-database-type) 87 0 R] >> endobj 2591 0 obj << /Limits [(default-string-length) (default-string-length)] /Names [(default-string-length) 1177 0 R] >> endobj 2592 0 obj << /Limits [(default-update-objects-max-len) (default-update-objects-max-len)] /Names [(default-update-objects-max-len) 1319 0 R] >> endobj 2593 0 obj << /Limits [(delete-instance-records) (delete-instance-records)] /Names [(delete-instance-records) 1294 0 R] >> endobj 2594 0 obj << /Limits [(delete-records) (delete-records)] /Names [(delete-records) 864 0 R] >> endobj 2595 0 obj << /Limits [(delete-sql-stream) (delete-sql-stream)] /Names [(delete-sql-stream) 1353 0 R] >> endobj 2596 0 obj << /Limits [(destroy-database) (destroy-database)] /Names [(destroy-database) 257 0 R] >> endobj 2597 0 obj << /Limits [(disable-sql-reader-syntax) (disable-sql-reader-syntax)] /Names [(disable-sql-reader-syntax) 452 0 R] >> endobj 2598 0 obj << /Limits [(disconnect) (disconnect)] /Names [(disconnect) 120 0 R] >> endobj 2599 0 obj << /Limits [(disconnect-pooled) (disconnect-pooled)] /Names [(disconnect-pooled) 144 0 R] >> endobj 2600 0 obj << /Limits [(do-query) (do-query)] /Names [(do-query) 911 0 R] >> endobj 2601 0 obj << /Limits [(drop-index) (drop-index)] /Names [(drop-index) 675 0 R] >> endobj 2602 0 obj << /Limits [(drop-sequence) (drop-sequence)] /Names [(drop-sequence) 748 0 R] >> endobj 2603 0 obj << /Limits [(drop-table) (drop-table)] /Names [(drop-table) 587 0 R] >> endobj 2604 0 obj << /Limits [(drop-view) (drop-view)] /Names [(drop-view) 632 0 R] >> endobj 2605 0 obj << /Limits [(drop-view-from-class) (drop-view-from-class)] /Names [(drop-view-from-class) 1200 0 R] >> endobj 2606 0 obj << /Limits [(enable-sql-reader-syntax) (enable-sql-reader-syntax)] /Names [(enable-sql-reader-syntax) 438 0 R] >> endobj 2607 0 obj << /Limits [(execute-command) (execute-command)] /Names [(execute-command) 888 0 R] >> endobj 2608 0 obj << /Limits [(file-enable-sql-reader-syntax) (file-enable-sql-reader-syntax)] /Names [(file-enable-sql-reader-syntax) 465 0 R] >> endobj 2609 0 obj << /Limits [(find-database) (find-database)] /Names [(find-database) 192 0 R] >> endobj 2610 0 obj << /Limits [(foreignlibs) (foreignlibs)] /Names [(foreignlibs) 1740 0 R] >> endobj 2611 0 obj << /Limits [(glossary) (glossary)] /Names [(glossary) 1912 0 R] >> endobj 2612 0 obj << /Limits [(history) (history)] /Names [(history) 318 0 R] >> endobj 2613 0 obj << /Limits [(idp34481632) (idp34481632)] /Names [(idp34481632) 2289 0 R] >> endobj 2614 0 obj << /Limits [(idp36677040) (idp36677040)] /Names [(idp36677040) 1749 0 R] >> endobj 2615 0 obj << /Limits [(idp36679600) (idp36679600)] /Names [(idp36679600) 1752 0 R] >> endobj 2616 0 obj << /Limits [(idp36680352) (idp36680352)] /Names [(idp36680352) 2292 0 R] >> endobj 2617 0 obj << /Limits [(idp38453344) (idp38453344)] /Names [(idp38453344) 324 0 R] >> endobj 2618 0 obj << /Limits [(idp38458784) (idp38458784)] /Names [(idp38458784) 327 0 R] >> endobj 2619 0 obj << /Limits [(idp39019424) (idp39019424)] /Names [(idp39019424) 1746 0 R] >> endobj 2620 0 obj << /Limits [(idp39355072) (idp39355072)] /Names [(idp39355072) 330 0 R] >> endobj 2621 0 obj << /Limits [(idp39358208) (idp39358208)] /Names [(idp39358208) 333 0 R] >> endobj 2622 0 obj << /Limits [(idp40098736) (idp40098736)] /Names [(idp40098736) 2293 0 R] >> endobj 2623 0 obj << /Limits [(idp40541360) (idp40541360)] /Names [(idp40541360) 366 0 R] >> endobj 2624 0 obj << /Limits [(idp40573376) (idp40573376)] /Names [(idp40573376) 336 0 R] >> endobj 2625 0 obj << /Limits [(idp40586448) (idp40586448)] /Names [(idp40586448) 342 0 R] >> endobj 2626 0 obj << /Limits [(idp40589952) (idp40589952)] /Names [(idp40589952) 345 0 R] >> endobj 2627 0 obj << /Limits [(idp40595440) (idp40595440)] /Names [(idp40595440) 2290 0 R] >> endobj 2628 0 obj << /Limits [(idp40600320) (idp40600320)] /Names [(idp40600320) 2291 0 R] >> endobj 2629 0 obj << /Limits [(idp40607328) (idp40607328)] /Names [(idp40607328) 348 0 R] >> endobj 2630 0 obj << /Limits [(idp40614736) (idp40614736)] /Names [(idp40614736) 351 0 R] >> endobj 2631 0 obj << /Limits [(idp40619744) (idp40619744)] /Names [(idp40619744) 354 0 R] >> endobj 2632 0 obj << /Limits [(idp40627744) (idp40627744)] /Names [(idp40627744) 357 0 R] >> endobj 2633 0 obj << /Limits [(idp45581152) (idp45581152)] /Names [(idp45581152) 1755 0 R] >> endobj 2634 0 obj << /Limits [(idp45583536) (idp45583536)] /Names [(idp45583536) 1761 0 R] >> endobj 2635 0 obj << /Limits [(idp45585600) (idp45585600)] /Names [(idp45585600) 1764 0 R] >> endobj 2636 0 obj << /Limits [(idp45588176) (idp45588176)] /Names [(idp45588176) 1767 0 R] >> endobj 2637 0 obj << /Limits [(idp45588928) (idp45588928)] /Names [(idp45588928) 2294 0 R] >> endobj 2638 0 obj << /Limits [(idp46309088) (idp46309088)] /Names [(idp46309088) 2295 0 R] >> endobj 2639 0 obj << /Limits [(idp46327104) (idp46327104)] /Names [(idp46327104) 1812 0 R] >> endobj 2640 0 obj << /Limits [(idp46329488) (idp46329488)] /Names [(idp46329488) 1819 0 R] >> endobj 2641 0 obj << /Limits [(idp46335776) (idp46335776)] /Names [(idp46335776) 1822 0 R] >> endobj 2642 0 obj << /Limits [(idp46338944) (idp46338944)] /Names [(idp46338944) 1825 0 R] >> endobj 2643 0 obj << /Limits [(idp46339696) (idp46339696)] /Names [(idp46339696) 2296 0 R] >> endobj 2644 0 obj << /Limits [(idp46343568) (idp46343568)] /Names [(idp46343568) 2297 0 R] >> endobj 2645 0 obj << /Limits [(idp46357952) (idp46357952)] /Names [(idp46357952) 1828 0 R] >> endobj 2646 0 obj << /Limits [(idp46358528) (idp46358528)] /Names [(idp46358528) 2298 0 R] >> endobj 2647 0 obj << /Limits [(idp46368832) (idp46368832)] /Names [(idp46368832) 2299 0 R] >> endobj 2648 0 obj << /Limits [(idp46373008) (idp46373008)] /Names [(idp46373008) 2300 0 R] >> endobj 2649 0 obj << /Limits [(idp46387184) (idp46387184)] /Names [(idp46387184) 1834 0 R] >> endobj 2650 0 obj << /Limits [(idp46395808) (idp46395808)] /Names [(idp46395808) 1837 0 R] >> endobj 2651 0 obj << /Limits [(idp46399744) (idp46399744)] /Names [(idp46399744) 1840 0 R] >> endobj 2652 0 obj << /Limits [(idp46400496) (idp46400496)] /Names [(idp46400496) 2301 0 R] >> endobj 2653 0 obj << /Limits [(idp46403920) (idp46403920)] /Names [(idp46403920) 2302 0 R] >> endobj 2654 0 obj << /Limits [(idp46414208) (idp46414208)] /Names [(idp46414208) 1843 0 R] >> endobj 2655 0 obj << /Limits [(idp46414784) (idp46414784)] /Names [(idp46414784) 2303 0 R] >> endobj 2656 0 obj << /Limits [(idp46417856) (idp46417856)] /Names [(idp46417856) 1846 0 R] >> endobj 2657 0 obj << /Limits [(idp46422928) (idp46422928)] /Names [(idp46422928) 1852 0 R] >> endobj 2658 0 obj << /Limits [(idp46426976) (idp46426976)] /Names [(idp46426976) 1855 0 R] >> endobj 2659 0 obj << /Limits [(idp46430912) (idp46430912)] /Names [(idp46430912) 1858 0 R] >> endobj 2660 0 obj << /Limits [(idp46431664) (idp46431664)] /Names [(idp46431664) 2304 0 R] >> endobj 2661 0 obj << /Limits [(idp46434640) (idp46434640)] /Names [(idp46434640) 2305 0 R] >> endobj 2662 0 obj << /Limits [(idp46442640) (idp46442640)] /Names [(idp46442640) 1861 0 R] >> endobj 2663 0 obj << /Limits [(idp46445424) (idp46445424)] /Names [(idp46445424) 1867 0 R] >> endobj 2664 0 obj << /Limits [(idp46448912) (idp46448912)] /Names [(idp46448912) 1870 0 R] >> endobj 2665 0 obj << /Limits [(idp46452848) (idp46452848)] /Names [(idp46452848) 1873 0 R] >> endobj 2666 0 obj << /Limits [(idp46453600) (idp46453600)] /Names [(idp46453600) 2306 0 R] >> endobj 2667 0 obj << /Limits [(idp46455680) (idp46455680)] /Names [(idp46455680) 2307 0 R] >> endobj 2668 0 obj << /Limits [(idp46460080) (idp46460080)] /Names [(idp46460080) 1876 0 R] >> endobj 2669 0 obj << /Limits [(idp46460656) (idp46460656)] /Names [(idp46460656) 2308 0 R] >> endobj 2670 0 obj << /Limits [(idp46465632) (idp46465632)] /Names [(idp46465632) 2309 0 R] >> endobj 2671 0 obj << /Limits [(idp46471760) (idp46471760)] /Names [(idp46471760) 2310 0 R] >> endobj 2672 0 obj << /Limits [(idp46479488) (idp46479488)] /Names [(idp46479488) 1882 0 R] >> endobj 2673 0 obj << /Limits [(idp46482976) (idp46482976)] /Names [(idp46482976) 1885 0 R] >> endobj 2674 0 obj << /Limits [(idp46486912) (idp46486912)] /Names [(idp46486912) 1888 0 R] >> endobj 2675 0 obj << /Limits [(idp46487664) (idp46487664)] /Names [(idp46487664) 2311 0 R] >> endobj 2676 0 obj << /Limits [(idp46490192) (idp46490192)] /Names [(idp46490192) 2312 0 R] >> endobj 2677 0 obj << /Limits [(idp46501664) (idp46501664)] /Names [(idp46501664) 1891 0 R] >> endobj 2678 0 obj << /Limits [(idp46502240) (idp46502240)] /Names [(idp46502240) 2313 0 R] >> endobj 2679 0 obj << /Limits [(idp46507216) (idp46507216)] /Names [(idp46507216) 2314 0 R] >> endobj 2680 0 obj << /Limits [(idp46513344) (idp46513344)] /Names [(idp46513344) 2315 0 R] >> endobj 2681 0 obj << /Limits [(idp46520672) (idp46520672)] /Names [(idp46520672) 1897 0 R] >> endobj 2682 0 obj << /Limits [(idp46524576) (idp46524576)] /Names [(idp46524576) 1900 0 R] >> endobj 2683 0 obj << /Limits [(idp46530112) (idp46530112)] /Names [(idp46530112) 1903 0 R] >> endobj 2684 0 obj << /Limits [(idp46533280) (idp46533280)] /Names [(idp46533280) 1906 0 R] >> endobj 2685 0 obj << /Limits [(idp46534032) (idp46534032)] /Names [(idp46534032) 2316 0 R] >> endobj 2686 0 obj << /Limits [(idp46537008) (idp46537008)] /Names [(idp46537008) 2317 0 R] >> endobj 2687 0 obj << /Limits [(idp46545136) (idp46545136)] /Names [(idp46545136) 1909 0 R] >> endobj 2688 0 obj << /Limits [(idp46545712) (idp46545712)] /Names [(idp46545712) 2318 0 R] >> endobj 2689 0 obj << /Limits [(idp46959488) (idp46959488)] /Names [(idp46959488) 2319 0 R] >> endobj 2690 0 obj << /Limits [(in-transaction-p) (in-transaction-p)] /Names [(in-transaction-p) 1085 0 R] >> endobj 2691 0 obj << /Limits [(index-exists-p) (index-exists-p)] /Names [(index-exists-p) 685 0 R] >> endobj 2692 0 obj << /Limits [(indexes) (indexes)] /Names [(indexes) 1732 0 R] >> endobj 2693 0 obj << /Limits [(initialize-database-type) (initialize-database-type)] /Names [(initialize-database-type) 155 0 R] >> endobj 2694 0 obj << /Limits [(initialized-database-types) (initialized-database-types)] /Names [(initialized-database-types) 166 0 R] >> endobj 2695 0 obj << /Limits [(insert-records) (insert-records)] /Names [(insert-records) 869 0 R] >> endobj 2696 0 obj << /Limits [(installation) (installation)] /Names [(installation) 339 0 R] >> endobj 2697 0 obj << /Limits [(instance-refreshed) (instance-refreshed)] /Names [(instance-refreshed) 1236 0 R] >> endobj 2698 0 obj << /Limits [(introduction) (introduction)] /Names [(introduction) 312 0 R] >> endobj 2699 0 obj << /Limits [(list-attribute-types) (list-attribute-types)] /Names [(list-attribute-types) 716 0 R] >> endobj 2700 0 obj << /Limits [(list-attributes) (list-attributes)] /Names [(list-attributes) 727 0 R] >> endobj 2701 0 obj << /Limits [(list-classes) (list-classes)] /Names [(list-classes) 1624 0 R] >> endobj 2702 0 obj << /Limits [(list-databases) (list-databases)] /Names [(list-databases) 267 0 R] >> endobj 2703 0 obj << /Limits [(list-indexes) (list-indexes)] /Names [(list-indexes) 677 0 R] >> endobj 2704 0 obj << /Limits [(list-sequences) (list-sequences)] /Names [(list-sequences) 750 0 R] >> endobj 2705 0 obj << /Limits [(list-sql-streams) (list-sql-streams)] /Names [(list-sql-streams) 1355 0 R] >> endobj 2706 0 obj << /Limits [(list-tables) (list-tables)] /Names [(list-tables) 589 0 R] >> endobj 2707 0 obj << /Limits [(list-views) (list-views)] /Names [(list-views) 634 0 R] >> endobj 2708 0 obj << /Limits [(locally-disable-sql-reader-syntax) (locally-disable-sql-reader-syntax)] /Names [(locally-disable-sql-reader-syntax) 484 0 R] >> endobj 2709 0 obj << /Limits [(locally-enable-sql-reader-syntax) (locally-enable-sql-reader-syntax)] /Names [(locally-enable-sql-reader-syntax) 481 0 R] >> endobj 2710 0 obj << /Limits [(loop-tuples) (loop-tuples)] /Names [(loop-tuples) 915 0 R] >> endobj 2711 0 obj << /Limits [(map-query) (map-query)] /Names [(map-query) 913 0 R] >> endobj 2712 0 obj << /Limits [(mysql) (mysql)] /Names [(mysql) 1816 0 R] >> endobj 2713 0 obj << /Limits [(odbc) (odbc)] /Names [(odbc) 1831 0 R] >> endobj 2714 0 obj << /Limits [(oracle) (oracle)] /Names [(oracle) 1894 0 R] >> endobj 2715 0 obj << /Limits [(postgresql) (postgresql)] /Names [(postgresql) 1743 0 R] >> endobj 2716 0 obj << /Limits [(postgresql-socket) (postgresql-socket)] /Names [(postgresql-socket) 1758 0 R] >> endobj 2717 0 obj << /Limits [(preface) (preface)] /Names [(preface) 308 0 R] >> endobj 2718 0 obj << /Limits [(prerequisites) (prerequisites)] /Names [(prerequisites) 321 0 R] >> endobj 2719 0 obj << /Limits [(print-query) (print-query)] /Names [(print-query) 920 0 R] >> endobj 2720 0 obj << /Limits [(probe-database) (probe-database)] /Names [(probe-database) 259 0 R] >> endobj 2721 0 obj << /Limits [(purpose) (purpose)] /Names [(purpose) 315 0 R] >> endobj 2722 0 obj << /Limits [(query) (query)] /Names [(query) 882 0 R] >> endobj 2723 0 obj << /Limits [(reconnect) (reconnect)] /Names [(reconnect) 189 0 R] >> endobj 2724 0 obj << /Limits [(ref-conditions) (ref-conditions)] /Names [(ref-conditions) 1705 0 R] >> endobj 2725 0 obj << /Limits [(ref-connect) (ref-connect)] /Names [(ref-connect) 384 0 R] >> endobj 2726 0 obj << /Limits [(ref-fddl) (ref-fddl)] /Names [(ref-fddl) 997 0 R] >> endobj 2727 0 obj << /Limits [(ref-fdml) (ref-fdml)] /Names [(ref-fdml) 1047 0 R] >> endobj 2728 0 obj << /Limits [(ref-ooddl) (ref-ooddl)] /Names [(ref-ooddl) 1281 0 R] >> endobj 2729 0 obj << /Limits [(ref-oodml) (ref-oodml)] /Names [(ref-oodml) 1662 0 R] >> endobj 2730 0 obj << /Limits [(ref-recording) (ref-recording)] /Names [(ref-recording) 1688 0 R] >> endobj 2731 0 obj << /Limits [(ref-syntax) (ref-syntax)] /Names [(ref-syntax) 435 0 R] >> endobj 2732 0 obj << /Limits [(ref-transaction) (ref-transaction)] /Names [(ref-transaction) 1074 0 R] >> endobj 2733 0 obj << /Limits [(restore-sql-reader-syntax-state) (restore-sql-reader-syntax-state)] /Names [(restore-sql-reader-syntax-state) 471 0 R] >> endobj 2734 0 obj << /Limits [(rollback) (rollback)] /Names [(rollback) 969 0 R] >> endobj 2735 0 obj << /Limits [(select) (select)] /Names [(select) 909 0 R] >> endobj 2736 0 obj << /Limits [(sequence-exists-p) (sequence-exists-p)] /Names [(sequence-exists-p) 768 0 R] >> endobj 2737 0 obj << /Limits [(sequence-last) (sequence-last)] /Names [(sequence-last) 752 0 R] >> endobj 2738 0 obj << /Limits [(sequence-next) (sequence-next)] /Names [(sequence-next) 771 0 R] >> endobj 2739 0 obj << /Limits [(set-autocommit) (set-autocommit)] /Names [(set-autocommit) 1093 0 R] >> endobj 2740 0 obj << /Limits [(set-sequence-position) (set-sequence-position)] /Names [(set-sequence-position) 788 0 R] >> endobj 2741 0 obj << /Limits [(sql) (sql)] /Names [(sql) 560 0 R] >> endobj 2742 0 obj << /Limits [(sql-condition) (sql-condition)] /Names [(sql-condition) 1396 0 R] >> endobj 2743 0 obj << /Limits [(sql-connection-error) (sql-connection-error)] /Names [(sql-connection-error) 1469 0 R] >> endobj 2744 0 obj << /Limits [(sql-database-data-error) (sql-database-data-error)] /Names [(sql-database-data-error) 1559 0 R] >> endobj 2745 0 obj << /Limits [(sql-database-error) (sql-database-error)] /Names [(sql-database-error) 1461 0 R] >> endobj 2746 0 obj << /Limits [(sql-database-warning) (sql-database-warning)] /Names [(sql-database-warning) 1422 0 R] >> endobj 2747 0 obj << /Limits [(sql-error) (sql-error)] /Names [(sql-error) 1408 0 R] >> endobj 2748 0 obj << /Limits [(sql-expression) (sql-expression)] /Names [(sql-expression) 563 0 R] >> endobj 2749 0 obj << /Limits [(sql-fatal-error) (sql-fatal-error)] /Names [(sql-fatal-error) 1570 0 R] >> endobj 2750 0 obj << /Limits [(sql-operation) (sql-operation)] /Names [(sql-operation) 565 0 R] >> endobj 2751 0 obj << /Limits [(sql-operator) (sql-operator)] /Names [(sql-operator) 994 0 R] >> endobj 2752 0 obj << /Limits [(sql-recording-p) (sql-recording-p)] /Names [(sql-recording-p) 1334 0 R] >> endobj 2753 0 obj << /Limits [(sql-stream) (sql-stream)] /Names [(sql-stream) 1349 0 R] >> endobj 2754 0 obj << /Limits [(sql-temporary-error) (sql-temporary-error)] /Names [(sql-temporary-error) 1581 0 R] >> endobj 2755 0 obj << /Limits [(sql-timeout-error) (sql-timeout-error)] /Names [(sql-timeout-error) 1584 0 R] >> endobj 2756 0 obj << /Limits [(sql-user-error) (sql-user-error)] /Names [(sql-user-error) 1436 0 R] >> endobj 2757 0 obj << /Limits [(sql-warning) (sql-warning)] /Names [(sql-warning) 1415 0 R] >> endobj 2758 0 obj << /Limits [(sqlite) (sqlite)] /Names [(sqlite) 1864 0 R] >> endobj 2759 0 obj << /Limits [(sqlite3) (sqlite3)] /Names [(sqlite3) 1879 0 R] >> endobj 2760 0 obj << /Limits [(standard-db-object) (standard-db-object)] /Names [(standard-db-object) 1213 0 R] >> endobj 2761 0 obj << /Limits [(start-sql-recording) (start-sql-recording)] /Names [(start-sql-recording) 1331 0 R] >> endobj 2762 0 obj << /Limits [(start-transaction) (start-transaction)] /Names [(start-transaction) 1077 0 R] >> endobj 2763 0 obj << /Limits [(status) (status)] /Names [(status) 194 0 R] >> endobj 2764 0 obj << /Limits [(stop-sql-recording) (stop-sql-recording)] /Names [(stop-sql-recording) 1341 0 R] >> endobj 2765 0 obj << /Limits [(table-exists-p) (table-exists-p)] /Names [(table-exists-p) 597 0 R] >> endobj 2766 0 obj << /Limits [(truncate-database) (truncate-database)] /Names [(truncate-database) 1044 0 R] >> endobj 2767 0 obj << /Limits [(update-instance-from-records) (update-instance-from-records)] /Names [(update-instance-from-records) 1288 0 R] >> endobj 2768 0 obj << /Limits [(update-objects-joins) (update-objects-joins)] /Names [(update-objects-joins) 1299 0 R] >> endobj 2769 0 obj << /Limits [(update-record-from-slot) (update-record-from-slot)] /Names [(update-record-from-slot) 1254 0 R] >> endobj 2770 0 obj << /Limits [(update-record-from-slots) (update-record-from-slots)] /Names [(update-record-from-slots) 1257 0 R] >> endobj 2771 0 obj << /Limits [(update-records) (update-records)] /Names [(update-records) 861 0 R] >> endobj 2772 0 obj << /Limits [(update-records-from-instance) (update-records-from-instance)] /Names [(update-records-from-instance) 1249 0 R] >> endobj 2773 0 obj << /Limits [(update-slot-from-record) (update-slot-from-record)] /Names [(update-slot-from-record) 1285 0 R] >> endobj 2774 0 obj << /Limits [(view-exists-p) (view-exists-p)] /Names [(view-exists-p) 642 0 R] >> endobj 2775 0 obj << /Limits [(with-database) (with-database)] /Names [(with-database) 289 0 R] >> endobj 2776 0 obj << /Limits [(with-default-database) (with-default-database)] /Names [(with-default-database) 300 0 R] >> endobj 2777 0 obj << /Limits [(with-transaction) (with-transaction)] /Names [(with-transaction) 1120 0 R] >> endobj 2778 0 obj << /Limits [(add-sql-stream) (with-transaction)] /Kids [2554 0 R 2555 0 R 2556 0 R 2557 0 R 2558 0 R 2559 0 R 2560 0 R 2561 0 R 2562 0 R 2563 0 R 2564 0 R 2565 0 R 2566 0 R 2567 0 R 2568 0 R 2569 0 R 2570 0 R 2571 0 R 2572 0 R 2573 0 R 2574 0 R 2575 0 R 2576 0 R 2577 0 R 2578 0 R 2579 0 R 2580 0 R 2581 0 R 2582 0 R 2583 0 R 2584 0 R 2585 0 R 2586 0 R 2587 0 R 2588 0 R 2589 0 R 2590 0 R 2591 0 R 2592 0 R 2593 0 R 2594 0 R 2595 0 R 2596 0 R 2597 0 R 2598 0 R 2599 0 R 2600 0 R 2601 0 R 2602 0 R 2603 0 R 2604 0 R 2605 0 R 2606 0 R 2607 0 R 2608 0 R 2609 0 R 2610 0 R 2611 0 R 2612 0 R 2613 0 R 2614 0 R 2615 0 R 2616 0 R 2617 0 R 2618 0 R 2619 0 R 2620 0 R 2621 0 R 2622 0 R 2623 0 R 2624 0 R 2625 0 R 2626 0 R 2627 0 R 2628 0 R 2629 0 R 2630 0 R 2631 0 R 2632 0 R 2633 0 R 2634 0 R 2635 0 R 2636 0 R 2637 0 R 2638 0 R 2639 0 R 2640 0 R 2641 0 R 2642 0 R 2643 0 R 2644 0 R 2645 0 R 2646 0 R 2647 0 R 2648 0 R 2649 0 R 2650 0 R 2651 0 R 2652 0 R 2653 0 R 2654 0 R 2655 0 R 2656 0 R 2657 0 R 2658 0 R 2659 0 R 2660 0 R 2661 0 R 2662 0 R 2663 0 R 2664 0 R 2665 0 R 2666 0 R 2667 0 R 2668 0 R 2669 0 R 2670 0 R 2671 0 R 2672 0 R 2673 0 R 2674 0 R 2675 0 R 2676 0 R 2677 0 R 2678 0 R 2679 0 R 2680 0 R 2681 0 R 2682 0 R 2683 0 R 2684 0 R 2685 0 R 2686 0 R 2687 0 R 2688 0 R 2689 0 R 2690 0 R 2691 0 R 2692 0 R 2693 0 R 2694 0 R 2695 0 R 2696 0 R 2697 0 R 2698 0 R 2699 0 R 2700 0 R 2701 0 R 2702 0 R 2703 0 R 2704 0 R 2705 0 R 2706 0 R 2707 0 R 2708 0 R 2709 0 R 2710 0 R 2711 0 R 2712 0 R 2713 0 R 2714 0 R 2715 0 R 2716 0 R 2717 0 R 2718 0 R 2719 0 R 2720 0 R 2721 0 R 2722 0 R 2723 0 R 2724 0 R 2725 0 R 2726 0 R 2727 0 R 2728 0 R 2729 0 R 2730 0 R 2731 0 R 2732 0 R 2733 0 R 2734 0 R 2735 0 R 2736 0 R 2737 0 R 2738 0 R 2739 0 R 2740 0 R 2741 0 R 2742 0 R 2743 0 R 2744 0 R 2745 0 R 2746 0 R 2747 0 R 2748 0 R 2749 0 R 2750 0 R 2751 0 R 2752 0 R 2753 0 R 2754 0 R 2755 0 R 2756 0 R 2757 0 R 2758 0 R 2759 0 R 2760 0 R 2761 0 R 2762 0 R 2763 0 R 2764 0 R 2765 0 R 2766 0 R 2767 0 R 2768 0 R 2769 0 R 2770 0 R 2771 0 R 2772 0 R 2773 0 R 2774 0 R 2775 0 R 2776 0 R 2777 0 R] >> endobj 2779 0 obj << /Dests 2778 0 R >> endobj 1 0 obj << /Type /Pages /Count 252 /Kids [8 0 R 14 0 R 307 0 R 976 0 R 1644 0 R 1811 0 R 17 0 R 1917 0 R 20 0 R 23 0 R 26 0 R 29 0 R 48 0 R 51 0 R 1165 0 R 54 0 R 1171 0 R 57 0 R 60 0 R 63 0 R 66 0 R 69 0 R 78 0 R 117 0 R 72 0 R 124 0 R 154 0 R 160 0 R 75 0 R 86 0 R 185 0 R 94 0 R 198 0 R 97 0 R 206 0 R 100 0 R 103 0 R 217 0 R 108 0 R 138 0 R 131 0 R 148 0 R 226 0 R 151 0 R 165 0 R 172 0 R 175 0 R 182 0 R 238 0 R 263 0 R 247 0 R 271 0 R 250 0 R 278 0 R 253 0 R 285 0 R 295 0 R 288 0 R 304 0 R 464 0 R 470 0 R 480 0 R 490 0 R 500 0 R 509 0 R 518 0 R 443 0 R 529 0 R 446 0 R 449 0 R 543 0 R 550 0 R 1435 0 R 553 0 R 1444 0 R 556 0 R 1452 0 R 559 0 R 1635 0 R 569 0 R 572 0 R 593 0 R 575 0 R 601 0 R 581 0 R 607 0 R 584 0 R 614 0 R 617 0 R 638 0 R 620 0 R 646 0 R 626 0 R 652 0 R 629 0 R 659 0 R 662 0 R 681 0 R 665 0 R 689 0 R 668 0 R 696 0 R 671 0 R 703 0 R 706 0 R 726 0 R 709 0 R 712 0 R 720 0 R 733 0 R 781 0 R 736 0 R 739 0 R 792 0 R 764 0 R 801 0 R 745 0 R 806 0 R 812 0 R 756 0 R 759 0 R 822 0 R 775 0 R 831 0 R 1937 0 R 839 0 R 905 0 R 847 0 R 1943 0 R 853 0 R 1949 0 R 860 0 R 1955 0 R 868 0 R 1961 0 R 875 0 R 1967 0 R 881 0 R 1976 0 R 887 0 R 919 0 R 1987 0 R 929 0 R 1995 0 R 893 0 R 896 0 R 1229 0 R 899 0 R 2005 0 R 938 0 R 2016 0 R 947 0 R 902 0 R 2024 0 R 956 0 R 959 0 R 1098 0 R 2035 0 R 1114 0 R 2041 0 R 1124 0 R 2047 0 R 1134 0 R 2053 0 R 1104 0 R 2060 0 R 1144 0 R 2068 0 R 968 0 R 2075 0 R 1111 0 R 2085 0 R 1150 0 R 1195 0 R 1159 0 R 1162 0 R 2147 0 R 1205 0 R 2162 0 R 1176 0 R 2168 0 R 1183 0 R 1186 0 R 1189 0 R 1192 0 R 1210 0 R 2174 0 R 2091 0 R 1218 0 R 1280 0 R 2186 0 R 1253 0 R 1223 0 R 1298 0 R 2197 0 R 1240 0 R 2205 0 R 1245 0 R 2213 0 R 1261 0 R 2223 0 R 1268 0 R 2233 0 R 1274 0 R 2243 0 R 1306 0 R 2253 0 R 1312 0 R 2263 0 R 1318 0 R 1327 0 R 2097 0 R 1345 0 R 2103 0 R 1330 0 R 2109 0 R 1338 0 R 2117 0 R 1359 0 R 2124 0 R 1366 0 R 2130 0 R 1374 0 R 2136 0 R 1385 0 R 1401 0 R 1392 0 R 1395 0 R 1407 0 R 1414 0 R 1421 0 R 1429 0 R 1460 0 R 1468 0 R 1477 0 R 1484 0 R 1491 0 R 1499 0 R 1507 0 R 1510 0 R 1618 0 R 1632 0 R 1641 0 R 1772 0 R 2273 0 R 1775 0 R 1778 0 R 1781 0 R 1786 0 R 1791 0 R 1797 0 R 2144 0 R ] >> endobj 2 0 obj << /Type /Catalog /Pages 1 0 R /Metadata 7 0 R /Lang (en) /PageLabels 9 0 R /Outlines 2320 0 R /PageMode /UseOutlines /Names 2779 0 R >> endobj 3 0 obj << /Font << /F10 2547 0 R /F5 2548 0 R /F4 2549 0 R /F3 2550 0 R /F9 2551 0 R /F6 2552 0 R /F7 2553 0 R >> /ProcSet [ /PDF /ImageB /ImageC /Text ] /ColorSpace << /DefaultRGB 6 0 R >> >> endobj 9 0 obj << /Nums [0 << /P (1) >> 1 << /P (2) >> 2 << /P (iii) >> 3 << /P (iv) >> 4 << /P (v) >> 5 << /P (vi) >> 6 << /P (vii) >> 7 << /P (1) >> 8 << /P (2) >> 9 << /P (3) >> 10 << /P (4) >> 11 << /P (5) >> 12 << /P (6) >> 13 << /P (7) >> 14 << /P (8) >> 15 << /P (9) >> 16 << /P (10) >> 17 << /P (11) >> 18 << /P (12) >> 19 << /P (13) >> 20 << /P (14) >> 21 << /P (15) >> 22 << /P (16) >> 23 << /P (17) >> 24 << /P (18) >> 25 << /P (19) >> 26 << /P (20) >> 27 << /P (21) >> 28 << /P (22) >> 29 << /P (23) >> 30 << /P (24) >> 31 << /P (25) >> 32 << /P (26) >> 33 << /P (27) >> 34 << /P (28) >> 35 << /P (29) >> 36 << /P (30) >> 37 << /P (31) >> 38 << /P (32) >> 39 << /P (33) >> 40 << /P (34) >> 41 << /P (35) >> 42 << /P (36) >> 43 << /P (37) >> 44 << /P (38) >> 45 << /P (39) >> 46 << /P (40) >> 47 << /P (41) >> 48 << /P (42) >> 49 << /P (43) >> 50 << /P (44) >> 51 << /P (45) >> 52 << /P (46) >> 53 << /P (47) >> 54 << /P (48) >> 55 << /P (49) >> 56 << /P (50) >> 57 << /P (51) >> 58 << /P (52) >> 59 << /P (53) >> 60 << /P (54) >> 61 << /P (55) >> 62 << /P (56) >> 63 << /P (57) >> 64 << /P (58) >> 65 << /P (59) >> 66 << /P (60) >> 67 << /P (61) >> 68 << /P (62) >> 69 << /P (63) >> 70 << /P (64) >> 71 << /P (65) >> 72 << /P (66) >> 73 << /P (67) >> 74 << /P (68) >> 75 << /P (69) >> 76 << /P (70) >> 77 << /P (71) >> 78 << /P (72) >> 79 << /P (73) >> 80 << /P (74) >> 81 << /P (75) >> 82 << /P (76) >> 83 << /P (77) >> 84 << /P (78) >> 85 << /P (79) >> 86 << /P (80) >> 87 << /P (81) >> 88 << /P (82) >> 89 << /P (83) >> 90 << /P (84) >> 91 << /P (85) >> 92 << /P (86) >> 93 << /P (87) >> 94 << /P (88) >> 95 << /P (89) >> 96 << /P (90) >> 97 << /P (91) >> 98 << /P (92) >> 99 << /P (93) >> 100 << /P (94) >> 101 << /P (95) >> 102 << /P (96) >> 103 << /P (97) >> 104 << /P (98) >> 105 << /P (99) >> 106 << /P (100) >> 107 << /P (101) >> 108 << /P (102) >> 109 << /P (103) >> 110 << /P (104) >> 111 << /P (105) >> 112 << /P (106) >> 113 << /P (107) >> 114 << /P (108) >> 115 << /P (109) >> 116 << /P (110) >> 117 << /P (111) >> 118 << /P (112) >> 119 << /P (113) >> 120 << /P (114) >> 121 << /P (115) >> 122 << /P (116) >> 123 << /P (117) >> 124 << /P (118) >> 125 << /P (119) >> 126 << /P (120) >> 127 << /P (121) >> 128 << /P (122) >> 129 << /P (123) >> 130 << /P (124) >> 131 << /P (125) >> 132 << /P (126) >> 133 << /P (127) >> 134 << /P (128) >> 135 << /P (129) >> 136 << /P (130) >> 137 << /P (131) >> 138 << /P (132) >> 139 << /P (133) >> 140 << /P (134) >> 141 << /P (135) >> 142 << /P (136) >> 143 << /P (137) >> 144 << /P (138) >> 145 << /P (139) >> 146 << /P (140) >> 147 << /P (141) >> 148 << /P (142) >> 149 << /P (143) >> 150 << /P (144) >> 151 << /P (145) >> 152 << /P (146) >> 153 << /P (147) >> 154 << /P (148) >> 155 << /P (149) >> 156 << /P (150) >> 157 << /P (151) >> 158 << /P (152) >> 159 << /P (153) >> 160 << /P (154) >> 161 << /P (155) >> 162 << /P (156) >> 163 << /P (157) >> 164 << /P (158) >> 165 << /P (159) >> 166 << /P (160) >> 167 << /P (161) >> 168 << /P (162) >> 169 << /P (163) >> 170 << /P (164) >> 171 << /P (165) >> 172 << /P (166) >> 173 << /P (167) >> 174 << /P (168) >> 175 << /P (169) >> 176 << /P (170) >> 177 << /P (171) >> 178 << /P (172) >> 179 << /P (173) >> 180 << /P (174) >> 181 << /P (175) >> 182 << /P (176) >> 183 << /P (177) >> 184 << /P (178) >> 185 << /P (179) >> 186 << /P (180) >> 187 << /P (181) >> 188 << /P (182) >> 189 << /P (183) >> 190 << /P (184) >> 191 << /P (185) >> 192 << /P (186) >> 193 << /P (187) >> 194 << /P (188) >> 195 << /P (189) >> 196 << /P (190) >> 197 << /P (191) >> 198 << /P (192) >> 199 << /P (193) >> 200 << /P (194) >> 201 << /P (195) >> 202 << /P (196) >> 203 << /P (197) >> 204 << /P (198) >> 205 << /P (199) >> 206 << /P (200) >> 207 << /P (201) >> 208 << /P (202) >> 209 << /P (203) >> 210 << /P (204) >> 211 << /P (205) >> 212 << /P (206) >> 213 << /P (207) >> 214 << /P (208) >> 215 << /P (209) >> 216 << /P (210) >> 217 << /P (211) >> 218 << /P (212) >> 219 << /P (213) >> 220 << /P (214) >> 221 << /P (215) >> 222 << /P (216) >> 223 << /P (217) >> 224 << /P (218) >> 225 << /P (219) >> 226 << /P (220) >> 227 << /P (221) >> 228 << /P (222) >> 229 << /P (223) >> 230 << /P (224) >> 231 << /P (225) >> 232 << /P (226) >> 233 << /P (227) >> 234 << /P (228) >> 235 << /P (229) >> 236 << /P (230) >> 237 << /P (231) >> 238 << /P (232) >> 239 << /P (233) >> 240 << /P (234) >> 241 << /P (235) >> 242 << /P (236) >> 243 << /P (237) >> 244 << /P (238) >> 245 << /P (239) >> 246 << /P (240) >> 247 << /P (241) >> 248 << /P (242) >> 249 << /P (243) >> 250 << /P (244) >> 251 << /P (245) >> ] >> endobj 2320 0 obj << /First 2321 0 R /Last 2546 0 R >> endobj xref 0 2780 0000000000 65535 f 0000651535 00000 n 0000653700 00000 n 0000653869 00000 n 0000000015 00000 n 0000000277 00000 n 0000002959 00000 n 0000002992 00000 n 0000004373 00000 n 0000654086 00000 n 0000004021 00000 n 0000004565 00000 n 0000004586 00000 n 0000004606 00000 n 0000005358 00000 n 0000004626 00000 n 0000005551 00000 n 0000006182 00000 n 0000005571 00000 n 0000006375 00000 n 0000007968 00000 n 0000006395 00000 n 0000008161 00000 n 0000010658 00000 n 0000008182 00000 n 0000010851 00000 n 0000011392 00000 n 0000010872 00000 n 0000011585 00000 n 0000016124 00000 n 0000011605 00000 n 0000011711 00000 n 0000016027 00000 n 0000011849 00000 n 0000011989 00000 n 0000012126 00000 n 0000012231 00000 n 0000012367 00000 n 0000012505 00000 n 0000012639 00000 n 0000012739 00000 n 0000012877 00000 n 0000013017 00000 n 0000013154 00000 n 0000013242 00000 n 0000013373 00000 n 0000013507 00000 n 0000016334 00000 n 0000017902 00000 n 0000016355 00000 n 0000018095 00000 n 0000021025 00000 n 0000018116 00000 n 0000021218 00000 n 0000023306 00000 n 0000021239 00000 n 0000023499 00000 n 0000025387 00000 n 0000023520 00000 n 0000025580 00000 n 0000027474 00000 n 0000025601 00000 n 0000027667 00000 n 0000029025 00000 n 0000027688 00000 n 0000029218 00000 n 0000029737 00000 n 0000029239 00000 n 0000029930 00000 n 0000030635 00000 n 0000029950 00000 n 0000030828 00000 n 0000032502 00000 n 0000030848 00000 n 0000032695 00000 n 0000035165 00000 n 0000032716 00000 n 0000035358 00000 n 0000036909 00000 n 0000035379 00000 n 0000035457 00000 n 0000036868 00000 n 0000035593 00000 n 0000035731 00000 n 0000035867 00000 n 0000037119 00000 n 0000039205 00000 n 0000059621 00000 n 0000037139 00000 n 0000039171 00000 n 0000037272 00000 n 0000037350 00000 n 0000037483 00000 n 0000039415 00000 n 0000040577 00000 n 0000039436 00000 n 0000040770 00000 n 0000042483 00000 n 0000040791 00000 n 0000042676 00000 n 0000044116 00000 n 0000042697 00000 n 0000044311 00000 n 0000045350 00000 n 0000044333 00000 n 0000045321 00000 n 0000044470 00000 n 0000045563 00000 n 0000048291 00000 n 0000045584 00000 n 0000045663 00000 n 0000048246 00000 n 0000045801 00000 n 0000048526 00000 n 0000045939 00000 n 0000046080 00000 n 0000048504 00000 n 0000050019 00000 n 0000048606 00000 n 0000049982 00000 n 0000048743 00000 n 0000048823 00000 n 0000048961 00000 n 0000050232 00000 n 0000051711 00000 n 0000050253 00000 n 0000051666 00000 n 0000050390 00000 n 0000050528 00000 n 0000050666 00000 n 0000051924 00000 n 0000053644 00000 n 0000051945 00000 n 0000053599 00000 n 0000052082 00000 n 0000052219 00000 n 0000052357 00000 n 0000053857 00000 n 0000055302 00000 n 0000053879 00000 n 0000053958 00000 n 0000055249 00000 n 0000054097 00000 n 0000054236 00000 n 0000054373 00000 n 0000054453 00000 n 0000054591 00000 n 0000055515 00000 n 0000057564 00000 n 0000055536 00000 n 0000057759 00000 n 0000059404 00000 n 0000057781 00000 n 0000059599 00000 n 0000061162 00000 n 0000059700 00000 n 0000059780 00000 n 0000061133 00000 n 0000059918 00000 n 0000061375 00000 n 0000062753 00000 n 0000061397 00000 n 0000062724 00000 n 0000061535 00000 n 0000062966 00000 n 0000064124 00000 n 0000062988 00000 n 0000063068 00000 n 0000064087 00000 n 0000063206 00000 n 0000063343 00000 n 0000064337 00000 n 0000066328 00000 n 0000064358 00000 n 0000066523 00000 n 0000067519 00000 n 0000066545 00000 n 0000067474 00000 n 0000066682 00000 n 0000066820 00000 n 0000066958 00000 n 0000067732 00000 n 0000068958 00000 n 0000067753 00000 n 0000069153 00000 n 0000071095 00000 n 0000069175 00000 n 0000071026 00000 n 0000069313 00000 n 0000069451 00000 n 0000069531 00000 n 0000069669 00000 n 0000069806 00000 n 0000069886 00000 n 0000070024 00000 n 0000070104 00000 n 0000070242 00000 n 0000071308 00000 n 0000072429 00000 n 0000071329 00000 n 0000072376 00000 n 0000071467 00000 n 0000071604 00000 n 0000071742 00000 n 0000071880 00000 n 0000072642 00000 n 0000074334 00000 n 0000072663 00000 n 0000072743 00000 n 0000074265 00000 n 0000072881 00000 n 0000073018 00000 n 0000073156 00000 n 0000073294 00000 n 0000073432 00000 n 0000073570 00000 n 0000074547 00000 n 0000076521 00000 n 0000074568 00000 n 0000076460 00000 n 0000074705 00000 n 0000074843 00000 n 0000074981 00000 n 0000075119 00000 n 0000075257 00000 n 0000076734 00000 n 0000078927 00000 n 0000076756 00000 n 0000078850 00000 n 0000076894 00000 n 0000076973 00000 n 0000077111 00000 n 0000077249 00000 n 0000077387 00000 n 0000077524 00000 n 0000077662 00000 n 0000077800 00000 n 0000079140 00000 n 0000080435 00000 n 0000079161 00000 n 0000080374 00000 n 0000079299 00000 n 0000079436 00000 n 0000079574 00000 n 0000079711 00000 n 0000079849 00000 n 0000080648 00000 n 0000081315 00000 n 0000080669 00000 n 0000081510 00000 n 0000082183 00000 n 0000081531 00000 n 0000082378 00000 n 0000084149 00000 n 0000084384 00000 n 0000082399 00000 n 0000084104 00000 n 0000086602 00000 n 0000082537 00000 n 0000088705 00000 n 0000082675 00000 n 0000082813 00000 n 0000084362 00000 n 0000086367 00000 n 0000084464 00000 n 0000086322 00000 n 0000084601 00000 n 0000084737 00000 n 0000084817 00000 n 0000084953 00000 n 0000086580 00000 n 0000088470 00000 n 0000086682 00000 n 0000088425 00000 n 0000086819 00000 n 0000086955 00000 n 0000087091 00000 n 0000088683 00000 n 0000090509 00000 n 0000088785 00000 n 0000090464 00000 n 0000088923 00000 n 0000089061 00000 n 0000089199 00000 n 0000090722 00000 n 0000092395 00000 n 0000090744 00000 n 0000092590 00000 n 0000094254 00000 n 0000092612 00000 n 0000092692 00000 n 0000094217 00000 n 0000092828 00000 n 0000092965 00000 n 0000094467 00000 n 0000095674 00000 n 0000094489 00000 n 0000095621 00000 n 0000094626 00000 n 0000094764 00000 n 0000094902 00000 n 0000094982 00000 n 0000095120 00000 n 0000095887 00000 n 0000096339 00000 n 0000095908 00000 n 0000096534 00000 n 0000129171 00000 n 0000096555 00000 n 0000096634 00000 n 0000128334 00000 n 0000096773 00000 n 0000478410 00000 n 0000096915 00000 n 0000097055 00000 n 0000478491 00000 n 0000097197 00000 n 0000097336 00000 n 0000478574 00000 n 0000097478 00000 n 0000097616 00000 n 0000478656 00000 n 0000097758 00000 n 0000097897 00000 n 0000478739 00000 n 0000098039 00000 n 0000098178 00000 n 0000478822 00000 n 0000098320 00000 n 0000098459 00000 n 0000478905 00000 n 0000098601 00000 n 0000098740 00000 n 0000098882 00000 n 0000098961 00000 n 0000099101 00000 n 0000099241 00000 n 0000099322 00000 n 0000099462 00000 n 0000099604 00000 n 0000099685 00000 n 0000099823 00000 n 0000099965 00000 n 0000100046 00000 n 0000100186 00000 n 0000100326 00000 n 0000100407 00000 n 0000100547 00000 n 0000100687 00000 n 0000100768 00000 n 0000100907 00000 n 0000101049 00000 n 0000101130 00000 n 0000101270 00000 n 0000101412 00000 n 0000101493 00000 n 0000101633 00000 n 0000101775 00000 n 0000101856 00000 n 0000101996 00000 n 0000102138 00000 n 0000102217 00000 n 0000102356 00000 n 0000102498 00000 n 0000102579 00000 n 0000102718 00000 n 0000102860 00000 n 0000102941 00000 n 0000103081 00000 n 0000305221 00000 n 0000103223 00000 n 0000103363 00000 n 0000307578 00000 n 0000103505 00000 n 0000103645 00000 n 0000103787 00000 n 0000103868 00000 n 0000104007 00000 n 0000104149 00000 n 0000104228 00000 n 0000104368 00000 n 0000104510 00000 n 0000104591 00000 n 0000104730 00000 n 0000104872 00000 n 0000104951 00000 n 0000105090 00000 n 0000105232 00000 n 0000105311 00000 n 0000105450 00000 n 0000105592 00000 n 0000105730 00000 n 0000105871 00000 n 0000106010 00000 n 0000106152 00000 n 0000106291 00000 n 0000106433 00000 n 0000106571 00000 n 0000106712 00000 n 0000106851 00000 n 0000106993 00000 n 0000107131 00000 n 0000107272 00000 n 0000107411 00000 n 0000107553 00000 n 0000107691 00000 n 0000107833 00000 n 0000107971 00000 n 0000108113 00000 n 0000108193 00000 n 0000108332 00000 n 0000108474 00000 n 0000108613 00000 n 0000108755 00000 n 0000108893 00000 n 0000109035 00000 n 0000109174 00000 n 0000109316 00000 n 0000109455 00000 n 0000109597 00000 n 0000109735 00000 n 0000109877 00000 n 0000110016 00000 n 0000110158 00000 n 0000110297 00000 n 0000110439 00000 n 0000110578 00000 n 0000110720 00000 n 0000110859 00000 n 0000111001 00000 n 0000111140 00000 n 0000111282 00000 n 0000111421 00000 n 0000111563 00000 n 0000111702 00000 n 0000134078 00000 n 0000111844 00000 n 0000111983 00000 n 0000135323 00000 n 0000112124 00000 n 0000112261 00000 n 0000112401 00000 n 0000129384 00000 n 0000129982 00000 n 0000129407 00000 n 0000130177 00000 n 0000130700 00000 n 0000130198 00000 n 0000130895 00000 n 0000133843 00000 n 0000130916 00000 n 0000133758 00000 n 0000139353 00000 n 0000131058 00000 n 0000131200 00000 n 0000131338 00000 n 0000131441 00000 n 0000131581 00000 n 0000131721 00000 n 0000131826 00000 n 0000131964 00000 n 0000132102 00000 n 0000132238 00000 n 0000134056 00000 n 0000135089 00000 n 0000134158 00000 n 0000134238 00000 n 0000135060 00000 n 0000134376 00000 n 0000135302 00000 n 0000137672 00000 n 0000148531 00000 n 0000135403 00000 n 0000137611 00000 n 0000135541 00000 n 0000135679 00000 n 0000135817 00000 n 0000135957 00000 n 0000136093 00000 n 0000137885 00000 n 0000139119 00000 n 0000141676 00000 n 0000137907 00000 n 0000139066 00000 n 0000146062 00000 n 0000138041 00000 n 0000138175 00000 n 0000138309 00000 n 0000138443 00000 n 0000139332 00000 n 0000141441 00000 n 0000139433 00000 n 0000141372 00000 n 0000139571 00000 n 0000139709 00000 n 0000139847 00000 n 0000139985 00000 n 0000140123 00000 n 0000140261 00000 n 0000141654 00000 n 0000144181 00000 n 0000141756 00000 n 0000144120 00000 n 0000141898 00000 n 0000142036 00000 n 0000142174 00000 n 0000142312 00000 n 0000142452 00000 n 0000144394 00000 n 0000145828 00000 n 0000144416 00000 n 0000145767 00000 n 0000144554 00000 n 0000144692 00000 n 0000144830 00000 n 0000144968 00000 n 0000145106 00000 n 0000146041 00000 n 0000148296 00000 n 0000146142 00000 n 0000148219 00000 n 0000146284 00000 n 0000146422 00000 n 0000146556 00000 n 0000146690 00000 n 0000146823 00000 n 0000146955 00000 n 0000147087 00000 n 0000148509 00000 n 0000151287 00000 n 0000148611 00000 n 0000151186 00000 n 0000148753 00000 n 0000148891 00000 n 0000149033 00000 n 0000149173 00000 n 0000149311 00000 n 0000149449 00000 n 0000149587 00000 n 0000149725 00000 n 0000149863 00000 n 0000150001 00000 n 0000151500 00000 n 0000152473 00000 n 0000151522 00000 n 0000152428 00000 n 0000151656 00000 n 0000151790 00000 n 0000151924 00000 n 0000152686 00000 n 0000153833 00000 n 0000152707 00000 n 0000154028 00000 n 0000155372 00000 n 0000154050 00000 n 0000155567 00000 n 0000157060 00000 n 0000155589 00000 n 0000157255 00000 n 0000159160 00000 n 0000157277 00000 n 0000157357 00000 n 0000159115 00000 n 0000157495 00000 n 0000157575 00000 n 0000157713 00000 n 0000157793 00000 n 0000157931 00000 n 0000159373 00000 n 0000160071 00000 n 0000159395 00000 n 0000160266 00000 n 0000161816 00000 n 0000160287 00000 n 0000162011 00000 n 0000163706 00000 n 0000162033 00000 n 0000162113 00000 n 0000163677 00000 n 0000162249 00000 n 0000163919 00000 n 0000165334 00000 n 0000163941 00000 n 0000165529 00000 n 0000167505 00000 n 0000165551 00000 n 0000167460 00000 n 0000165688 00000 n 0000165768 00000 n 0000165904 00000 n 0000165984 00000 n 0000166120 00000 n 0000167718 00000 n 0000169273 00000 n 0000167740 00000 n 0000169228 00000 n 0000167878 00000 n 0000168016 00000 n 0000168096 00000 n 0000168234 00000 n 0000169486 00000 n 0000170324 00000 n 0000169507 00000 n 0000170287 00000 n 0000169641 00000 n 0000169775 00000 n 0000170537 00000 n 0000171451 00000 n 0000170558 00000 n 0000171406 00000 n 0000170696 00000 n 0000170834 00000 n 0000170972 00000 n 0000171664 00000 n 0000172041 00000 n 0000171685 00000 n 0000172236 00000 n 0000173906 00000 n 0000172257 00000 n 0000174101 00000 n 0000175791 00000 n 0000174123 00000 n 0000174203 00000 n 0000175762 00000 n 0000174339 00000 n 0000176004 00000 n 0000177352 00000 n 0000176026 00000 n 0000177547 00000 n 0000179535 00000 n 0000177569 00000 n 0000179490 00000 n 0000177706 00000 n 0000177786 00000 n 0000177922 00000 n 0000178002 00000 n 0000178138 00000 n 0000179748 00000 n 0000180996 00000 n 0000179770 00000 n 0000180951 00000 n 0000179908 00000 n 0000180046 00000 n 0000180126 00000 n 0000180264 00000 n 0000181209 00000 n 0000182045 00000 n 0000181230 00000 n 0000182008 00000 n 0000181364 00000 n 0000181498 00000 n 0000182258 00000 n 0000183222 00000 n 0000182279 00000 n 0000183177 00000 n 0000182417 00000 n 0000182555 00000 n 0000182693 00000 n 0000183435 00000 n 0000183874 00000 n 0000183456 00000 n 0000184069 00000 n 0000185664 00000 n 0000184090 00000 n 0000185859 00000 n 0000187427 00000 n 0000185881 00000 n 0000187622 00000 n 0000189206 00000 n 0000187644 00000 n 0000189401 00000 n 0000191455 00000 n 0000189423 00000 n 0000189503 00000 n 0000191410 00000 n 0000189640 00000 n 0000189720 00000 n 0000189856 00000 n 0000189936 00000 n 0000190072 00000 n 0000191668 00000 n 0000192663 00000 n 0000191690 00000 n 0000192618 00000 n 0000191828 00000 n 0000191966 00000 n 0000192046 00000 n 0000192184 00000 n 0000192876 00000 n 0000194016 00000 n 0000192897 00000 n 0000193971 00000 n 0000193035 00000 n 0000193173 00000 n 0000193311 00000 n 0000194229 00000 n 0000195196 00000 n 0000194250 00000 n 0000195151 00000 n 0000194388 00000 n 0000194526 00000 n 0000194664 00000 n 0000195409 00000 n 0000195848 00000 n 0000195430 00000 n 0000196043 00000 n 0000197853 00000 n 0000196064 00000 n 0000198048 00000 n 0000199754 00000 n 0000198070 00000 n 0000199949 00000 n 0000200875 00000 n 0000199971 00000 n 0000200051 00000 n 0000200838 00000 n 0000200189 00000 n 0000200269 00000 n 0000200407 00000 n 0000201088 00000 n 0000202831 00000 n 0000201109 00000 n 0000202794 00000 n 0000201245 00000 n 0000201381 00000 n 0000203044 00000 n 0000203923 00000 n 0000203066 00000 n 0000203146 00000 n 0000203886 00000 n 0000203284 00000 n 0000203422 00000 n 0000204136 00000 n 0000204515 00000 n 0000204157 00000 n 0000204710 00000 n 0000205151 00000 n 0000204731 00000 n 0000205346 00000 n 0000206966 00000 n 0000216142 00000 n 0000205367 00000 n 0000206937 00000 n 0000205503 00000 n 0000207179 00000 n 0000209251 00000 n 0000207201 00000 n 0000209198 00000 n 0000207339 00000 n 0000207419 00000 n 0000211789 00000 n 0000207556 00000 n 0000221867 00000 n 0000207692 00000 n 0000207828 00000 n 0000209464 00000 n 0000209904 00000 n 0000209486 00000 n 0000210099 00000 n 0000211554 00000 n 0000210120 00000 n 0000211525 00000 n 0000210254 00000 n 0000211767 00000 n 0000214049 00000 n 0000211869 00000 n 0000213988 00000 n 0000212007 00000 n 0000212145 00000 n 0000212225 00000 n 0000212362 00000 n 0000212498 00000 n 0000212578 00000 n 0000212714 00000 n 0000214262 00000 n 0000215907 00000 n 0000214284 00000 n 0000215870 00000 n 0000214420 00000 n 0000214556 00000 n 0000216120 00000 n 0000218338 00000 n 0000216222 00000 n 0000218269 00000 n 0000216356 00000 n 0000216490 00000 n 0000216624 00000 n 0000216757 00000 n 0000216889 00000 n 0000216969 00000 n 0000217101 00000 n 0000218551 00000 n 0000219794 00000 n 0000218573 00000 n 0000219733 00000 n 0000218707 00000 n 0000218841 00000 n 0000218975 00000 n 0000219109 00000 n 0000219243 00000 n 0000220007 00000 n 0000220633 00000 n 0000220028 00000 n 0000220604 00000 n 0000220162 00000 n 0000220846 00000 n 0000221633 00000 n 0000220867 00000 n 0000221596 00000 n 0000221001 00000 n 0000221135 00000 n 0000221846 00000 n 0000224100 00000 n 0000221947 00000 n 0000224031 00000 n 0000222085 00000 n 0000222223 00000 n 0000222361 00000 n 0000222498 00000 n 0000222634 00000 n 0000222770 00000 n 0000224313 00000 n 0000225558 00000 n 0000224335 00000 n 0000225497 00000 n 0000224469 00000 n 0000224603 00000 n 0000224737 00000 n 0000224871 00000 n 0000225005 00000 n 0000225771 00000 n 0000226867 00000 n 0000225792 00000 n 0000226814 00000 n 0000225926 00000 n 0000226060 00000 n 0000226194 00000 n 0000226328 00000 n 0000227080 00000 n 0000228213 00000 n 0000227101 00000 n 0000228160 00000 n 0000227239 00000 n 0000227377 00000 n 0000227515 00000 n 0000227653 00000 n 0000228426 00000 n 0000229632 00000 n 0000485262 00000 n 0000228447 00000 n 0000229603 00000 n 0000228585 00000 n 0000229845 00000 n 0000231013 00000 n 0000229866 00000 n 0000229946 00000 n 0000230976 00000 n 0000230085 00000 n 0000230224 00000 n 0000231226 00000 n 0000232404 00000 n 0000490762 00000 n 0000231247 00000 n 0000232367 00000 n 0000493354 00000 n 0000231385 00000 n 0000231523 00000 n 0000232617 00000 n 0000233897 00000 n 0000487763 00000 n 0000232638 00000 n 0000233860 00000 n 0000232776 00000 n 0000232914 00000 n 0000234110 00000 n 0000234869 00000 n 0000234131 00000 n 0000234832 00000 n 0000234269 00000 n 0000234407 00000 n 0000235082 00000 n 0000235886 00000 n 0000497913 00000 n 0000235103 00000 n 0000235857 00000 n 0000235241 00000 n 0000236099 00000 n 0000237766 00000 n 0000495465 00000 n 0000236120 00000 n 0000237737 00000 n 0000236254 00000 n 0000237979 00000 n 0000241698 00000 n 0000238001 00000 n 0000241893 00000 n 0000242975 00000 n 0000241915 00000 n 0000243170 00000 n 0000243850 00000 n 0000243191 00000 n 0000244045 00000 n 0000244511 00000 n 0000244066 00000 n 0000244706 00000 n 0000246601 00000 n 0000244727 00000 n 0000246532 00000 n 0000244865 00000 n 0000505019 00000 n 0000245007 00000 n 0000508377 00000 n 0000245149 00000 n 0000515283 00000 n 0000245289 00000 n 0000512270 00000 n 0000245429 00000 n 0000245569 00000 n 0000246814 00000 n 0000248102 00000 n 0000501824 00000 n 0000246835 00000 n 0000248041 00000 n 0000246969 00000 n 0000247103 00000 n 0000247237 00000 n 0000247371 00000 n 0000247505 00000 n 0000248315 00000 n 0000249888 00000 n 0000248336 00000 n 0000249827 00000 n 0000248474 00000 n 0000248612 00000 n 0000248750 00000 n 0000248888 00000 n 0000249026 00000 n 0000250101 00000 n 0000252188 00000 n 0000250122 00000 n 0000252127 00000 n 0000250260 00000 n 0000250398 00000 n 0000250536 00000 n 0000250674 00000 n 0000250812 00000 n 0000252401 00000 n 0000254552 00000 n 0000252423 00000 n 0000254491 00000 n 0000252561 00000 n 0000252699 00000 n 0000252837 00000 n 0000252975 00000 n 0000253113 00000 n 0000254765 00000 n 0000256073 00000 n 0000254787 00000 n 0000256268 00000 n 0000258019 00000 n 0000256290 00000 n 0000257958 00000 n 0000256428 00000 n 0000256566 00000 n 0000256704 00000 n 0000256842 00000 n 0000256980 00000 n 0000258232 00000 n 0000259049 00000 n 0000523125 00000 n 0000258253 00000 n 0000259012 00000 n 0000526960 00000 n 0000258387 00000 n 0000258521 00000 n 0000259262 00000 n 0000291512 00000 n 0000259283 00000 n 0000290539 00000 n 0000259418 00000 n 0000259556 00000 n 0000259691 00000 n 0000259829 00000 n 0000259964 00000 n 0000260102 00000 n 0000260237 00000 n 0000260375 00000 n 0000260510 00000 n 0000260648 00000 n 0000260783 00000 n 0000260921 00000 n 0000261056 00000 n 0000261194 00000 n 0000261329 00000 n 0000261467 00000 n 0000261547 00000 n 0000261681 00000 n 0000261819 00000 n 0000261899 00000 n 0000262035 00000 n 0000262173 00000 n 0000262309 00000 n 0000262448 00000 n 0000262584 00000 n 0000262723 00000 n 0000262859 00000 n 0000262998 00000 n 0000263134 00000 n 0000263273 00000 n 0000263409 00000 n 0000263548 00000 n 0000263683 00000 n 0000263822 00000 n 0000263957 00000 n 0000264096 00000 n 0000264232 00000 n 0000264371 00000 n 0000264507 00000 n 0000264646 00000 n 0000264781 00000 n 0000264920 00000 n 0000265056 00000 n 0000265195 00000 n 0000265331 00000 n 0000265470 00000 n 0000265606 00000 n 0000265745 00000 n 0000265881 00000 n 0000266020 00000 n 0000266156 00000 n 0000266295 00000 n 0000266431 00000 n 0000266570 00000 n 0000266706 00000 n 0000266845 00000 n 0000266981 00000 n 0000267120 00000 n 0000267256 00000 n 0000267395 00000 n 0000267531 00000 n 0000267670 00000 n 0000267806 00000 n 0000267945 00000 n 0000268081 00000 n 0000483492 00000 n 0000268220 00000 n 0000268357 00000 n 0000268497 00000 n 0000268578 00000 n 0000268716 00000 n 0000268856 00000 n 0000268992 00000 n 0000269131 00000 n 0000269267 00000 n 0000269406 00000 n 0000269542 00000 n 0000269681 00000 n 0000269817 00000 n 0000269956 00000 n 0000270092 00000 n 0000270231 00000 n 0000270367 00000 n 0000270506 00000 n 0000270642 00000 n 0000270781 00000 n 0000270917 00000 n 0000271056 00000 n 0000271192 00000 n 0000271331 00000 n 0000271467 00000 n 0000271606 00000 n 0000271742 00000 n 0000271881 00000 n 0000272017 00000 n 0000291750 00000 n 0000272156 00000 n 0000272294 00000 n 0000519231 00000 n 0000272434 00000 n 0000272571 00000 n 0000521145 00000 n 0000272711 00000 n 0000272848 00000 n 0000272988 00000 n 0000273124 00000 n 0000525126 00000 n 0000273263 00000 n 0000273400 00000 n 0000273540 00000 n 0000273675 00000 n 0000529341 00000 n 0000273813 00000 n 0000273948 00000 n 0000531579 00000 n 0000274086 00000 n 0000274221 00000 n 0000274359 00000 n 0000291726 00000 n 0000292953 00000 n 0000291832 00000 n 0000292913 00000 n 0000291972 00000 n 0000292116 00000 n 0000293169 00000 n 0000294120 00000 n 0000293191 00000 n 0000294071 00000 n 0000293327 00000 n 0000293462 00000 n 0000293598 00000 n 0000294336 00000 n 0000294779 00000 n 0000294358 00000 n 0000294976 00000 n 0000296405 00000 n 0000294998 00000 n 0000296338 00000 n 0000295138 00000 n 0000295277 00000 n 0000295417 00000 n 0000534192 00000 n 0000295557 00000 n 0000295697 00000 n 0000296621 00000 n 0000298228 00000 n 0000296643 00000 n 0000298152 00000 n 0000296783 00000 n 0000296922 00000 n 0000297062 00000 n 0000297201 00000 n 0000297341 00000 n 0000297481 00000 n 0000298444 00000 n 0000300057 00000 n 0000298466 00000 n 0000299981 00000 n 0000298606 00000 n 0000298746 00000 n 0000298886 00000 n 0000299026 00000 n 0000299166 00000 n 0000299306 00000 n 0000300273 00000 n 0000301104 00000 n 0000300295 00000 n 0000301064 00000 n 0000300431 00000 n 0000300567 00000 n 0000301320 00000 n 0000302578 00000 n 0000301342 00000 n 0000302511 00000 n 0000301482 00000 n 0000301622 00000 n 0000301761 00000 n 0000301900 00000 n 0000302040 00000 n 0000302794 00000 n 0000303573 00000 n 0000302816 00000 n 0000303770 00000 n 0000305001 00000 n 0000303792 00000 n 0000305198 00000 n 0000307339 00000 n 0000558453 00000 n 0000305302 00000 n 0000307308 00000 n 0000305440 00000 n 0000307555 00000 n 0000309656 00000 n 0000307661 00000 n 0000309625 00000 n 0000307803 00000 n 0000309872 00000 n 0000313168 00000 n 0000309895 00000 n 0000309977 00000 n 0000313128 00000 n 0000310115 00000 n 0000310253 00000 n 0000313384 00000 n 0000314708 00000 n 0000313407 00000 n 0000314905 00000 n 0000316593 00000 n 0000314928 00000 n 0000316790 00000 n 0000317686 00000 n 0000316813 00000 n 0000317883 00000 n 0000318909 00000 n 0000317905 00000 n 0000319106 00000 n 0000320704 00000 n 0000319128 00000 n 0000320646 00000 n 0000554946 00000 n 0000319268 00000 n 0000564848 00000 n 0000319412 00000 n 0000319556 00000 n 0000319696 00000 n 0000320920 00000 n 0000321812 00000 n 0000320942 00000 n 0000321781 00000 n 0000321078 00000 n 0000322028 00000 n 0000323822 00000 n 0000322050 00000 n 0000323773 00000 n 0000322190 00000 n 0000322272 00000 n 0000322412 00000 n 0000322552 00000 n 0000324038 00000 n 0000324642 00000 n 0000324061 00000 n 0000324611 00000 n 0000324201 00000 n 0000324858 00000 n 0000326071 00000 n 0000324880 00000 n 0000326031 00000 n 0000325021 00000 n 0000325160 00000 n 0000326287 00000 n 0000328592 00000 n 0000326309 00000 n 0000328516 00000 n 0000326444 00000 n 0000326579 00000 n 0000326714 00000 n 0000326849 00000 n 0000570421 00000 n 0000326984 00000 n 0000327120 00000 n 0000328808 00000 n 0000329445 00000 n 0000328831 00000 n 0000329414 00000 n 0000328970 00000 n 0000329661 00000 n 0000330789 00000 n 0000329683 00000 n 0000330740 00000 n 0000329822 00000 n 0000575400 00000 n 0000329961 00000 n 0000330101 00000 n 0000331005 00000 n 0000331780 00000 n 0000578140 00000 n 0000331027 00000 n 0000331740 00000 n 0000581039 00000 n 0000331163 00000 n 0000331299 00000 n 0000331996 00000 n 0000332952 00000 n 0000332018 00000 n 0000332903 00000 n 0000332158 00000 n 0000332298 00000 n 0000332437 00000 n 0000333168 00000 n 0000333959 00000 n 0000333190 00000 n 0000333919 00000 n 0000333330 00000 n 0000333470 00000 n 0000334175 00000 n 0000335018 00000 n 0000334197 00000 n 0000334978 00000 n 0000334337 00000 n 0000334477 00000 n 0000335234 00000 n 0000338063 00000 n 0000335256 00000 n 0000335338 00000 n 0000337951 00000 n 0000335482 00000 n 0000586833 00000 n 0000335625 00000 n 0000335769 00000 n 0000584023 00000 n 0000335909 00000 n 0000336051 00000 n 0000336191 00000 n 0000336335 00000 n 0000336479 00000 n 0000572926 00000 n 0000336619 00000 n 0000336763 00000 n 0000338279 00000 n 0000339677 00000 n 0000589673 00000 n 0000338302 00000 n 0000339628 00000 n 0000338446 00000 n 0000338586 00000 n 0000338726 00000 n 0000339893 00000 n 0000340707 00000 n 0000339915 00000 n 0000340667 00000 n 0000340055 00000 n 0000340195 00000 n 0000340923 00000 n 0000341718 00000 n 0000340945 00000 n 0000341678 00000 n 0000341085 00000 n 0000341225 00000 n 0000341934 00000 n 0000343293 00000 n 0000341956 00000 n 0000342038 00000 n 0000343235 00000 n 0000342178 00000 n 0000342318 00000 n 0000342458 00000 n 0000342598 00000 n 0000343509 00000 n 0000344237 00000 n 0000343531 00000 n 0000344434 00000 n 0000345251 00000 n 0000538443 00000 n 0000344456 00000 n 0000345211 00000 n 0000543076 00000 n 0000344596 00000 n 0000344736 00000 n 0000345467 00000 n 0000346343 00000 n 0000345489 00000 n 0000346303 00000 n 0000540816 00000 n 0000345629 00000 n 0000345769 00000 n 0000346559 00000 n 0000347975 00000 n 0000346581 00000 n 0000347899 00000 n 0000346721 00000 n 0000545276 00000 n 0000346861 00000 n 0000547383 00000 n 0000347001 00000 n 0000549736 00000 n 0000347141 00000 n 0000551876 00000 n 0000347281 00000 n 0000347421 00000 n 0000348191 00000 n 0000349082 00000 n 0000348213 00000 n 0000349033 00000 n 0000348349 00000 n 0000348485 00000 n 0000348621 00000 n 0000349298 00000 n 0000350572 00000 n 0000349320 00000 n 0000350514 00000 n 0000349460 00000 n 0000349600 00000 n 0000349740 00000 n 0000349880 00000 n 0000350788 00000 n 0000352357 00000 n 0000350810 00000 n 0000352272 00000 n 0000350950 00000 n 0000351090 00000 n 0000351230 00000 n 0000351370 00000 n 0000351510 00000 n 0000351650 00000 n 0000351790 00000 n 0000352573 00000 n 0000353498 00000 n 0000352595 00000 n 0000353449 00000 n 0000352735 00000 n 0000352875 00000 n 0000353015 00000 n 0000353714 00000 n 0000354653 00000 n 0000353736 00000 n 0000354850 00000 n 0000355894 00000 n 0000354872 00000 n 0000354954 00000 n 0000355863 00000 n 0000355095 00000 n 0000356110 00000 n 0000357201 00000 n 0000356132 00000 n 0000357161 00000 n 0000356273 00000 n 0000356417 00000 n 0000357417 00000 n 0000358683 00000 n 0000357439 00000 n 0000357521 00000 n 0000358643 00000 n 0000357662 00000 n 0000357804 00000 n 0000358899 00000 n 0000360149 00000 n 0000358921 00000 n 0000359003 00000 n 0000360109 00000 n 0000359144 00000 n 0000359286 00000 n 0000360365 00000 n 0000361774 00000 n 0000360387 00000 n 0000360469 00000 n 0000361725 00000 n 0000360610 00000 n 0000360751 00000 n 0000360893 00000 n 0000361990 00000 n 0000363413 00000 n 0000362012 00000 n 0000363373 00000 n 0000362156 00000 n 0000362300 00000 n 0000363629 00000 n 0000365042 00000 n 0000363651 00000 n 0000363733 00000 n 0000364984 00000 n 0000363877 00000 n 0000364016 00000 n 0000364155 00000 n 0000364294 00000 n 0000365258 00000 n 0000366558 00000 n 0000365280 00000 n 0000366500 00000 n 0000365424 00000 n 0000365563 00000 n 0000365702 00000 n 0000365841 00000 n 0000366774 00000 n 0000368025 00000 n 0000366796 00000 n 0000367967 00000 n 0000366940 00000 n 0000367079 00000 n 0000367218 00000 n 0000367357 00000 n 0000368241 00000 n 0000370214 00000 n 0000368263 00000 n 0000368345 00000 n 0000370165 00000 n 0000368486 00000 n 0000368628 00000 n 0000368769 00000 n 0000370430 00000 n 0000372615 00000 n 0000370453 00000 n 0000370535 00000 n 0000372557 00000 n 0000370676 00000 n 0000370820 00000 n 0000370962 00000 n 0000371104 00000 n 0000372831 00000 n 0000374797 00000 n 0000372854 00000 n 0000374748 00000 n 0000372998 00000 n 0000373142 00000 n 0000373284 00000 n 0000375013 00000 n 0000376914 00000 n 0000375036 00000 n 0000376865 00000 n 0000375180 00000 n 0000375324 00000 n 0000375465 00000 n 0000377130 00000 n 0000379277 00000 n 0000377153 00000 n 0000379219 00000 n 0000377294 00000 n 0000377438 00000 n 0000377580 00000 n 0000377722 00000 n 0000379493 00000 n 0000381597 00000 n 0000379516 00000 n 0000381539 00000 n 0000379657 00000 n 0000379801 00000 n 0000379943 00000 n 0000380085 00000 n 0000381813 00000 n 0000382156 00000 n 0000381836 00000 n 0000382353 00000 n 0000398950 00000 n 0000382375 00000 n 0000382457 00000 n 0000398046 00000 n 0000382598 00000 n 0000382738 00000 n 0000382878 00000 n 0000383019 00000 n 0000383158 00000 n 0000567685 00000 n 0000383298 00000 n 0000383439 00000 n 0000383578 00000 n 0000383718 00000 n 0000383858 00000 n 0000383997 00000 n 0000384137 00000 n 0000384278 00000 n 0000384417 00000 n 0000384558 00000 n 0000384698 00000 n 0000384838 00000 n 0000384978 00000 n 0000385119 00000 n 0000385259 00000 n 0000385399 00000 n 0000385538 00000 n 0000385679 00000 n 0000385819 00000 n 0000385959 00000 n 0000386099 00000 n 0000386239 00000 n 0000386379 00000 n 0000386520 00000 n 0000386660 00000 n 0000386799 00000 n 0000386939 00000 n 0000387079 00000 n 0000387219 00000 n 0000387359 00000 n 0000387500 00000 n 0000387640 00000 n 0000387780 00000 n 0000387920 00000 n 0000388060 00000 n 0000388200 00000 n 0000388341 00000 n 0000388481 00000 n 0000388622 00000 n 0000388763 00000 n 0000388845 00000 n 0000388986 00000 n 0000389126 00000 n 0000389267 00000 n 0000389406 00000 n 0000389546 00000 n 0000389685 00000 n 0000389826 00000 n 0000389966 00000 n 0000390106 00000 n 0000390247 00000 n 0000390329 00000 n 0000390470 00000 n 0000390611 00000 n 0000390751 00000 n 0000390891 00000 n 0000391030 00000 n 0000391171 00000 n 0000391312 00000 n 0000391452 00000 n 0000391593 00000 n 0000391733 00000 n 0000391815 00000 n 0000391956 00000 n 0000392096 00000 n 0000392178 00000 n 0000392319 00000 n 0000392458 00000 n 0000392599 00000 n 0000392739 00000 n 0000392880 00000 n 0000393019 00000 n 0000393160 00000 n 0000393300 00000 n 0000393441 00000 n 0000393581 00000 n 0000393721 00000 n 0000393860 00000 n 0000394001 00000 n 0000394142 00000 n 0000394282 00000 n 0000394422 00000 n 0000394563 00000 n 0000394703 00000 n 0000394844 00000 n 0000394984 00000 n 0000395125 00000 n 0000395266 00000 n 0000395407 00000 n 0000395547 00000 n 0000395688 00000 n 0000395828 00000 n 0000395968 00000 n 0000396106 00000 n 0000396245 00000 n 0000396383 00000 n 0000396522 00000 n 0000399166 00000 n 0000401004 00000 n 0000399189 00000 n 0000400901 00000 n 0000399325 00000 n 0000399461 00000 n 0000399597 00000 n 0000536332 00000 n 0000399733 00000 n 0000399870 00000 n 0000400006 00000 n 0000400142 00000 n 0000400279 00000 n 0000400415 00000 n 0000401220 00000 n 0000403241 00000 n 0000401242 00000 n 0000403438 00000 n 0000404739 00000 n 0000403461 00000 n 0000403543 00000 n 0000404708 00000 n 0000403678 00000 n 0000404955 00000 n 0000406805 00000 n 0000404977 00000 n 0000407002 00000 n 0000440009 00000 n 0000407025 00000 n 0000439015 00000 n 0000407162 00000 n 0000407302 00000 n 0000407439 00000 n 0000407579 00000 n 0000407716 00000 n 0000407856 00000 n 0000407993 00000 n 0000408133 00000 n 0000408270 00000 n 0000408410 00000 n 0000408547 00000 n 0000408687 00000 n 0000408824 00000 n 0000408964 00000 n 0000409101 00000 n 0000409241 00000 n 0000409323 00000 n 0000409461 00000 n 0000409601 00000 n 0000409738 00000 n 0000409878 00000 n 0000409960 00000 n 0000410097 00000 n 0000410237 00000 n 0000410374 00000 n 0000410514 00000 n 0000410650 00000 n 0000410790 00000 n 0000410927 00000 n 0000411067 00000 n 0000411204 00000 n 0000411344 00000 n 0000411481 00000 n 0000411621 00000 n 0000411758 00000 n 0000411898 00000 n 0000412035 00000 n 0000412175 00000 n 0000412312 00000 n 0000412452 00000 n 0000412589 00000 n 0000412729 00000 n 0000412811 00000 n 0000412949 00000 n 0000413089 00000 n 0000413226 00000 n 0000413366 00000 n 0000413503 00000 n 0000413643 00000 n 0000413780 00000 n 0000413920 00000 n 0000414057 00000 n 0000414197 00000 n 0000414334 00000 n 0000414474 00000 n 0000414611 00000 n 0000414751 00000 n 0000414888 00000 n 0000415028 00000 n 0000415110 00000 n 0000415248 00000 n 0000415388 00000 n 0000415525 00000 n 0000415665 00000 n 0000415802 00000 n 0000415942 00000 n 0000416079 00000 n 0000416219 00000 n 0000416356 00000 n 0000416496 00000 n 0000416632 00000 n 0000416772 00000 n 0000416909 00000 n 0000417049 00000 n 0000417186 00000 n 0000417326 00000 n 0000417463 00000 n 0000417603 00000 n 0000417740 00000 n 0000417880 00000 n 0000418017 00000 n 0000418157 00000 n 0000418294 00000 n 0000418434 00000 n 0000418571 00000 n 0000418711 00000 n 0000418793 00000 n 0000418930 00000 n 0000419070 00000 n 0000419152 00000 n 0000419290 00000 n 0000419430 00000 n 0000419568 00000 n 0000419708 00000 n 0000419792 00000 n 0000419930 00000 n 0000420070 00000 n 0000420154 00000 n 0000420291 00000 n 0000420431 00000 n 0000420515 00000 n 0000420651 00000 n 0000420791 00000 n 0000420875 00000 n 0000421012 00000 n 0000421152 00000 n 0000421236 00000 n 0000421374 00000 n 0000421514 00000 n 0000421598 00000 n 0000421735 00000 n 0000421875 00000 n 0000421959 00000 n 0000422096 00000 n 0000422236 00000 n 0000422320 00000 n 0000422455 00000 n 0000422594 00000 n 0000422678 00000 n 0000422813 00000 n 0000422951 00000 n 0000423035 00000 n 0000423171 00000 n 0000423309 00000 n 0000440225 00000 n 0000442048 00000 n 0000440249 00000 n 0000442245 00000 n 0000443721 00000 n 0000442268 00000 n 0000443918 00000 n 0000445058 00000 n 0000443941 00000 n 0000445255 00000 n 0000446947 00000 n 0000445278 00000 n 0000446916 00000 n 0000445419 00000 n 0000447163 00000 n 0000449513 00000 n 0000447186 00000 n 0000449482 00000 n 0000447327 00000 n 0000449729 00000 n 0000451373 00000 n 0000449752 00000 n 0000451333 00000 n 0000449894 00000 n 0000450036 00000 n 0000451589 00000 n 0000454883 00000 n 0000451612 00000 n 0000451696 00000 n 0000454798 00000 n 0000451838 00000 n 0000451980 00000 n 0000452064 00000 n 0000452206 00000 n 0000452348 00000 n 0000452490 00000 n 0000452574 00000 n 0000452716 00000 n 0000452856 00000 n 0000455099 00000 n 0000478170 00000 n 0000455122 00000 n 0000455206 00000 n 0000477536 00000 n 0000455343 00000 n 0000455483 00000 n 0000455567 00000 n 0000455704 00000 n 0000455844 00000 n 0000455928 00000 n 0000456064 00000 n 0000456204 00000 n 0000456288 00000 n 0000456425 00000 n 0000456565 00000 n 0000456649 00000 n 0000456787 00000 n 0000592689 00000 n 0000456927 00000 n 0000457064 00000 n 0000592772 00000 n 0000457204 00000 n 0000457341 00000 n 0000592856 00000 n 0000457481 00000 n 0000457617 00000 n 0000457757 00000 n 0000457839 00000 n 0000457976 00000 n 0000458116 00000 n 0000458200 00000 n 0000458338 00000 n 0000458478 00000 n 0000458562 00000 n 0000458699 00000 n 0000458839 00000 n 0000458923 00000 n 0000459061 00000 n 0000459201 00000 n 0000459283 00000 n 0000459419 00000 n 0000459559 00000 n 0000459643 00000 n 0000459779 00000 n 0000459919 00000 n 0000460003 00000 n 0000460140 00000 n 0000460280 00000 n 0000460364 00000 n 0000460502 00000 n 0000460642 00000 n 0000460726 00000 n 0000460863 00000 n 0000461003 00000 n 0000461087 00000 n 0000461225 00000 n 0000461365 00000 n 0000461449 00000 n 0000461585 00000 n 0000461725 00000 n 0000461809 00000 n 0000461946 00000 n 0000462086 00000 n 0000462170 00000 n 0000462308 00000 n 0000462448 00000 n 0000462532 00000 n 0000462669 00000 n 0000462809 00000 n 0000462893 00000 n 0000463031 00000 n 0000463171 00000 n 0000463255 00000 n 0000463391 00000 n 0000463531 00000 n 0000463615 00000 n 0000463752 00000 n 0000463892 00000 n 0000463974 00000 n 0000464112 00000 n 0000464252 00000 n 0000464336 00000 n 0000464473 00000 n 0000464613 00000 n 0000464697 00000 n 0000464834 00000 n 0000464974 00000 n 0000465058 00000 n 0000465194 00000 n 0000465334 00000 n 0000465418 00000 n 0000465556 00000 n 0000465696 00000 n 0000465778 00000 n 0000465915 00000 n 0000466055 00000 n 0000466139 00000 n 0000466277 00000 n 0000466417 00000 n 0000466501 00000 n 0000466638 00000 n 0000466778 00000 n 0000466860 00000 n 0000466997 00000 n 0000467137 00000 n 0000478386 00000 n 0000483253 00000 n 0000478988 00000 n 0000479072 00000 n 0000483132 00000 n 0000479214 00000 n 0000479356 00000 n 0000479424 00000 n 0000479568 00000 n 0000479708 00000 n 0000479849 00000 n 0000479908 00000 n 0000480050 00000 n 0000480192 00000 n 0000480276 00000 n 0000480417 00000 n 0000480558 00000 n 0000480622 00000 n 0000480758 00000 n 0000480894 00000 n 0000483469 00000 n 0000485023 00000 n 0000483574 00000 n 0000484983 00000 n 0000483716 00000 n 0000483858 00000 n 0000485239 00000 n 0000487524 00000 n 0000485343 00000 n 0000487484 00000 n 0000485485 00000 n 0000485627 00000 n 0000487740 00000 n 0000490523 00000 n 0000487844 00000 n 0000490483 00000 n 0000487986 00000 n 0000488128 00000 n 0000490739 00000 n 0000493115 00000 n 0000490843 00000 n 0000493075 00000 n 0000490985 00000 n 0000491127 00000 n 0000493331 00000 n 0000495226 00000 n 0000493435 00000 n 0000495186 00000 n 0000493577 00000 n 0000493719 00000 n 0000495442 00000 n 0000497674 00000 n 0000495546 00000 n 0000495630 00000 n 0000497616 00000 n 0000495772 00000 n 0000495914 00000 n 0000496056 00000 n 0000496198 00000 n 0000497890 00000 n 0000501585 00000 n 0000497994 00000 n 0000501509 00000 n 0000498138 00000 n 0000498282 00000 n 0000498424 00000 n 0000498566 00000 n 0000498650 00000 n 0000498791 00000 n 0000498932 00000 n 0000501801 00000 n 0000504780 00000 n 0000501905 00000 n 0000504722 00000 n 0000502049 00000 n 0000502193 00000 n 0000502335 00000 n 0000502477 00000 n 0000504996 00000 n 0000508138 00000 n 0000505100 00000 n 0000508062 00000 n 0000505242 00000 n 0000505384 00000 n 0000505526 00000 n 0000505668 00000 n 0000505806 00000 n 0000505943 00000 n 0000508354 00000 n 0000512031 00000 n 0000508458 00000 n 0000511946 00000 n 0000508602 00000 n 0000508746 00000 n 0000508888 00000 n 0000509030 00000 n 0000509174 00000 n 0000509318 00000 n 0000509461 00000 n 0000512247 00000 n 0000515044 00000 n 0000512351 00000 n 0000514986 00000 n 0000512495 00000 n 0000512639 00000 n 0000512777 00000 n 0000512916 00000 n 0000515260 00000 n 0000518992 00000 n 0000515364 00000 n 0000518907 00000 n 0000515508 00000 n 0000515652 00000 n 0000515794 00000 n 0000515936 00000 n 0000516080 00000 n 0000516224 00000 n 0000516367 00000 n 0000519208 00000 n 0000520906 00000 n 0000519313 00000 n 0000520866 00000 n 0000519455 00000 n 0000519597 00000 n 0000521122 00000 n 0000522886 00000 n 0000521227 00000 n 0000522846 00000 n 0000521369 00000 n 0000521511 00000 n 0000523102 00000 n 0000524887 00000 n 0000523206 00000 n 0000524847 00000 n 0000523348 00000 n 0000523490 00000 n 0000525103 00000 n 0000526722 00000 n 0000525208 00000 n 0000526673 00000 n 0000525350 00000 n 0000525492 00000 n 0000525626 00000 n 0000526938 00000 n 0000529102 00000 n 0000527041 00000 n 0000529044 00000 n 0000527183 00000 n 0000527325 00000 n 0000527463 00000 n 0000527600 00000 n 0000529318 00000 n 0000531340 00000 n 0000529423 00000 n 0000531291 00000 n 0000529565 00000 n 0000529707 00000 n 0000529845 00000 n 0000531556 00000 n 0000533953 00000 n 0000531661 00000 n 0000533877 00000 n 0000531803 00000 n 0000531945 00000 n 0000532085 00000 n 0000532224 00000 n 0000532361 00000 n 0000532499 00000 n 0000534169 00000 n 0000536093 00000 n 0000534274 00000 n 0000536053 00000 n 0000534416 00000 n 0000534558 00000 n 0000536309 00000 n 0000538204 00000 n 0000536414 00000 n 0000538164 00000 n 0000536558 00000 n 0000536702 00000 n 0000538420 00000 n 0000540577 00000 n 0000538525 00000 n 0000540537 00000 n 0000538664 00000 n 0000538802 00000 n 0000540793 00000 n 0000542837 00000 n 0000540898 00000 n 0000542797 00000 n 0000541040 00000 n 0000541182 00000 n 0000543053 00000 n 0000545037 00000 n 0000543158 00000 n 0000544979 00000 n 0000543300 00000 n 0000543442 00000 n 0000543582 00000 n 0000543722 00000 n 0000545253 00000 n 0000547144 00000 n 0000545358 00000 n 0000547095 00000 n 0000545500 00000 n 0000545642 00000 n 0000545780 00000 n 0000547360 00000 n 0000549497 00000 n 0000547465 00000 n 0000549457 00000 n 0000547607 00000 n 0000547749 00000 n 0000549713 00000 n 0000551637 00000 n 0000549818 00000 n 0000551597 00000 n 0000549960 00000 n 0000550102 00000 n 0000551853 00000 n 0000553982 00000 n 0000551958 00000 n 0000553924 00000 n 0000552100 00000 n 0000552242 00000 n 0000552382 00000 n 0000552522 00000 n 0000554198 00000 n 0000554727 00000 n 0000554221 00000 n 0000554924 00000 n 0000558214 00000 n 0000555028 00000 n 0000555110 00000 n 0000558102 00000 n 0000555252 00000 n 0000555394 00000 n 0000555536 00000 n 0000555678 00000 n 0000555820 00000 n 0000555964 00000 n 0000556108 00000 n 0000556250 00000 n 0000556392 00000 n 0000556530 00000 n 0000558430 00000 n 0000561859 00000 n 0000558535 00000 n 0000561819 00000 n 0000558679 00000 n 0000558823 00000 n 0000562075 00000 n 0000564609 00000 n 0000562098 00000 n 0000564569 00000 n 0000562241 00000 n 0000562384 00000 n 0000564825 00000 n 0000567446 00000 n 0000564930 00000 n 0000567352 00000 n 0000565072 00000 n 0000565214 00000 n 0000565355 00000 n 0000565496 00000 n 0000565639 00000 n 0000565782 00000 n 0000565922 00000 n 0000566062 00000 n 0000567662 00000 n 0000570182 00000 n 0000567767 00000 n 0000570097 00000 n 0000567909 00000 n 0000568051 00000 n 0000568189 00000 n 0000568327 00000 n 0000568465 00000 n 0000568605 00000 n 0000568743 00000 n 0000570398 00000 n 0000572687 00000 n 0000570503 00000 n 0000572629 00000 n 0000570645 00000 n 0000570787 00000 n 0000570931 00000 n 0000571075 00000 n 0000572903 00000 n 0000575161 00000 n 0000573008 00000 n 0000575103 00000 n 0000573150 00000 n 0000573292 00000 n 0000573434 00000 n 0000573576 00000 n 0000575377 00000 n 0000577901 00000 n 0000575482 00000 n 0000577825 00000 n 0000575624 00000 n 0000575766 00000 n 0000575907 00000 n 0000576048 00000 n 0000576191 00000 n 0000576334 00000 n 0000578117 00000 n 0000580800 00000 n 0000578222 00000 n 0000580724 00000 n 0000578364 00000 n 0000578506 00000 n 0000578648 00000 n 0000578790 00000 n 0000578933 00000 n 0000579076 00000 n 0000581016 00000 n 0000583784 00000 n 0000581121 00000 n 0000583708 00000 n 0000581263 00000 n 0000581405 00000 n 0000581547 00000 n 0000581689 00000 n 0000581833 00000 n 0000581977 00000 n 0000584000 00000 n 0000586594 00000 n 0000584105 00000 n 0000586518 00000 n 0000584247 00000 n 0000584389 00000 n 0000584531 00000 n 0000584673 00000 n 0000584817 00000 n 0000584961 00000 n 0000586810 00000 n 0000589434 00000 n 0000586915 00000 n 0000589358 00000 n 0000587057 00000 n 0000587199 00000 n 0000587341 00000 n 0000587483 00000 n 0000587627 00000 n 0000587771 00000 n 0000589650 00000 n 0000592450 00000 n 0000589755 00000 n 0000592374 00000 n 0000589897 00000 n 0000590039 00000 n 0000590181 00000 n 0000590323 00000 n 0000590467 00000 n 0000590611 00000 n 0000592666 00000 n 0000596665 00000 n 0000592940 00000 n 0000596562 00000 n 0000593079 00000 n 0000593161 00000 n 0000593302 00000 n 0000593443 00000 n 0000593586 00000 n 0000593727 00000 n 0000593793 00000 n 0000593936 00000 n 0000594079 00000 n 0000594164 00000 n 0000594304 00000 n 0000594444 00000 n 0000596881 00000 n 0000596904 00000 n 0000596983 00000 n 0000597063 00000 n 0000597145 00000 n 0000597229 00000 n 0000597311 00000 n 0000597395 00000 n 0000597477 00000 n 0000597561 00000 n 0000597643 00000 n 0000597727 00000 n 0000597811 00000 n 0000597895 00000 n 0000597979 00000 n 0000598063 00000 n 0000598147 00000 n 0000598231 00000 n 0000598315 00000 n 0000598398 00000 n 0000598482 00000 n 0000598566 00000 n 0000598650 00000 n 0000598734 00000 n 0000598818 00000 n 0000598901 00000 n 0000598985 00000 n 0000599069 00000 n 0000599153 00000 n 0000599237 00000 n 0000599321 00000 n 0000599405 00000 n 0000658930 00000 n 0000599489 00000 n 0000599588 00000 n 0000599669 00000 n 0000599783 00000 n 0000599886 00000 n 0000600123 00000 n 0000600210 00000 n 0000600313 00000 n 0000600466 00000 n 0000600550 00000 n 0000600650 00000 n 0000600749 00000 n 0000600881 00000 n 0000600989 00000 n 0000601125 00000 n 0000601226 00000 n 0000601390 00000 n 0000601488 00000 n 0000601573 00000 n 0000601682 00000 n 0000601790 00000 n 0000601916 00000 n 0000602023 00000 n 0000602283 00000 n 0000602375 00000 n 0000602495 00000 n 0000602606 00000 n 0000602717 00000 n 0000602828 00000 n 0000602940 00000 n 0000603030 00000 n 0000603200 00000 n 0000603288 00000 n 0000603402 00000 n 0000603528 00000 n 0000603642 00000 n 0000603760 00000 n 0000603884 00000 n 0000603986 00000 n 0000604101 00000 n 0000604210 00000 n 0000604329 00000 n 0000604438 00000 n 0000604544 00000 n 0000604657 00000 n 0000604766 00000 n 0000604886 00000 n 0000604991 00000 n 0000605093 00000 n 0000605204 00000 n 0000605316 00000 n 0000605426 00000 n 0000605536 00000 n 0000605645 00000 n 0000605746 00000 n 0000605910 00000 n 0000606014 00000 n 0000606135 00000 n 0000606263 00000 n 0000606392 00000 n 0000606519 00000 n 0000606644 00000 n 0000606743 00000 n 0000606853 00000 n 0000606962 00000 n 0000607054 00000 n 0000607239 00000 n 0000607331 00000 n 0000607437 00000 n 0000607544 00000 n 0000607654 00000 n 0000607761 00000 n 0000607866 00000 n 0000607972 00000 n 0000608081 00000 n 0000608189 00000 n 0000608295 00000 n 0000608403 00000 n 0000608513 00000 n 0000608623 00000 n 0000608739 00000 n 0000608850 00000 n 0000608961 00000 n 0000609070 00000 n 0000609180 00000 n 0000609293 00000 n 0000609402 00000 n 0000609511 00000 n 0000609628 00000 n 0000609726 00000 n 0000609914 00000 n 0000610023 00000 n 0000610138 00000 n 0000610248 00000 n 0000610358 00000 n 0000610468 00000 n 0000610579 00000 n 0000610680 00000 n 0000610787 00000 n 0000610889 00000 n 0000610993 00000 n 0000611093 00000 n 0000611182 00000 n 0000611343 00000 n 0000611441 00000 n 0000611544 00000 n 0000611648 00000 n 0000611761 00000 n 0000611884 00000 n 0000612010 00000 n 0000612121 00000 n 0000612218 00000 n 0000612409 00000 n 0000612508 00000 n 0000612628 00000 n 0000612747 00000 n 0000612858 00000 n 0000612975 00000 n 0000613068 00000 n 0000613262 00000 n 0000613357 00000 n 0000613471 00000 n 0000613600 00000 n 0000613715 00000 n 0000613835 00000 n 0000613960 00000 n 0000614080 00000 n 0000614201 00000 n 0000614326 00000 n 0000614446 00000 n 0000614547 00000 n 0000614705 00000 n 0000614805 00000 n 0000614920 00000 n 0000615032 00000 n 0000615139 00000 n 0000615250 00000 n 0000615364 00000 n 0000615461 00000 n 0000615625 00000 n 0000615732 00000 n 0000615842 00000 n 0000615948 00000 n 0000616056 00000 n 0000616173 00000 n 0000616284 00000 n 0000616399 00000 n 0000616516 00000 n 0000616636 00000 n 0000616752 00000 n 0000616866 00000 n 0000616962 00000 n 0000617108 00000 n 0000617209 00000 n 0000617475 00000 n 0000617599 00000 n 0000617750 00000 n 0000617840 00000 n 0000617951 00000 n 0000618116 00000 n 0000618222 00000 n 0000618333 00000 n 0000618419 00000 n 0000618577 00000 n 0000618667 00000 n 0000618778 00000 n 0000618943 00000 n 0000619049 00000 n 0000619160 00000 n 0000619246 00000 n 0000619392 00000 n 0000619482 00000 n 0000619593 00000 n 0000619758 00000 n 0000619864 00000 n 0000619975 00000 n 0000620105 00000 n 0000620190 00000 n 0000620291 00000 n 0000620391 00000 n 0000620536 00000 n 0000620626 00000 n 0000620737 00000 n 0000620902 00000 n 0000621008 00000 n 0000621119 00000 n 0000621265 00000 n 0000621334 00000 n 0000621431 00000 n 0000621577 00000 n 0000621667 00000 n 0000621778 00000 n 0000621943 00000 n 0000622049 00000 n 0000622160 00000 n 0000622246 00000 n 0000622403 00000 n 0000622493 00000 n 0000622604 00000 n 0000622769 00000 n 0000622875 00000 n 0000622986 00000 n 0000623116 00000 n 0000623207 00000 n 0000623308 00000 n 0000623408 00000 n 0000623565 00000 n 0000623655 00000 n 0000623766 00000 n 0000623931 00000 n 0000624037 00000 n 0000624148 00000 n 0000624278 00000 n 0000624369 00000 n 0000624470 00000 n 0000624570 00000 n 0000624701 00000 n 0000624791 00000 n 0000624904 00000 n 0000625015 00000 n 0000625180 00000 n 0000625286 00000 n 0000625397 00000 n 0000625527 00000 n 0000625627 00000 n 0000625720 00000 n 0000625809 00000 n 0000625924 00000 n 0000626035 00000 n 0000626156 00000 n 0000626270 00000 n 0000626377 00000 n 0000626489 00000 n 0000626599 00000 n 0000626703 00000 n 0000626845 00000 n 0000626994 00000 n 0000627071 00000 n 0000627157 00000 n 0000627260 00000 n 0000627394 00000 n 0000627512 00000 n 0000627654 00000 n 0000627749 00000 n 0000627829 00000 n 0000627910 00000 n 0000628021 00000 n 0000628139 00000 n 0000628245 00000 n 0000628342 00000 n 0000628448 00000 n 0000628545 00000 n 0000628639 00000 n 0000628767 00000 n 0000628840 00000 n 0000628931 00000 n 0000629022 00000 n 0000629107 00000 n 0000629195 00000 n 0000629286 00000 n 0000629371 00000 n 0000629456 00000 n 0000629556 00000 n 0000629686 00000 n 0000629786 00000 n 0000629884 00000 n 0000630029 00000 n 0000630133 00000 n 0000630240 00000 n 0000630349 00000 n 0000630472 00000 n 0000630597 00000 n 0000630749 00000 n 0000630880 00000 n 0000630983 00000 n 0000631096 00000 n 0000631205 00000 n 0000631341 00000 n 0000631432 00000 n 0000631544 00000 n 0000631629 00000 n 0000631720 00000 n 0000631820 00000 n 0000631911 00000 n 0000631999 00000 n 0000632121 00000 n 0000632254 00000 n 0000632360 00000 n 0000632508 00000 n 0000632608 00000 n 0000632703 00000 n 0000632789 00000 n 0000632871 00000 n 0000632966 00000 n 0000633061 00000 n 0000633156 00000 n 0000633251 00000 n 0000633345 00000 n 0000633439 00000 n 0000633534 00000 n 0000633628 00000 n 0000633722 00000 n 0000633817 00000 n 0000633911 00000 n 0000634005 00000 n 0000634099 00000 n 0000634193 00000 n 0000634288 00000 n 0000634383 00000 n 0000634477 00000 n 0000634571 00000 n 0000634665 00000 n 0000634759 00000 n 0000634854 00000 n 0000634949 00000 n 0000635044 00000 n 0000635139 00000 n 0000635234 00000 n 0000635329 00000 n 0000635424 00000 n 0000635519 00000 n 0000635614 00000 n 0000635709 00000 n 0000635804 00000 n 0000635899 00000 n 0000635994 00000 n 0000636089 00000 n 0000636184 00000 n 0000636279 00000 n 0000636374 00000 n 0000636469 00000 n 0000636564 00000 n 0000636659 00000 n 0000636754 00000 n 0000636849 00000 n 0000636944 00000 n 0000637039 00000 n 0000637134 00000 n 0000637229 00000 n 0000637324 00000 n 0000637419 00000 n 0000637514 00000 n 0000637609 00000 n 0000637704 00000 n 0000637799 00000 n 0000637894 00000 n 0000637989 00000 n 0000638084 00000 n 0000638179 00000 n 0000638274 00000 n 0000638369 00000 n 0000638464 00000 n 0000638559 00000 n 0000638654 00000 n 0000638749 00000 n 0000638844 00000 n 0000638939 00000 n 0000639034 00000 n 0000639129 00000 n 0000639224 00000 n 0000639319 00000 n 0000639414 00000 n 0000639509 00000 n 0000639604 00000 n 0000639699 00000 n 0000639794 00000 n 0000639889 00000 n 0000639984 00000 n 0000640079 00000 n 0000640174 00000 n 0000640284 00000 n 0000640387 00000 n 0000640470 00000 n 0000640603 00000 n 0000640742 00000 n 0000640845 00000 n 0000640942 00000 n 0000641058 00000 n 0000641155 00000 n 0000641276 00000 n 0000641382 00000 n 0000641480 00000 n 0000641583 00000 n 0000641680 00000 n 0000641783 00000 n 0000641893 00000 n 0000641987 00000 n 0000642078 00000 n 0000642238 00000 n 0000642395 00000 n 0000642489 00000 n 0000642577 00000 n 0000642654 00000 n 0000642728 00000 n 0000642808 00000 n 0000642900 00000 n 0000643013 00000 n 0000643095 00000 n 0000643195 00000 n 0000643289 00000 n 0000643392 00000 n 0000643474 00000 n 0000643550 00000 n 0000643638 00000 n 0000643742 00000 n 0000643836 00000 n 0000643921 00000 n 0000644007 00000 n 0000644096 00000 n 0000644185 00000 n 0000644286 00000 n 0000644377 00000 n 0000644484 00000 n 0000644638 00000 n 0000644723 00000 n 0000644802 00000 n 0000644914 00000 n 0000645014 00000 n 0000645114 00000 n 0000645218 00000 n 0000645342 00000 n 0000645412 00000 n 0000645513 00000 n 0000645635 00000 n 0000645766 00000 n 0000645882 00000 n 0000646004 00000 n 0000646093 00000 n 0000646196 00000 n 0000646303 00000 n 0000646403 00000 n 0000646500 00000 n 0000646607 00000 n 0000646699 00000 n 0000646818 00000 n 0000646931 00000 n 0000647035 00000 n 0000647130 00000 n 0000647210 00000 n 0000647293 00000 n 0000647409 00000 n 0000647528 00000 n 0000647641 00000 n 0000647720 00000 n 0000647836 00000 n 0000647939 00000 n 0000648052 00000 n 0000648198 00000 n 0000648320 00000 n 0000648451 00000 n 0000648585 00000 n 0000648688 00000 n 0000648834 00000 n 0000648965 00000 n 0000649065 00000 n 0000649165 00000 n 0000649289 00000 n 0000649399 00000 n 0000651494 00000 n trailer << /Size 2780 /Root 2 0 R /Info 4 0 R /ID [<5A83388C669A328295BF9122317AF0B2> <5A83388C669A328295BF9122317AF0B2>] >> startxref 658986 %%EOF cl-sql-6.4.1/doc/html.xsl0000644000175000017500000000042110703552706014172 0ustar kevinkevin cl-sql-6.4.1/doc/ref-ooddl.xml0000644000175000017500000011041012064366222015071 0ustar kevinkevin %myents; ]> Object Oriented Data Definition Language (OODDL) The Object Oriented Data Definition Language (OODDL) provides access to relational SQL tables using Common Lisp Object System (CLOS) objects. SQL tables are mapped to CLOS objects with the SQL columns being mapped to slots of the CLOS object. The mapping between SQL tables and CLOS objects is defined with the macro def-view-class. SQL tables are created with create-view-from-class and SQL tables can be deleted with drop-view-from-class. The above functions refer to the Lisp view of the SQL table. This Lisp view should not be confused with SQL VIEW statement. STANDARD-DB-OBJECT Superclass for all &clsql; View Classes. Class Class Precedence List standard-db-object standard-object t Description This class is the superclass of all &clsql; View Classes. Class details (defclass STANDARD-DB-OBJECT ()(...)) Slots slot VIEW-DATABASE is of type (OR NULL DATABASE) which stores the associated database for the instance. *DEFAULT-STRING-LENGTH* Default length of SQL strings. Variable Value Type Fixnum Initial Value 255 Description If a slot of a class defined by def-view-class is of the type string or varchar and does not have a length specified, then the value of this variable is used as SQL length. Examples (let ((*default-string-length* 80)) (def-view-class s80 () ((a :type string) (b :type (string 80)) (c :type varchar)))) => #<Standard-Db-Class S80 {480A431D}> (create-view-from-class 's80) => (table-exists-p [s80]) => T The above code causes a SQL table to be created with the SQL command CREATE TABLE (A VARCHAR(80), B CHAR(80), C VARCHAR(80)) Affected By Some SQL backends do not support varchar lengths greater than 255. See Also None. Notes This is a CLSQL extension to the CommonSQL API. CREATE-VIEW-FROM-CLASS Create a SQL table from a View Class. Function Syntax create-view-from-class view-class-name &key database transactions => Arguments and Values view-class-name The name of a View Class that has been defined with def-view-class. database The database in which to create the SQL table. This will default to the value of *default-database*. transactions When &nil; specifies that a table type which does not support transactions should be used. Description Creates a table as defined by the View Class view-class-name in database. Examples (def-view-class foo () ((a :type (string 80)))) => #<Standard-Db-Class FOO {4807F7CD}> (create-view-from-class 'foo) => (list-tables) => ("FOO") Side Effects Causes a table to be created in the SQL database. Affected by Most SQL database systems will signal an error if a table creation is attempted when a table with the same name already exists. The SQL user, as specified in the database connection, must have sufficient permission for table creation. Exceptional Situations A condition will be signaled if the table can not be created in the SQL database. See Also def-view-class drop-view-from-class Notes Currently, only &mysql; supports transactionless tables. &clsql; provides the ability to create such tables for applications which would benefit from faster table access and do not require transaction support. The case of the table name is determined by the type of the database. &mysql;, for example, creates databases in upper-case while &postgresql; uses lowercase. DEF-VIEW-CLASS Defines CLOS classes with mapping to SQL database. Macro Syntax def-view-class name superclasses slots &rest class-options => class Arguments and Values name The class name. superclasses The superclasses for the defined class. slots The class slot definitions. class options The class options. class The defined class. Slot Options :db-kind - specifies the kind of database mapping which is performed for this slot and defaults to :base which indicates that the slot maps to an ordinary column of the database table. A :db-kind value of :key indicates that this slot is a special kind of :base slot which maps onto a column which is one of the unique keys for the database table, the value :join indicates this slot represents a join onto another View Class which contains View Class objects, and the value :virtual indicates a standard CLOS slot which does not map onto columns of the database table. :db-info - if a slot is specified with :db-kind :join, the slot option :db-info contains a property list which specifies the nature of the join. The valid members of the list are: :join-class class-name - the name of the class to join on. :home-key slot-name - the name of the slot of this class for joining :foreign-key slot-name - the name of the slot of the :join-class for joining :target-slot target-slot - this is an optional parameter. If specified, then the join slot of the defining class will contain instances of this target slot rather than of the join class. This can be useful when the :join-class is an intermediate class in a many-to-many relationship and the application is actually interested in the :target-slot. :retrieval time - The default value is :deferred, which defers filling this slot until the value is accessed. The other valid value is :immediate which performs the SQL query when the instance of the class is created. In this case, the :set is automatically set to &nil; :set set - This controls what is stored in the join slot. The default value is &t;. When set is &t; and target-slot is undefined, the join slot will contain a list of instances of the join class. Whereas, if target-slot is defined, then the join slot will contain a list of pairs of (target-value join-instance). When set is &nil;, the join slot will contain a single instances. :type - for slots of :db-kind :base or :key, the :type slot option has a special interpretation such that Lisp types, such as string, integer and float are automatically converted into appropriate SQL types for the column onto which the slot maps. This behaviour may be overridden using the :db-type slot option. The valid values are: string - a variable length character field up to *default-string-length* characters. (string n) - a fixed length character field n characters long. varchar - a variable length character field up to *default-string-length* characters. (varchar n) - a variable length character field up to n characters in length. char - a single character field integer - signed integer at least 32-bits wide (integer n) float (float n) long-float number (number n) (number n p) tinyint - An integer column 8-bits wide. [not supported by all database backends] smallint - An integer column 16-bits wide. [not supported by all database backends] bigint - An integer column 64-bits wide. [not supported by all database backends] universal-time - an integer field sufficiently wide to store a universal-time. On most databases, a slot of this type assigned a SQL type of BIGINT wall-time - a slot which stores a date and time in a SQL timestamp column. &clsql; provides a number of time manipulation functions to support objects of type wall-time. date - a slot which stores the date (without any time of day resolution) in a column. &clsql; provides a number of time manipulation functions that operate on date values. duration - stores a duration structure. &clsql; provides routines for wall-time and duration processing. boolean - stores a &t; or &nil; value. generalized-boolean - similar to a boolean in that either a &t; or &nil; value is stored in the SQL database. However, any Lisp object can be stored in the Lisp object. A Lisp value of &nil; is stored as FALSE in the database, any other Lisp value is stored as TRUE. keyword - stores a keyword symbol - stores a symbol list - stores a list by writing it to a string. The items in the list must be able to be readable written. vector - stores a vector similarly to list array - stores a array similarly to list :column - specifies the name of the SQL column which the slot maps onto, if :db-kind is not :virtual, and defaults to the slot name. If the slot name is used for the SQL column name, any hypens in the slot name are converted to underscore characters. :void-value - specifies the value to store in the Lisp instance if the SQL value is NULL and defaults to NIL. :db-constraints - is a keyword symbol representing an SQL column constraint expression or a list of such symbols. The following column constraints are supported: :not-null, :primary-key, :unique, :unsigned (&mysql; specific), :zerofill (&mysql; specific) and :auto-increment (&mysql; specific). :db-type - a string to specify the SQL column type. If specified, this string overrides the SQL column type as computed from the :type slot value. :db-reader - If a string, then when reading values from the database, the string will be used for a format string, with the only value being the value from the database. The resulting string will be used as the slot value. If a function then it will take one argument, the value from the database, and return the value that should be put into the slot. If a symbol, then the symbol-function of the symbol will be used. :db-writer - If a string, then when reading values from the slot for the database, the string will be used for a format string, with the only value being the value of the slot. The resulting string will be used as the column value in the database. If a function then it will take one argument, the value of the slot, and return the value that should be put into the database. If a symbol, then the symbol-function of the symbol will be used. Class Options :base-table - specifies the name of the SQL database table. The default value is the class name. Like slot names, hypens in the class name are converted to underscore characters. :normalizedp - specifies whether this class uses normalized inheritance from parent classes. Defaults to nil, i.e. non-normalized schemas. When true, SQL database tables that map to this class and parent classes are joined on their primary keys to get the full set of database columns for this class. Description Creates a View Class called name whose slots slots can map onto the attributes of a table in a database. If superclasses is &nil; then the superclass of class will be standard-db-object, otherwise superclasses is a list of superclasses for class which must include standard-db-object or a descendent of this class. Normalized inheritance schemas Specifying that :normalizedp is T tells &clsql; to normalize the database schema for inheritance. What this means is shown in the examples below. With :normalizedp equal to NIL (the default) the class inheritance would result in the following: (def-view-class node () ((title :accessor title :initarg :title :type (varchar 240)))) SQL table NODE: +-------+--------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+--------------+------+-----+---------+-------+ | TITLE | varchar(240) | YES | | NULL | | +-------+--------------+------+-----+---------+-------+ (def-view-class user (node) ((user-id :accessor user-id :initarg :user-id :type integer :db-kind :key :db-constraints (:not-null)) (nick :accessor nick :initarg :nick :type (varchar 64)))) SQL table USER: +---------+--------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +---------+--------------+------+-----+---------+-------+ | USER_ID | int(11) | NO | PRI | | | | NICK | varchar(64) | YES | | NULL | | | TITLE | varchar(240) | YES | | NULL | | +---------+--------------+------+-----+---------+-------+ Using :normalizedp T, both view-classes need a primary key to join them on: (def-view-class node () ((node-id :accessor node-id :initarg :node-id :type integer :db-kind :key :db-constraints (:not-null)) (title :accessor title :initarg :title :type (varchar 240)))) SQL table NODE: +---------+--------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +---------+--------------+------+-----+---------+-------+ | NODE_ID | int(11) | NO | PRI | | | | TITLE | varchar(240) | YES | | NULL | | +---------+--------------+------+-----+---------+-------+ (def-view-class user (node) ((user-id :accessor user-id :initarg :user-id :type integer :db-kind :key :db-constraints (:not-null)) (nick :accessor nick :initarg :nick :type (varchar 64))) (:normalizedp t)) SQL table USER: +---------+-------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +---------+-------------+------+-----+---------+-------+ | USER_ID | int(11) | NO | PRI | | | | NICK | varchar(64) | YES | | NULL | | +---------+-------------+------+-----+---------+-------+ In this second case, all slots of the view-class 'node are also available in view-class 'user, and can be used as one would expect. For example, with the above normalized view-classes 'node and 'user, and SQL tracing turned on: CLSQL> (setq test-user (make-instance 'user :node-id 1 :nick "test-user" :title "This is a test user")) ]]> CLSQL> (update-records-from-instance test-user :database db) INSERT INTO NODE (NODE_ID,TITLE) VALUES (1,'This is a test user') ;; .. <= T ;; .. => INSERT INTO USER (USER_ID,NICK) VALUES (1,'test-user') ;; .. <= T 1 ]]> CLSQL> (node-id test-user) 1 CLSQL> (title test-user) "This is a test user" CLSQL> (nick test-user) "test-user" Notes from a refactor of this code. There are many assumptions that need to be met for normalized classes to work * The each of the classes should have its own single key column (of a different name) that will contain an identical value. EG: node has a node-id, setting which is a node has a node-id and a setting-id which must be equal. You cannot use node-id as the primary key on both tables (as I would have expected). The exception to this seems to be if your class has no slots at all, then you dont need to have a single key column, because your class is fully represented in the db by its parent(s) * more than one parent class per normalized class should be considered experimental and untested (vaya con Dios) * There are a few code paths that just dont pay any attention to normalized classes eg: delete-records-for-instance Examples The following examples are from the &clsql; test suite. (def-view-class person (thing) ((height :db-kind :base :accessor height :type float :initarg :height) (married :db-kind :base :accessor married :type boolean :initarg :married) (birthday :type clsql:wall-time :initarg :birthday) (bd-utime :type clsql:universal-time :initarg :bd-utime) (hobby :db-kind :virtual :initarg :hobby :initform nil))) (def-view-class employee (person) ((emplid :db-kind :key :db-constraints :not-null :type integer :initarg :emplid) (groupid :db-kind :key :db-constraints :not-null :type integer :initarg :groupid) (first-name :accessor first-name :type (varchar 30) :initarg :first-name) (last-name :accessor last-name :type (varchar 30) :initarg :last-name) (email :accessor employee-email :type (varchar 100) :initarg :email) (ecompanyid :type integer :initarg :companyid) (company :accessor employee-company :db-kind :join :db-info (:join-class company :home-key ecompanyid :foreign-key companyid :set nil)) (managerid :type integer :initarg :managerid) (manager :accessor employee-manager :db-kind :join :db-info (:join-class employee :home-key managerid :foreign-key emplid :set nil)) (addresses :accessor employee-addresses :db-kind :join :db-info (:join-class employee-address :home-key emplid :foreign-key aemplid :target-slot address :set t))) (:base-table employee)) (def-view-class company () ((companyid :db-kind :key :db-constraints :not-null :type integer :initarg :companyid) (groupid :db-kind :key :db-constraints :not-null :type integer :initarg :groupid) (name :type (varchar 100) :initarg :name) (presidentid :type integer :initarg :presidentid) (president :reader president :db-kind :join :db-info (:join-class employee :home-key presidentid :foreign-key emplid :set nil)) (employees :reader company-employees :db-kind :join :db-info (:join-class employee :home-key (companyid groupid) :foreign-key (ecompanyid groupid) :set t)))) (def-view-class address () ((addressid :db-kind :key :db-constraints :not-null :type integer :initarg :addressid) (street-number :type integer :initarg :street-number) (street-name :type (varchar 30) :void-value "" :initarg :street-name) (city :column "city_field" :void-value "no city" :type (varchar 30) :initarg :city) (postal-code :column zip :type integer :void-value 0 :initarg :postal-code)) (:base-table addr)) ;; many employees can reside at many addressess (def-view-class employee-address () ((aemplid :type integer :initarg :emplid) (aaddressid :type integer :initarg :addressid) (verified :type boolean :initarg :verified) (address :db-kind :join :db-info (:join-class address :home-key aaddressid :foreign-key addressid :retrieval :immediate))) (:base-table "ea_join")) (def-view-class deferred-employee-address () ((aemplid :type integer :initarg :emplid) (aaddressid :type integer :initarg :addressid) (verified :type boolean :initarg :verified) (address :db-kind :join :db-info (:join-class address :home-key aaddressid :foreign-key addressid :retrieval :deferred :set nil))) (:base-table "ea_join")) Side Effects Creates a new CLOS class. Affected by Nothing. Exceptional Situations None. See Also create-view-from-class standard-db-object drop-view-from-class Notes The actual SQL type for a column depends up the database type in which the SQL table is stored. As an example, the view class type (varchar 100) specifies a SQL column type VARCHAR(100) in &mysql; and a column type VARCHAR2(100) in &oracle; The actual lisp type for a slot may be different than the value specified by the :type attribute. For example, a slot declared with ":type (string 30)" actually sets the slots Lisp type as (or null string). This is to allow a &nil; value or a string shorter than 30 characters to be stored in the slot. DROP-VIEW-FROM-CLASS Delete table from SQL database. Function Syntax drop-view-from-class view-class-name &key database => Arguments and Values view-class-name The name of the View Class. database database object. This will default to the value of *default-database*. Description Removes a table defined by the View Class view-class-name from database which defaults to *default-database*. Examples (list-tables) => ("FOO" "BAR") (drop-view-from-class 'foo) => (list-tables) => ("BAR") Side Effects Deletes a table from the SQL database. Affected by Whether the specified table exists in the SQL database. Exceptional Situations A condition may be signalled if the table does not exist in the SQL database or if the SQL connection does not have sufficient permissions to delete tables. See Also create-view-from-class def-view-class Notes None. LIST-CLASSES List classes for tables in SQL database. Function Syntax list-classes &key test root-class database => classes Arguments and Values test a function used to filter the search. By default, identity is used which will return all classes. root-class specifies the root class to the search. By default, standard-db-object is used which is the root for all view classes. database The database to search for view classes. This will default to the value of *default-database*. classes List of view classes. Description Returns a list of all the View Classes which have been defined in the Lisp session and are connected to database and which descended from the class root-class and which satisfy the function test. Examples (list-classes) => (#<clsql-sys::standard-db-class big> #<clsql-sys::standard-db-class employee-address> #<clsql-sys::standard-db-class address> #<clsql-sys::standard-db-class company> #<clsql-sys::standard-db-class employee>) (list-classes :test #'(lambda (c) (> (length (symbol-name (class-name c))) 3))) => (#<clsql-sys::standard-db-class employee-address> #<clsql-sys::standard-db-class address> #<clsql-sys::standard-db-class company> #<clsql-sys::standard-db-class employee>) Side Effects None. Affected by Which view classes have been defined in the Lisp session. Exceptional Situations None. See Also def-view-class Notes None. cl-sql-6.4.1/doc/ref-fdml.xml0000644000175000017500000023661210667176647014750 0ustar kevinkevin %myents; ]> Functional Data Manipulation Language (FDML) The functional data manipulation interface provided by &clsql; includes functions for inserting, updating and deleting records in existing database tables and executing SQL queries and statements with the results of queries returned as Lisp types. SQL statements expressed as strings may be executed with the query and execute-command functions. The select function, on the other hand, allows for the construction of queries in Lisp using the symbolic SQL syntax. Finally, iterative manipulation of query results is supported by do-query, map-query and an extended clause for the loop macro. *CACHE-TABLE-QUERIES-DEFAULT* *CACHE-TABLE-QUERIES-DEFAULT* Specifies the default behaviour for caching of attribute types. Variable Value Type A valid argument to the action parameter of cache-table-queries, i.e. one of &t; &nil; :flush . Initial Value nil Description Specifies the default behaivour for caching of attribute types. Meaningful values are &t;, &nil; and :flush as described for the action argument to cache-table-queries. Examples None. Affected By None. See Also cache-table-queries Notes None. CACHE-TABLE-QUERIES CACHE-TABLE-QUERIES Control the caching of table attribute types. Function Syntax cache-table-queries table &key action database => Arguments and Values table A string representing a database table, &t; or :default. action &t;, &nil; or :flush. database A database object. This will default to the value of *default-database*. Description Controls the caching of attribute type information on the table specified by table in database which defaults to *default-database*. action specifies the caching behaviour to adopt. If its value is &t; then attribute type information is cached whereas if its value is &nil; then attribute type information is not cached. If action is :flush then all existing type information in the cache for table is removed, but caching is still enabled. table may be a string representing a table for which the caching action is to be taken while the caching action is applied to all tables if table is &t;. Alternatively, when table is :default, the default caching action specified by *cache-table-queries-default* is applied to all tables for which a caching action has not been explicitly set. Examples (setf *cache-table-queries-default* t) => T (create-table [foo] '(([id] integer) ([height] float) ([name] (string 24)) ([comments] varchar))) => (cache-table-queries "foo") => (list-attribute-types "foo") => (("id" :INT4 4 NIL 1) ("height" :FLOAT8 8 NIL 1) ("name" :BPCHAR 24 NIL 1) ("comments" :VARCHAR 255 NIL 1)) (drop-table "foo") => (create-table [foo] '(([id] integer) ([height] float) ([name] (string 36)) ([comments] (string 100)))) => (cache-table-queries "foo" :action :flush) => (list-attribute-types "foo") => (("id" :INT4 4 NIL 1) ("height" :FLOAT8 8 NIL 1) ("name" :BPCHAR 36 NIL 1) ("comments" :BPCHAR 100 NIL 1)) Side Effects The internal attribute cache for database is modified. Affected by *cache-table-queries-default* Exceptional Situations None. See Also *cache-table-queries-default* Notes None. INSERT-RECORDS INSERT-RECORDS Insert tuples of data into a database table. Function Syntax insert-records &key into attributes values av-pairs query database => Arguments and Values into A string, symbol or symbolic SQL expression representing the name of a table existing in database. attributes A list of attribute identifiers or &nil;. values A list of attribute values or &nil;. av-pairs A list of attribute identifier/value pairs or &nil;. query A query expression or &nil;. database A database object. This will default to the value of *default-database*. Description Inserts records into the table specified by into in database which defaults to *default-database*. There are five ways of specifying the values inserted into each row. In the first values contains a list of values to insert and attributes, av-pairs and query are &nil;. This can be used when values are supplied for all attributes in into. In the second, attributes is a list of column names, values is a corresponding list of values and av-pairs and query are &nil;. In the third, attributes, values and query are &nil; and av-pairs is an alist of (attribute value) pairs. In the fourth, values, av-pairs and attributes are &nil; and query is a symbolic SQL query expression in which the selected columns also exist in into. In the fifth method, values and av-pairs are nil and attributes is a list of column names and query is a symbolic SQL query expression which returns values for the specified columns. Examples (select [first-name] [last-name] [email] :from [employee] :where [= [emplid] 11] :field-names nil) => NIL (insert-records :into [employee] :attributes '(emplid groupid first_name last_name email ecompanyid managerid) :values '(11 1 "Yuri" "Gagarin" "gagarin@soviet.org" 1 1)) => (select [first-name] [last-name] [email] :from [employee] :where [= [emplid] 11] :field-names nil) => (("Yuri" "Gagarin" "gagarin@soviet.org")) Side Effects Modifications are made to the underlying database. Affected by None. Exceptional Situations An error of type sql-database-data-error is signalled if table is not an existing table in database or if the specified attributes are not found. See Also update-records delete-records Notes None. UPDATE-RECORDS UPDATE-RECORDS Updates the values of existing records. Function Syntax update-records table &key attributes values av-pairs where database => Arguments and Values table A string, symbol or symbolic SQL expression representing the name of a table existing in database. attributes A list of attribute identifiers or &nil;. values A list of attribute values or &nil;. av-pairs A list of attribute identifier/value pairs or &nil;. where A symbolic SQL expression. database A database object. This will default to the value of *default-database*. Description Updates the attribute values of existing records satsifying the SQL expression where in the table specified by table in database which defaults to *default-database*. There are three ways of specifying the values to update for each row. In the first, values contains a list of values to use in the update and attributes and av-pairs are &nil;. This can be used when values are supplied for all attributes in table. In the second, attributes is a list of column names, values is a corresponding list of values and av-pairs is &nil;. In the third, attributes and values are &nil; and av-pairs is an alist of (attribute value) pairs. Examples (select [first-name] [last-name] [email] :from [employee] :where [= [emplid] 1] :field-names nil) => (("Vladimir" "Lenin" "lenin@soviet.org")) (update-records [employee] :av-pairs'((first_name "Yuri") (last_name "Gagarin") (email "gagarin@soviet.org")) :where [= [emplid] 1]) => (select [first-name] [last-name] [email] :from [employee] :where [= [emplid] 1] :field-names nil) => (("Yuri" "Gagarin" "gagarin@soviet.org")) Side Effects Modifications are made to the underlying database. Affected by None. Exceptional Situations An error of type sql-database-data-error is signalled if table is not an existing table in database, if the specified attributes are not found or if the SQL statement resulting from the symbolic expression where does not return a Boolean value. If the execution of the SQL query leads to any errors, an error of type sql-database-error is signalled. See Also insert-records delete-records Notes None. DELETE-RECORDS DELETE-RECORDS Delete records from a database table. Function Syntax delete-records &key from where database => Arguments and Values from A string, symbol or symbolic SQL expression representing the name of a table existing in database. where A symbolic SQL expression. database A database object. This will default to the value of *default-database*. Description Deletes records satisfying the SQL expression where from the table specified by from in database specifies a database which defaults to *default-database*. Examples (select [first-name] [last-name] [email] :from [employee] :where [= [emplid] 11] :field-names nil) => (("Yuri" "Gagarin" "gagarin@soviet.org")) (delete-records :from [employee] :where [= [emplid] 11]) => (select [first-name] [last-name] [email] :from [employee] :where [= [emplid] 11] :field-names nil) => NIL Side Effects Modifications are made to the underlying database. Affected by None. Exceptional Situations An error of type sql-database-data-error is signalled if from is not an existing table in database or if the SQL statement resulting from the symbolic expression where does not return a Boolean value. See Also insert-records update-records Notes None. EXECUTE-COMMAND EXECUTE-COMMAND Execute an SQL command which returns no values. Generic Function Syntax execute-command sql-expression &key database => Arguments and Values sql-expression An sql expression that represents an SQL statement which will return no values. database A database object. This will default to the value of *default-database*. Description Executes the SQL command sql-expression, which may be a symbolic SQL expression or a string representing any SQL statement apart from a query, on the supplied database which defaults to *default-database*. Examples (execute-command "create table eventlog (time char(30),event char(70))") => (execute-command "create table eventlog (time char(30),event char(70))") >> >> While accessing database #<CLSQL-POSTGRESQL:POSTGRESQL-DATABASE {480B2B6D}> >> with expression "create table eventlog (time char(30),event char(70))": >> Error NIL: ERROR: amcreate: eventlog relation already exists >> has occurred. >> >> Restarts: >> 0: [ABORT] Return to Top-Level. >> >> Debug (type H for help) >> >> (CLSQL-POSTGRESQL::|(PCL::FAST-METHOD DATABASE-EXECUTE-COMMAND (T POSTGRESQL-DATABASE))| >> #<unused-arg> >> #<unused-arg> >> #<unavailable-arg> >> #<unavailable-arg>) >> Source: (ERROR 'SQL-DATABASE-ERROR :DATABASE DATABASE :EXPRESSION ...) >> 0] 0 (execute-command "drop table eventlog") => Side Effects Whatever effects the execution of the SQL statement has on the underlying database, if any. Affected by None. Exceptional Situations If the execution of the SQL statement leads to any errors, an error of type sql-database-error is signalled. See Also query Notes None. QUERY QUERY Execute an SQL query and return the tuples as a list. Generic Function Syntax query query-expression &key database result-types flatp field-names => result Arguments and Values query-expression An sql expression that represents an SQL query which is expected to return a (possibly empty) result set. database A database object. This will default to the value of *default-database*. flatp A Boolean whose default value is &nil;. result-types A field type specifier. The default is :auto;. The purpose of this argument is cause &clsql; to import SQL numeric fields into numeric Lisp objects rather than strings. This reduces the cost of allocating a temporary string and the &clsql; users' inconvenience of converting number strings into number objects. A value of :auto causes &clsql; to automatically convert SQL fields into a numeric format where applicable. The default value of &nil; causes all fields to be returned as strings regardless of the SQL type. Otherwise a list is expected which has a element for each field that specifies the conversion. Valid type identifiers are: :int Field is imported as a signed integer, from 8-bits to 64-bits depending upon the field type. :double Field is imported as a double-float number. t Field is imported as a string. If the list is shorter than the number of fields, the a value of t is assumed for the field. If the list is longer than the number of fields, the extra elements are ignored. field-names A boolean with a default value of &t;. When &t;, this function returns a second value of a list of field names. When &nil;, this function only returns one value - the list of rows. result A list representing the result set obtained. For each tuple in the result set, there is an element in this list, which is itself a list of all the attribute values in the tuple. Description Executes the SQL query expression query-expression, which may be an SQL expression or a string, on the supplied database which defaults to *default-database*. result-types is a list of symbols which specifies the lisp type for each field returned by query-expression. If result-types is &nil; all results are returned as strings whereas the default value of :auto means that the lisp types are automatically computed for each field. field-names is &t; by default which means that the second value returned is a list of strings representing the columns selected by query-expression. If field-names is &nil;, the list of column names is not returned as a second value. flatp has a default value of &nil; which means that the results are returned as a list of lists.If FLATP is &t; and only one result is returned for each record selected by query-expression, the results are returned as elements of a list. Examples (query "select emplid,first_name,last_name,height from employee where emplid = 1") => ((1 "Vladimir" "Lenin" 1.5564661d0)), ("emplid" "first_name" "last_name" "height") (query "select emplid,first_name,last_name,height from employee where emplid = 1" :field-names nil) => ((1 "Vladimir" "Lenin" 1.5564661d0)) (query "select emplid,first_name,last_name,height from employee where emplid = 1" :field-names nil :result-types nil) => (("1" "Vladimir" "Lenin" "1.5564661")) (query "select emplid,first_name,last_name,height from employee where emplid = 1" :field-names nil :result-types '(:int t t :double)) => ((1 "Vladimir" "Lenin" 1.5564661)) (query "select last_name from employee where emplid > 5" :flatp t) => ("Andropov" "Chernenko" "Gorbachev" "Yeltsin" "Putin"), ("last_name") (query "select last_name from employee where emplid > 10" :flatp t :field-names nil) => NIL Side Effects Whatever effects the execution of the SQL query has on the underlying database, if any. Affected by None. Exceptional Situations If the execution of the SQL query leads to any errors, an error of type sql-database-error is signalled. See Also execute-command print-query do-query map-query loop select Notes The field-names and result-types keyword arguments are a &clsql; extension. PRINT-QUERY PRINT-QUERY Prints a tabular report of query results. Function Syntax print-query query-expression &key titles formats sizes stream database => Arguments and Values query-expression An sql expression that represents an SQL query which is expected to return a (possibly empty) result set. database A database object. This will default to the value of *default-database*. titles A list of strings or &nil; which is the default value. formats A list of strings, &nil; or &t; which is the default value. sizes A list of numbers, &nil; or &t; which is the default value. stream An output stream or &t; which is the default value. Description Prints a tabular report of the results returned by the SQL query query-expression, which may be a symbolic SQL expression or a string, in database which defaults to *default-database*. The report is printed onto stream which has a default value of &t; which means that *standard-output* is used. The title argument, which defaults to &nil;, allows the specification of a list of strings to use as column titles in the tabular output. sizes accepts a list of column sizes, one for each column selected by query-expression, to use in formatting the tabular report. The default value of &t; means that minimum sizes are computed. formats is a list of format strings to be used for printing each column selected by query-expression. The default value of formats is &t; meaning that ~A is used to format all columns or ~VA if column sizes are used. Examples (print-query [select [emplid] [first-name] [last-name] [email] :from [employee] :where [< [emplid] 5]] :titles '("ID" "FORENAME" "SURNAME" "EMAIL")) ID FORENAME SURNAME EMAIL 1 Vladimir Lenin lenin@soviet.org 2 Josef Stalin stalin@soviet.org 3 Leon Trotsky trotsky@soviet.org 4 Nikita Kruschev kruschev@soviet.org => (print-query "select emplid,first_name,last_name,email from employee where emplid >= 5" :titles '("ID" "FORENAME" "SURNAME" "EMAIL")) ID FORENAME SURNAME EMAIL 5 Leonid Brezhnev brezhnev@soviet.org 6 Yuri Andropov andropov@soviet.org 7 Konstantin Chernenko chernenko@soviet.org 8 Mikhail Gorbachev gorbachev@soviet.org 9 Boris Yeltsin yeltsin@soviet.org 10 Vladimir Putin putin@soviet.org => Side Effects None. Affected by None. Exceptional Situations If the execution of the SQL query leads to any errors, an error of type sql-database-error is signalled. See Also query do-query map-query loop select Notes None. SELECT SELECT Executes a query given the supplied constraints. Function Syntax select &rest identifiers &key all distinct from group-by having limit offset order-by set-operation where result-types field-names flatp refresh caching database => result Arguments and Values identifiers A set of sql expressions each of which indicates a column to query. all A Boolean. distinct A Boolean. from One or more SQL expression representing tables. group-by An SQL expression. having An SQL expression. limit A non-negative integer. offset A non-negative integer. order-by An SQL expression. set-operation An SQL expression. where An SQL expression. database A database object. This will default to the value of *default-database*. flatp A Boolean whose default value is &nil;. result-types A field type specifier. The default is :auto. The purpose of this argument is cause &clsql; to import SQL numeric fields into numeric Lisp objects rather than strings. This reduces the cost of allocating a temporary string and the &clsql; users' inconvenience of converting number strings into number objects. A value of :auto causes &clsql; to automatically convert SQL fields into a numeric format where applicable. The default value of &nil; causes all fields to be returned as strings regardless of the SQL type. Otherwise a list is expected which has a element for each field that specifies the conversion. Valid type identifiers are: :int Field is imported as a signed integer, from 8-bits to 64-bits depending upon the field type. :double Field is imported as a double-float number. t Field is imported as a string. If the list is shorter than the number of fields, the a value of t is assumed for the field. If the list is longer than the number of fields, the extra elements are ignored. field-names A boolean with a default value of &t;. When &t;, this function returns a second value of a list of field names. When &nil;, this function only returns one value - the list of rows. refresh This value is only considered when CLOS objects are being selected. A boolean with a default value of &nil;. When the value of the caching keyword is &t;, a second equivalent select call will return the same view class instance objects. When refresh is &t;, then slots of the existing instances are updated as necessary. In such cases, you may wish to override the hook instance-refresh. caching This value is only considered when CLOS objects are being selected. A boolean with a default value of *default-caching*. &clsql; caches objects in accordance with the &commonsql; interface: a second equivalent select call will return the same view class instance objects. result A list representing the result set obtained. For each tuple in the result set, there is an element in this list, which is itself a list of all the attribute values in the tuple. Description Executes a query on database, which has a default value of *default-database*, specified by the SQL expressions supplied using the remaining arguments in args. The select function can be used to generate queries in both functional and object oriented contexts. In the functional case, the required arguments specify the columns selected by the query and may be symbolic SQL expressions or strings representing attribute identifiers. Type modified identifiers indicate that the values selected from the specified column are converted to the specified lisp type. The keyword arguments all, distinct, from, group-by, having, limit, offset, order-by, set-operation and where are used to specify, using the symbolic SQL syntax, the corresponding components of the SQL query generated by the call to select. result-types is a list of symbols which specifies the lisp type for each field returned by the query. If result-types is &nil; all results are returned as strings whereas the default value of :auto means that the lisp types are automatically computed for each field. field-names is &t; by default which means that the second value returned is a list of strings representing the columns selected by the query. If field-names is &nil;, the list of column names is not returned as a second value. In the object oriented case, the required arguments to select are symbols denoting View Classes which specify the database tables to query. In this case, select returns a list of View Class instances whose slots are set from the attribute values of the records in the specified table. Slot-value is a legal operator which can be employed as part of the symbolic SQL syntax used in the where keyword argument to select. refresh is &nil; by default which means that the View Class instances returned are retrieved from a cache if an equivalent call to select has previously been issued. If refresh is true, the View Class instances returned are updated as necessary from the database and the generic function instance-refreshed is called to perform any necessary operations on the updated instances. In both object oriented and functional contexts, flatp has a default value of &nil; which means that the results are returned as a list of lists. If flatp is t and only one result is returned for each record selected in the query, the results are returned as elements of a list. Examples (select [first-name] :from [employee] :flatp t :distinct t :field-names nil :result-types nil :order-by [first-name]) => ("Boris" "Josef" "Konstantin" "Leon" "Leonid" "Mikhail" "Nikita" "Vladimir" "Yuri") (select [first-name] [count [*]] :from [employee] :result-types nil :group-by [first-name] :order-by [first-name] :field-names nil) => (("Boris" "1") ("Josef" "1") ("Konstantin" "1") ("Leon" "1") ("Leonid" "1") ("Mikhail" "1") ("Nikita" "1") ("Vladimir" "2") ("Yuri" "1")) (select [last-name] :from [employee] :where [like [email] "%org"] :order-by [last-name] :field-names nil :result-types nil :flatp t) => ("Andropov" "Brezhnev" "Chernenko" "Gorbachev" "Kruschev" "Lenin" "Putin" "Stalin" "Trotsky" "Yeltsin") (select [max [emplid]] :from [employee] :flatp t :field-names nil :result-types :auto) => (10) (select [avg [height]] :from [employee] :flatp t :field-names nil) => (1.58999584d0) (select [emplid] [last-name] :from [employee] :where [= [emplid] 1]) => ((1 "Lenin")), ("emplid" "last_name") (select [emplid :string] :from [employee] :where [= 1 [emplid]] :field-names nil :flatp t) => ("1") (select [emplid] :from [employee] :order-by [emplid] :where [not [between [* [emplid] 10] [* 5 10] [* 10 10]]] :field-names nil :flatp t) => (1 2 3 4) (select [emplid] :from [employee] :where [in [emplid] '(1 2 3 4)] :flatp t :order-by [emplid] :field-names nil) => (1 2 3 4) (select [emplid] :from [employee] :order-by [emplid] :limit 5 :offset 3 :field-names nil :flatp t) => (4 5 6 7 8) (select [first-name] [last-name] :from [employee] :field-names nil :order-by '(([first-name] :asc) ([last-name] :desc))) => (("Boris" "Yeltsin") ("Josef" "Stalin") ("Konstantin" "Chernenko") ("Leon" "Trotsky") ("Leonid" "Brezhnev") ("Mikhail" "Gorbachev") ("Nikita" "Kruschev") ("Vladimir" "Putin") ("Vladimir" "Lenin") ("Yuri" "Andropov")) (select [last-name] :from [employee] :set-operation [union [select [first-name] :from [employee] :order-by [last-name]]] :flatp t :result-types nil :field-names nil) => ("Andropov" "Boris" "Brezhnev" "Chernenko" "Gorbachev" "Josef" "Konstantin" "Kruschev" "Lenin" "Leon" "Leonid" "Mikhail" "Nikita" "Putin" "Stalin" "Trotsky" "Vladimir" "Yeltsin" "Yuri") Side Effects Whatever effects the execution of the SQL query has on the underlying database, if any. Affected by None. Exceptional Situations If the execution of the SQL query leads to any errors, an error of type sql-database-error is signalled. See Also query print-query do-query map-query loop instance-refreshed Notes The select function is actually implemented in &clsql; with a single &rest parameter (which is subsequently destructured) rather than the keyword parameters presented here for the purposes of exposition. This means that incorrect or missing keywords or values may not trigger errors in the way that they would if select had been defined using keyword arguments. The field-names and result-types keyword arguments are a &clsql; extension. select is common across the functional and object-oriented data manipulation languages. DO-QUERY DO-QUERY Iterate over all the tuples of a query. Macro Syntax do-query ((&rest args) query-expression &key database result-types &body body => result Arguments and Values args A list of variable names. query-expression An sql expression that represents an SQL query which is expected to return a (possibly empty) result set, where each tuple has as many attributes as function takes arguments. database A database object. This will default to *default-database*. result-types A field type specifier. The default is &nil;. See query for the semantics of this argument. body A body of Lisp code, like in a destructuring-bind form. result The result of executing body. Description Repeatedly executes body within a binding of args on the fields of each row selected by the SQL query query-expression, which may be a string or a symbolic SQL expression, in database which defaults to *default-database*. The body of code is executed in a block named nil which may be returned from prematurely via return or return-from. In this case the result of evaluating the do-query form will be the one supplied to return or return-from. Otherwise the result will be nil. The body of code appears also is if wrapped in a destructuring-bind form, thus allowing declarations at the start of the body, especially those pertaining to the bindings of the variables named in args. result-types is a list of symbols which specifies the lisp type for each field returned by query-expression. If result-types is &nil; all results are returned as strings whereas the default value of :auto means that the lisp types are automatically computed for each field. query-expression may be an object query (i.e., the selection arguments refer to View Classes), in which case args are bound to the tuples of View Class instances returned by the object oriented query. Examples (do-query ((salary name) "select salary,name from simple") (format t "~30A gets $~2,5$~%" name (read-from-string salary))) >> Mai, Pierre gets $10000.00 >> Hacker, Random J. gets $08000.50 => NIL (do-query ((salary name) "select salary,name from simple") (return (cons salary name))) => ("10000.00" . "Mai, Pierre") (let ((result '())) (do-query ((name) [select [last-name] :from [employee] :order-by [last-name]]) (push name result)) result) => ("Yeltsin" "Trotsky" "Stalin" "Putin" "Lenin" "Kruschev" "Gorbachev" "Chernenko" "Brezhnev" "Andropov") (let ((result '())) (do-query ((e) [select 'employee :order-by [last-name]]) (push (slot-value e 'last-name) result)) result) => ("Yeltsin" "Trotsky" "Stalin" "Putin" "Lenin" "Kruschev" "Gorbachev" "Chernenko" "Brezhnev" "Andropov") Side Effects Whatever effects the execution of the SQL query has on the underlying database, if any. Affected by None. Exceptional Situations If the execution of the SQL query leads to any errors, an error of type sql-database-error is signalled. If the number of variable names in args and the number of attributes in the tuples in the result set don't match up, an error is signalled. See Also query map-query print-query loop select Notes The result-types keyword argument is a &clsql; extension. do-query is common across the functional and object-oriented data manipulation languages. LOOP LOOP Extension to Common Lisp Loop to iterate over all the tuples of a query via a loop clause. Loop Clause Syntax {as | for} var [type-spec] being {each | the} {record | records | tuple | tuples} {in | of} query [from database] Arguments and Values var A d-var-spec, as defined in the grammar for loop-clauses in the ANSI Standard for Common Lisp. This allows for the usual loop-style destructuring. type-spec An optional type-spec either simple or destructured, as defined in the grammar for loop-clauses in the ANSI Standard for Common Lisp. query An sql expression that represents an SQL query which is expected to return a (possibly empty) result set, where each tuple has as many attributes as function takes arguments. database An optional database object. This will default to the value of *default-database*. Description This clause is an iteration driver for loop, that binds the given variable (possibly destructured) to the consecutive tuples (which are represented as lists of attribute values) in the result set returned by executing the SQL query expression on the database specified. query may be an object query (i.e., the selection arguments refer to View Classes), in which case the supplied variable is bound to the tuples of View Class instances returned by the object oriented query. Examples (defvar *my-db* (connect '("dent" "newesim" "dent" "dent")) "My database" => *MY-DB* (loop with time-graph = (make-hash-table :test #'equal) with event-graph = (make-hash-table :test #'equal) for (time event) being the tuples of "select time,event from log" from *my-db* do (incf (gethash time time-graph 0)) (incf (gethash event event-graph 0)) finally (flet ((show-graph (k v) (format t "~40A => ~5D~%" k v))) (format t "~&Time-Graph:~%===========~%") (maphash #'show-graph time-graph) (format t "~&~%Event-Graph:~%============~%") (maphash #'show-graph event-graph)) (return (values time-graph event-graph))) >> Time-Graph: >> =========== >> D => 53000 >> X => 3 >> test-me => 3000 >> >> Event-Graph: >> ============ >> CLOS Benchmark entry. => 9000 >> Demo Text... => 3 >> doit-text => 3000 >> C Benchmark entry. => 12000 >> CLOS Benchmark entry => 32000 => #<EQUAL hash table, 3 entries {48350A1D}> => #<EQUAL hash table, 5 entries {48350FCD}> (loop for (forename surname) being each tuple in [select [first-name] [last-name] :from [employee] :order-by [last-name]] collect (concatenate 'string forename " " surname)) => ("Yuri Andropov" "Leonid Brezhnev" "Konstantin Chernenko" "Mikhail Gorbachev" "Nikita Kruschev" "Vladimir Lenin" "Vladimir Putin" "Josef Stalin" "Leon Trotsky" "Boris Yeltsin") (loop for (e) being the records in [select 'employee :where [< [emplid] 4] :order-by [emplid]] collect (slot-value e 'last-name)) => ("Lenin" "Stalin" "Trotsky") Side Effects Whatever effects the execution of the SQL query has on the underlying database, if any. Affected by None. Exceptional Situations If the execution of the SQL query leads to any errors, an error of type sql-database-error is signalled. Otherwise, any of the exceptional situations of loop applies. See Also query map-query do-query print-query select Notes The database loop keyword is a &clsql; extension. The extended loop syntax is common across the functional and object-oriented data manipulation languages. MAP-QUERY MAP-QUERY Map a function over all the tuples from a query Function Syntax map-query output-type-spec function query-expression &key database result-types => result Arguments and Values output-type-spec A sequence type specifier or nil. function A function designator. function takes a single argument which is the atom value for a query single with a single column or is a list of values for a multi-column query. query-expression An sql expression that represents an SQL query which is expected to return a (possibly empty) result set. database A database object. This will default to the value of *default-database*. result-types A field type specifier. The default is &nil;. See query for the semantics of this argument. result If output-type-spec is a type specifier other than nil, then a sequence of the type it denotes. Otherwise nil is returned. Description Applies function to the successive tuples in the result set returned by executing the SQL query-expression. If the output-type-spec is nil, then the result of each application of function is discarded, and map-query returns nil. Otherwise the result of each successive application of function is collected in a sequence of type output-type-spec, where the jths element is the result of applying function to the attributes of the jths tuple in the result set. The collected sequence is the result of the call to map-query. If the output-type-spec is a subtype of list, the result will be a list. If the result-type is a subtype of vector, then if the implementation can determine the element type specified for the result-type, the element type of the resulting array is the result of upgrading that element type; or, if the implementation can determine that the element type is unspecified (or *), the element type of the resulting array is t; otherwise, an error is signaled. If result-types is &nil; all results are returned as strings whereas the default value of :auto means that the lisp types are automatically computed for each field. query-expression may be an object query (i.e., the selection arguments refer to View Classes), in which case the supplied function is applied to the tuples of View Class instances returned by the object oriented query. Examples (map-query 'list #'(lambda (tuple) (multiple-value-bind (salary name) tuple (declare (ignorable name)) (read-from-string salary))) "select salary,name from simple where salary > 8000") => (10000.0 8000.5) (map-query '(vector double-float) #'(lambda (tuple) (multiple-value-bind (salary name) tuple (declare (ignorable name)) (let ((*read-default-float-format* 'double-float)) (coerce (read-from-string salary) 'double-float)) "select salary,name from simple where salary > 8000"))) => #(10000.0d0 8000.5d0) (type-of *) => (SIMPLE-ARRAY DOUBLE-FLOAT (2)) (let (list) (values (map-query nil #'(lambda (tuple) (multiple-value-bind (salary name) tuple (push (cons name (read-from-string salary)) list)) "select salary,name from simple where salary > 8000")) list)) => NIL => (("Hacker, Random J." . 8000.5) ("Mai, Pierre" . 10000.0)) (map-query 'vector #'identity [select [last-name] :from [employee] :flatp t :order-by [last-name]]) => #("Andropov" "Brezhnev" "Chernenko" "Gorbachev" "Kruschev" "Lenin" "Putin" "Stalin" "Trotsky" "Yeltsin") (map-query 'list #'identity [select [first-name] [last-name] :from [employee] :order-by [last-name]]) => (("Yuri" "Andropov") ("Leonid" "Brezhnev") ("Konstantin" "Chernenko") ("Mikhail" "Gorbachev") ("Nikita" "Kruschev") ("Vladimir" "Lenin") ("Vladimir" "Putin") ("Josef" "Stalin") ("Leon" "Trotsky") ("Boris" "Yeltsin")) (map-query 'list #'last-name [select 'employee :order-by [emplid]]) => ("Lenin" "Stalin" "Trotsky" "Kruschev" "Brezhnev" "Andropov" "Chernenko" "Gorbachev" "Yeltsin" "Putin") Side Effects Whatever effects the execution of the SQL query has on the underlying database, if any. Affected by None. Exceptional Situations If the execution of the SQL query leads to any errors, an error of type sql-database-error is signalled. An error of type type-error must be signaled if the output-type-spec is not a recognizable subtype of list, not a recognizable subtype of vector, and not nil. An error of type type-error should be signaled if output-type-spec specifies the number of elements and the size of the result set is different from that number. See Also query do-query print-query loop select Notes The result-types keyword argument is a &clsql; extension. map-query is common across the functional and object-oriented data manipulation languages. cl-sql-6.4.1/doc/ref-lob.xml0000644000175000017500000001474610667176647014604 0ustar kevinkevin %myents; ]> Large Object Support CREATE-LARGE-OBJECT Function Syntax (CREATE-LARGE-OBJECT &KEY (DATABASE *DEFAULT-DATABASE*)) [function] => Arguments and Values Description Creates a new large object in the database and returns the object identifier Examples Side Effects Affected by Exceptional Situations See Also Notes DELETE-LARGE-OBJECT Function Syntax (DELETE-LARGE-OBJECT OBJECT-ID &KEY (DATABASE *DEFAULT-DATABASE*)) [function] => Arguments and Values Description Deletes the large object in the database Examples Side Effects Affected by Exceptional Situations See Also Notes READ-LARGE-OBJECT Function Syntax (READ-LARGE-OBJECT OBJECT-ID &KEY (DATABASE *DEFAULT-DATABASE*)) [function] => Arguments and Values Description Reads the large object content Examples Side Effects Affected by Exceptional Situations See Also Notes WRITE-LARGE-OBJECT Function Syntax (WRITE-LARGE-OBJECT OBJECT-ID DATA &KEY (DATABASE *DEFAULT-DATABASE*)) [function] => Arguments and Values Description Writes data to the large object Examples Side Effects Affected by Exceptional Situations See Also Notes cl-sql-6.4.1/doc/bookinfo.xml0000644000175000017500000000401711335067642015035 0ustar kevinkevin %myents; ]> &clsql; Users' Guide Kevin M. Rosenberg Maintainer of &clsql; Marcus T. Pearce Contributor to &clsql; Pierre R. Mai Author of Original MaiSQL Code onShore Development, Inc. Author of UncommonSQL Package &clsql; is Copyright © 2002-2010 by Kevin M. Rosenberg, Copyright © 1999-2001 by Pierre R. Mai, and Copyright © 1999-2003 onShore Development, Inc. Allegro CL® is a registered trademark of Franz Inc. Common SQL, LispWorks are trademarks or registered trademarks of LispWorks Ltd. Oracle® is a registered trademark of Oracle Inc. Microsoft Windows® is a registered trademark of Microsoft Inc. Other brand or product names are the registered trademarks or trademarks of their respective holders. cl-sql-6.4.1/doc/catalog-debian.xml0000644000175000017500000000266210667176647016102 0ustar kevinkevin cl-sql-6.4.1/doc/intro.xml0000644000175000017500000002157410667176647014406 0ustar kevinkevin %myents; ]> Introduction Purpose &clsql; is a Common Lisp interface to SQL databases. A number of Common Lisp implementations and SQL databases are supported. The general structure of &clsql; is based on the &commonsql; package by LispWorks Ltd. History The &clsql; project was started by Kevin M. Rosenberg in 2001 to support SQL access on multiple Common Lisp implementations using the &uffi; library. The initial code was based substantially on Pierre R. Mai's excellent &maisql; package. In late 2003, the &usql; library was orphaned by its author, onShore Development, Inc. In April 2004, Marcus Pearce ported the &usql; library to &clsql;. The &usql; library provides a &commonsql;-compatible API for &clsql;. The main changes from &maisql; and &usql; are: Port from the &cmucl; FFI to &uffi; which provide compatibility with the major Common Lisp implementations. Optimized loading of integer and floating-point fields. Additional database backends: &odbc;, &aodbc;, &sqlite; and &sqlite3;. A compatibility layer for &cmucl; specific code. Much improved robustness for the &mysql; back-end along with version 4 client library support. Improved library loading and installation documentation. Improved packages and symbol export. Pooled connections. Integrated transaction support for the classic &maisql; iteration macros. Prerequisites &asdf; &clsql; uses &asdf; to compile and load its components. &asdf; is included in the &cclan; collection. &uffi; &clsql; uses &uffi; as a Foreign Function Interface (FFI) to support multiple &cl; implementations. &md5; &clsql;'s postgresql-socket interface uses Pierre Mai's md5 module. Supported Common Lisp Implementation The implementations that support &clsql; is governed by the supported implementations of &uffi;. The following implementations are supported: &acl; v6.2 through 8.0 on Debian Linux x86 & x86_64 & PowerPC, FreeBSD 4.5, and Microsoft Windows XP. &lw; v4.3 and v4.4 on Debian Linux and Microsoft Windows XP. &cmucl; 18e on Debian Linux, FreeBSD 4.5, and Solaris 2.8. 19c on Debian Linux. &sbcl; 0.8.4 through 0.9.16 on Debian Linux. &scl; 1.1.1 on Debian Linux. &openmcl; 0.14 PowerPC and 1.0pre AMD64 on Debian Linux . Supported &sql; Implementation &clsql; supports the following databases: &mysql; (tested v3.23.51, v4.0.18, 5.0.24). &postgresql; (tested with v7.4 and 8.0 with both direct API and TCP socket connections. &sqlite;. &sqlite3;. Direct &odbc; interface. &oracle; OCI. Allegro's DB interface (&aodbc;). Installation Ensure &asdf; is loaded Simply load the file asdf.lisp. (load "asdf.lisp") Build &c; helper libraries &clsql; uses functions that require 64-bit integer parameters and return values. The &ffi; in most &clsql; implementations do not support 64-bit integers. Thus, C helper libraries are required to break these 64-bit integers into two compatible 32-bit integers. The helper libraries reside in the directories uffi and db-mysql. &mswindows; Files named Makefile.msvc are supplied for building the libraries under Microsoft Windows. Since &mswindows; does not come with that compiler, compiled DLL and LIB library files are supplied with &clsql;. &unix; Files named Makefile are supplied for building the libraries under &unix;. Loading the .asd files automatically invokes make when necessary. So, manual building of the helper libraries is not necessary on most &unix; systems. However, the location of the &mysql; library files and include files may need to adjusted in db-mysql/Makefile on non-Debian systems. Add &uffi; path Unzip or untar the &uffi; distribution which creates a directory for the &uffi; files. Add that directory to &asdf;'s asdf:*central-registry*. You can do that by pushing the pathname of the directory onto this variable. The following example code assumes the &uffi; files reside in the /usr/share/lisp/uffi/ directory. (push #P"/usr/share/lisp/uffi/" asdf:*central-registry*) Add &md5; path If you plan to use the clsql-postgresql-socket interface, you must load the md5 module. Unzip or untar the cl-md5 distribution, which creates a directory for the cl-md5 files. Add that directory to &asdf;'s asdf:*central-registry*. You can do that by pushing the pathname of the directory onto this variable. The following example code assumes the cl-md5 files reside in the /usr/share/lisp/cl-md5/ directory. (push #P"/usr/share/lisp/cl-md5/" asdf:*central-registry*) Add &clsql; path and load module Unzip or untar the &clsql; distribution which creates a directory for the &clsql; files. Add that directory to &asdf;'s asdf:*central-registry*. You can do that by pushing the pathname of the directory onto this variable. The following example code assumes the &clsql; files reside in the /usr/share/lisp/clsql/ directory. You need to load the clsql system. (push #P"/usr/share/lisp/clsql/" asdf:*central-registry*) (asdf:operate 'asdf:load-op 'clsql) ; main CLSQL package Run test suite (optional) The test suite can be executed using the &asdf; test-op operator. If &clsql; has not been loaded with asdf:load-op, the asdf:test-op operator will automatically load &clsql;. A configuration file named .clsql-test.config must be created in your home directory. There are instructures on the format of that file in the tests/README. After creating .clsql-test.config, you can run the test suite with &asdf;: (asdf:operate 'asdf:test-op 'clsql) cl-sql-6.4.1/doc/mysql-macosx-notes.txt0000644000175000017500000000405310667176647017046 0ustar kevinkevinInstructions: ---------------- 1. Install MySQL from Fink, not from mysql.com It is sufficient to install the binaries from Fink. CLSQL requires the MySQL library libmysqlclient.dylib; this library is not provided with the mysql binary install. This library is in /sw/lib/mysql . However, it is actually called libmysqlclient.14.0.0.dylib . ----------------- 2. After installing MySQL, do the following at the shell. (Assuming that you do not want to have to load CLSQL as root user every time you use it.) 2a. Create a symbolic link from libmysqlclient.14.0.0.dylib to the name libmysqlclient.dylib . 2b. Change ownership to yourself along the path /sw/lib/mysql/ libmysqlclient.dylib . ----------------- 3. Either install CocoaMySQL or download the source of MySQL (e.g. 5.0) from mysql.com. CLSQL requires MySQL's header files. These files are not provided with Fink's binary MySQL install. In CocoaMySQL the headers are found at: /Applications/CocoaMySQL.app/ Contents/Frameworks/SMySQL.framework/Versions/A/Headers In MySQL 5.0 sources, the headers are found at: ~/Desktop/ mysql-5.0.15/include 3a. Copy the directory full of headers to /sw/include/mysql 3b. Make yourself the owner of these files. You may now dispose of CocoaMySQL or the MySQL sources, if you desire. ----------------- 4. In the CLSQL sources, modify db-mysql/makefile to read as follows: ... CFLAGS="-I /sw/include/mysql" LDFLAGS=" -L/sw/lib/mysql/ ... ----------------- 5. In Lisp, do the following: Assuming asdf and the CLSQL & UFFI sources are in the same directory; substitute the appropriate path for ~ . The code below is right out of the CLSQL docs, but note particularly the commented expression. (load "~/asdf.lisp") (progn (push "~/uffi-1.5.5/" asdf:*central-registry*) (asdf:operate 'asdf:load-op :uffi) (push "~/clsql-3.3.4/" asdf:*central-registry*) (asdf:operate 'asdf:load-op :clsql)) (progn (in-package :clsql) (setf *default-database-type* :mysql) (clsql:push-library-path "/sw/lib/mysql/") ; !! (asdf:operate 'asdf:load-op 'clsql-mysql)) cl-sql-6.4.1/doc/ref-prepared.xml0000644000175000017500000001640410667176647015623 0ustar kevinkevin %myents; ]> Prepared Statements PREPARE-SQL >PREPARE-SQL Create a prepared statement. Function Syntax prepare-sql sql-stmt types &key database result-types field-names => result Arguments and Values Description Prepares a SQL statement sql-stmt for execution. types contains a list of types corresponding to the input parameters. Returns a prepared-statement object. A type can be :int :double :null (:string n) Examples Side Effects Affected by Exceptional Situations See Also Notes RUN-PREPARED-SQL RUN-PREPARED-SQL Execute a prepared statement. Function Syntax run-prepared-sql prepared-stmt => Arguments and Values Description Execute the prepared sql statment. All input parameters must be bound. Examples Side Effects Affected by Exceptional Situations See Also Notes FREE-PREPARED-SQL FREE-PREPARED-SQL Delete a prepared statement object. Function Syntax free-prepared-sql prepared-stmt => Arguments and Values Description Delete the objects associated with a prepared statement. Examples Side Effects Affected by Exceptional Situations See Also Notes BIND-PARAMETER BIND-PARAMETER Bind a parameter in a prepared statement. Function Syntax bind-parameter prepared-stmt position value => Arguments and Values Description Sets the value of a parameter in a prepared statement. Examples Side Effects Affected by Exceptional Situations See Also Notes cl-sql-6.4.1/doc/ref-syntax.xml0000644000175000017500000011061511345753563015336 0ustar kevinkevin %myents; ]> The Symbolic SQL Syntax &clsql; provides a symbolic syntax allowing the construction of SQL expressions as lists delimited by square brackets. The syntax is turned off by default. This section describes utilities for enabling and disabling the square bracket reader syntax and for constructing symbolic SQL expressions. Tip: just want it on file-enable-sql-reader-syntax at the top of each file is easiest. ENABLE-SQL-READER-SYNTAX ENABLE-SQL-READER-SYNTAX Globally enable square bracket reader syntax. Macro Syntax enable-sql-reader-syntax => Arguments and Values None. Description Turns on the SQL reader syntax setting the syntax state such that if the syntax is subsequently disabled, restore-sql-reader-syntax-state will enable it again. Examples None. Side Effects Sets the internal syntax state to enabled. Modifies the default readtable. &clsql; tries to keep track of whether the syntax has already been enabled. This can be problematic if the syntax is somehow disabled externally to &clsql; as future attempts to enable the syntax will do nothing--the system thinks it is already enabled. This may happen if there is an enable, but no disable, in a file that is processed with load or compile-file as the lisp implementation will restore the readtable on completion. Or, even if there is a disable but a compiler-error is encountered before running the disable. If you encounter this try running disable-sql-reader-syntax a couple times in the REPL. See file-enable-sql-reader-syntax for an alternative. Affected by None. Exceptional Situations None. See Also disable-sql-reader-syntax locally-enable-sql-reader-syntax locally-disable-sql-reader-syntax restore-sql-reader-syntax-state file-enable-sql-reader-syntax Notes The symbolic SQL syntax is disabled by default. &clsql; differs from &commonsql; in that enable-sql-reader-syntax is defined as a macro rather than a function. DISABLE-SQL-READER-SYNTAX DISABLE-SQL-READER-SYNTAX Globally disable square bracket reader syntax. Macro Syntax disable-sql-reader-syntax => Arguments and Values None. Description Turns off the SQL reader syntax setting the syntax state such that if the syntax is subsequently enabled, restore-sql-reader-syntax-state will disable it again. Examples None. Side Effects Sets the internal syntax state to disabled. Modifies the default readtable. Affected by None. Exceptional Situations None. See Also enable-sql-reader-syntax locally-enable-sql-reader-syntax locally-disable-sql-reader-syntax restore-sql-reader-syntax-state file-enable-sql-reader-syntax Notes The symbolic SQL syntax is disabled by default. &clsql; differs from &commonsql; in that disable-sql-reader-syntax is defined as a macro rather than a function. LOCALLY-ENABLE-SQL-READER-SYNTAX LOCALLY-ENABLE-SQL-READER-SYNTAX Locally enable square bracket reader syntax. Macro Syntax locally-enable-sql-reader-syntax => Arguments and Values None. Description Turns on the SQL reader syntax without changing the syntax state such that restore-sql-reader-syntax-state will re-establish the current syntax state. Examples Intended to be used in a file for code which uses the square bracket syntax without changing the global state. #.(locally-enable-sql-reader-syntax) ... CODE USING SYMBOLIC SQL SYNTAX ... #.(restore-sql-reader-syntax-state) Side Effects Modifies the default readtable. &clsql; tries to keep track of whether the syntax has already been enabled. This can be problematic if the syntax is somehow disabled externally to &clsql; as future attempts to enable the syntax will do nothing--the system thinks it is already enabled. This may happen if there is an enable, but no disable, in a file that is processed with load or compile-file as the lisp implementation will restore the readtable on completion. Or, even if there is a disable but a compiler-error is encountered before running the disable. If you encounter this try running disable-sql-reader-syntax a couple times in the REPL. See file-enable-sql-reader-syntax for an alternative. Affected by None. Exceptional Situations None. See Also enable-sql-reader-syntax disable-sql-reader-syntax locally-disable-sql-reader-syntax restore-sql-reader-syntax-state file-enable-sql-reader-syntax Notes The symbolic SQL syntax is disabled by default. &clsql; differs from &commonsql; in that locally-enable-sql-reader-syntax is defined as a macro rather than a function. LOCALLY-DISABLE-SQL-READER-SYNTAX LOCALLY-DISABLE-SQL-READER-SYNTAX Locally disable square bracket reader syntax. Macro Syntax locally-disable-sql-reader-syntax => Arguments and Values None. Description Turns off the SQL reader syntax without changing the syntax state such that restore-sql-reader-syntax-state will re-establish the current syntax state. Examples Intended to be used in a file for code in which the square bracket syntax should be disabled without changing the global state. #.(locally-disable-sql-reader-syntax) ... CODE NOT USING SYMBOLIC SQL SYNTAX ... #.(restore-sql-reader-syntax-state) Side Effects Modifies the default readtable. Affected by None. Exceptional Situations None. See Also enable-sql-reader-syntax disable-sql-reader-syntax locally-enable-sql-reader-syntax restore-sql-reader-syntax-state file-enable-sql-reader-syntax Notes The symbolic SQL syntax is disabled by default. &clsql; differs from &commonsql; in that locally-disable-sql-reader-syntax is defined as a macro rather than a function. RESTORE-SQL-READER-SYNTAX-STATE RESTORE-SQL-READER-SYNTAX-STATE Restore square bracket reader syntax to its previous state. Macro Syntax restore-sql-reader-syntax-state => Arguments and Values None. Description Enables the SQL reader syntax if enable-sql-reader-syntax has been called more recently than disable-sql-reader-syntax and otherwise disables the SQL reader syntax. By default, the SQL reader syntax is disabled. Examples See locally-enable-sql-reader-syntax and locally-disable-sql-reader-syntax. Side Effects Reverts the internal syntax state. Modifies the default readtable. Affected by The current internal syntax state. Exceptional Situations None. See Also enable-sql-reader-syntax disable-sql-reader-syntax locally-enable-sql-reader-syntax locally-disable-sql-reader-syntax file-enable-sql-reader-syntax Notes The symbolic SQL syntax is disabled by default. &clsql; differs from &commonsql; in that restore-sql-reader-syntax-state is defined as a macro rather than a function. FILE-ENABLE-SQL-READER-SYNTAX FILE-ENABLE-SQL-READER-SYNTAX Enable the square bracket reader syntax for the duration of the file. Macro Syntax file-enable-sql-reader-syntax => Arguments and Values None. Description Uncoditionally enables the SQL reader syntax. Unlike enable-sql-reader-syntax and disable-sql-reader-syntax which try to keep track of whether the syntax has been enabled or disabled and keep track of the old read-table for restoration this function just enables it unconditionally. Once enabled this way there is no corresponding disable function but instead relies on being used in a file context. The spec for load and compile-file states that the *readtable* will be restored after processing the file. Examples Intended to be used at the top of a file that contains sql reader syntax. (in-package :my-package) (clsql:file-enable-sql-reader-syntax) ... ;;functions that use the square bracket syntax. Side Effects Modifies the readtable for #\[ and #\] Affected by None. Exceptional Situations None. See Also enable-sql-reader-syntax disable-sql-reader-syntax locally-enable-sql-reader-syntax locally-disable-sql-reader-syntax Notes Unique to &clsql;, not present in &commonsql;. SQL SQL Construct an SQL string from supplied expressions. Function Syntax sql &rest args => sql-expression Arguments and Values args A set of expressions. sql-expression A string representing an SQL expression. Description Returns an SQL string generated from the expressions args. The expressions are translated into SQL strings and then concatenated with a single space delimiting each expression. Examples (sql nil) => "NULL" (sql 'foo) => "FOO" (sql "bar") => "'bar'" (sql 10) => "10" (sql '(nil foo "bar" 10)) => "(NULL,FOO,'bar',10)" (sql #(nil foo "bar" 10)) => "NULL,FOO,'bar',10" (sql [select [foo] [bar] :from [baz]] 'having [= [foo id] [bar id]] 'and [foo val] '< 5) => "SELECT FOO,BAR FROM BAZ HAVING (FOO.ID = BAR.ID) AND FOO.VAL < 5" Side Effects None. Affected by None. Exceptional Situations An error of type sql-user-error is signalled if any element in args is not of the supported types (a symbol, string, number or symbolic SQL expression) or a list or vector containing only these supported types. See Also sql-expression sql-operation sql-operator Notes None. SQL-EXPRESSION SQL-EXPRESSION Constructs an SQL expression from supplied keyword arguments. Function Syntax sql-expression &key string table alias attribute type => result Arguments and Values string A string. table A symbol representing a database table identifier. alias A table alias. attribute A symbol representing an attribute identifier. type A type specifier. result A object of type sql-expression. Description Returns an SQL expression constructed from the supplied arguments which may be combined as follows: attribute and type; attribute; alias or table and attribute and type; alias or table and attribute; table, attribute and type; table and attribute; table and alias; table; string. Examples (sql-expression :table 'foo :attribute 'bar) => #<CLSQL-SYS:SQL-IDENT-ATTRIBUTE FOO.BAR> (sql-expression :attribute 'baz) => #<CLSQL-SYS:SQL-IDENT-ATTRIBUTE BAZ> Side Effects None. Affected by None. Exceptional Situations An error of type sql-user-error is signalled if an unsupported combination of keyword arguments is specified. See Also sql sql-operation sql-operator Notes None. SQL-OPERATION SQL-OPERATION Constructs an SQL expression from a supplied operator and arguments. Function Syntax sql-operation operator &rest args => result sql-operation 'function func &rest args => result Arguments and Values operator A symbol denoting an SQL operator. func A string denoting an SQL function. args A set of arguments for the specified SQL operator or function. result A object of type sql-expression. Description Returns an SQL expression constructed from the supplied SQL operator or function operator and its arguments args. If operator is passed the symbol 'function then the first value in args is taken to be a valid SQL function and the remaining values in args its arguments. Examples (sql-operation 'select (sql-expression :table 'foo :attribute 'bar) (sql-operation 'sum (sql-expression :table 'foo :attribute 'baz)) :from (sql-expression :table 'foo) :where (sql-operation '> (sql-expression :attribute 'bar) 12) :order-by (sql-operation 'sum (sql-expression :attribute 'baz))) => #<SQL-QUERY SELECT FOO.BAR,SUM(FOO.BAZ) FROM FOO WHERE (BAR > 12) ORDER BY SUM(BAZ)> (sql-operation 'function "strpos" "CLSQL" "SQL") => #<CLSQL-SYS:SQL-FUNCTION-EXP STRPOS('CLSQL','SQL')> Side Effects None. Affected by None. Exceptional Situations An error of type sql-user-error is signalled if operator is not a symbol representing a supported SQL operator. See Also sql sql-expression sql-operator Notes None. SQL-OPERATOR SQL-OPERATOR Returns the symbol for the supplied SQL operator. Function Syntax sql-operator operator => result Arguments and Values operator A symbol denoting an SQL operator. result The Lisp symbol used by &clsql; to represent the specified operator. Description Returns the Lisp symbol corresponding to the SQL operator represented by the symbol operator. If operator does not represent a supported SQL operator or is not a symbol, nil is returned. Examples (sql-operator 'like) => SQL-LIKE Side Effects None. Affected by None. Exceptional Situations None. See Also sql sql-expression sql-operation Notes &clsql;'s symbolic SQL syntax currently has support for the following &commonsql; compatible SQL operators: any some all not union intersect minus except order-by null * + / - like and or in substr || = < > >= <= <> count max min avg sum function between distinct nvl slot-value userenv as well as the pseudo-operator function. The following operators are provided as &clsql; extensions to the &commonsql; API. concat substring limit group-by having not-null exists uplike is == the coalesce view-class Note that some of these operators are not supported by all of the RDBMS supported by &clsql; (see the Appendix for details). cl-sql-6.4.1/doc/fo.xsl0000644000175000017500000000033311251607553013634 0ustar kevinkevin cl-sql-6.4.1/doc/catalog-darwin.xml0000644000175000017500000000263110667176647016140 0ustar kevinkevin cl-sql-6.4.1/doc/ref-clsql-sys.xml0000644000175000017500000000727310667176647015757 0ustar kevinkevin %myents; ]> <symbol>CLSQL-SYS</symbol> This part gives a reference to the symbols exported from the package CLSQL-SYS, which are not exported from CLSQL package.. These symbols are part of the interface for database back-ends, but not part of the normal user-interface of &clsql;. DATABASE-INITIALIZE-DATABASE-TYPE Back-end part of initialize-database-type. Generic Function Syntax database-initialize-database-type database-type => result Arguments and Values database-type A keyword indicating the database type to initialize. result Either t if the initialization succeeds or nil if it fails. Description This generic function implements the main part of the database type initialization performed by initialize-database-type. After initialize-database-type has checked that the given database type has not been initialized before, as indicated by *initialized-database-types*, it will call this function with the database type as it's sole parameter. Database back-ends are required to define a method on this generic function which is specialized via an eql-specializer to the keyword representing their database type. Database back-ends shall indicate successful initialization by returning t from their method, and nil otherwise. Methods for this generic function are allowed to signal errors of type clsql-error or subtypes thereof. They may also signal other types of conditions, if appropriate, but have to document this. Examples Side Effects All necessary side effects to initialize the database instance. Affected By None. Exceptional Situations Conditions of type clsql-error or other conditions may be signalled, depending on the database back-end. See Also initialize-database-type *initialized-database-types* Notes None. cl-sql-6.4.1/doc/appendix.xml0000644000175000017500000007130612021503403015023 0ustar kevinkevin %myents; ]> Database Back-ends How CLSQL finds and loads foreign libraries For some database types CLSQL has to load external foreign libaries. These are usually searched for in the standard locations the operating system uses but you can tell &clsql; to look into other directories as well by using the function CLSQL:PUSH-LIBRARY-PATH or by directly manipulating the special variable CLSQL:*FOREIGN-LIBRARY-SEARCH-PATHS*. If, say, the shared library libpq.so needed for PostgreSQL support is located in the directory /opt/foo/ on your machine you'd use (clsql:push-library-path "/opt/foo/") before loading the CLSQL-POSTGRESQL module. (Note the trailing slash above!) If you want to combine this with fully automatic loading of libraries via ASDF a technique like the following works: (defmethod asdf:perform :after ((o asdf:load-op) (c (eql (asdf:find-system 'clsql)))) (funcall (find-symbol (symbol-name '#:push-library-path) (find-package 'clsql)) #p"/opt/foo/")) Additionally, site-specific initialization can be done using an initialization file. If the file /etc/clsql-init.lisp exists, this file will be read after the &clsql; ASDF system is loaded. This file can contain forms to set site-specific paths as well as change &clsql; default values. PostgreSQL Libraries The PostgreSQL back-end requires the PostgreSQL C client library (libpq.so). The location of this library is specified via *postgresql-so-load-path*, which defaults to /usr/lib/libpq.so. Additional flags to ld needed for linking are specified via *postgresql-so-libraries*, which defaults to ("-lcrypt" "-lc"). Initialization Use (asdf:operate 'asdf:load-op 'clsql-postgresql) to load the PostgreSQL back-end. The database type for the PostgreSQL back-end is :postgresql. Connection Specification Syntax of connection-spec (host db user password &optional port options tty) Description of connection-spec For every parameter in the connection-spec, nil indicates that the PostgreSQL default environment variables (see PostgreSQL documentation) will be used, or if those are unset, the compiled-in defaults of the C client library are used. host String representing the hostname or IP address the PostgreSQL server resides on. Use the empty string to indicate a connection to localhost via Unix-Domain sockets instead of TCP/IP. db String representing the name of the database on the server to connect to. user String representing the user name to use for authentication. password String representing the unencrypted password to use for authentication. port String representing the port to use for communication with the PostgreSQL server. options String representing further runtime options for the PostgreSQL server. tty String representing the tty or file to use for debugging messages from the PostgreSQL server. Notes None. PostgreSQL Socket Libraries The PostgreSQL Socket back-end needs no access to the PostgreSQL C client library, since it communicates directly with the PostgreSQL server using the published frontend/backend protocol, version 2.0. This eases installation and makes it possible to dump CMU CL images containing CLSQL and this backend, contrary to backends which require FFI code. Initialization Use (asdf:operate 'asdf:load-op 'clsql-postgresql-socket) to load the PostgreSQL Socket back-end. The database type for the PostgreSQL Socket back-end is :postgresql-socket. Connection Specification Syntax of connection-spec (host db user password &optional port options tty) Description of connection-spec host If this is a string, it represents the hostname or IP address the PostgreSQL server resides on. In this case communication with the server proceeds via a TCP connection to the given host and port. If this is a pathname, then it is assumed to name the directory that contains the server's Unix-Domain sockets. The full name to the socket is then constructed from this and the port number passed, and communication will proceed via a connection to this unix-domain socket. db String representing the name of the database on the server to connect to. user String representing the user name to use for authentication. password String representing the unencrypted password to use for authentication. This can be the empty string if no password is required for authentication. port Integer representing the port to use for communication with the PostgreSQL server. This defaults to 5432. options String representing further runtime options for the PostgreSQL server. tty String representing the tty or file to use for debugging messages from the PostgreSQL server. Notes None. MySQL Libraries The &mysql; back-end requires the &mysql; C client library (libmysqlclient.so). The location of this library is specified via *mysql-so-load-path*, which defaults to /usr/lib/libmysqlclient.so. Additional flags to ld needed for linking are specified via *mysql-so-libraries*, which defaults to ("-lc"). Initialization Use (asdf:operate 'asdf:load-op 'clsql-mysql) to load the &mysql; back-end. The database type for the MySQL back-end is :mysql. Connection Specification Syntax of connection-spec (host db user password &optional port) Description of connection-spec host String representing the hostname or IP address the &mysql; server resides on, or nil to indicate the localhost. db String representing the name of the database on the server to connect to. user String representing the user name to use for authentication, or nil to use the current Unix user ID. password String representing the unencrypted password to use for authentication, or nil if the authentication record has an empty password field. port String representing the port to use for communication with the MySQL server. Notes FDDL drop-index requires a table to be specified with the :on keyword parameter. views are not supported by &mysql;. The :transactions keyword argument to create-table controls whether or not the created table is an InnoDB table which supports transactions. The :owner keyword argument to the FDDL functions for listing and testing for database objects is ignored. FDML Prior to version 4.1, &mysql; does not support nested subqueries in calls to select. Symbolic SQL Syntax &mysql; does not support the || concatenation operator. Use concat instead. &mysql; does not support the substr operator. Use substring instead. &mysql; does not support the intersect and except set operations. &mysql; (version 4.0 and later) does not support string table aliases unless the server is started with ANSI_QUOTES enabled. &odbc; Libraries The &odbc; back-end requires access to an &odbc; driver manager as well as &odbc; drivers for the underlying database server. &clsql; has been tested with unixODBC ODBC Driver Manager as well as Microsoft's ODBC manager. These driver managers have been tested with the psqlODBC driver for &postgresql; and the MyODBC driver for &mysql;. Initialization Use (asdf:operate 'asdf:load-op 'clsql-odbc) to load the &odbc; back-end. The database type for the &odbc; back-end is :odbc. Connection Specification Syntax of connection-spec (dsn user password &key connection-string) Description of connection-spec dsn String representing the ODBC data source name. user String representing the user name to use for authentication. password String representing the unencrypted password to use for authentication. connection-string Raw connection string passed to the underlying ODBC driver. Allows bypassing creating a DSN on the server. Notes FDDL The :owner keyword argument to the FDDL functions for listing and testing for database objects is ignored. Connect Examples ;; assumes a "mssql" DSN is configured on the lisp host, specifying database server ;; and database name. > (clsql:connect '("mssql" "database-user" "database-password") :database-type :odbc) => #<CLSQL-ODBC:ODBC-DATABASE mssql/database-user OPEN {100756D123}> ;; no DSN on the lisp host, specify connection information via :connection-string > (clsql:connect '("friendly-server-name" "friendly-username" "" :connection-string "DRIVER={FreeTDS};SERVER=mssql-server;DATABASE=database-name;UID=database-user;PWD=database-password;PORT=1433;TDS_Version=8.0;APP=clsql") :database-type :odbc) => #<CLSQL-ODBC:ODBC-DATABASE friendly-server-name/friendly-username OPEN {100756D123}> The friendly-server-name and friendly-username are only used when printing the connection object to a stream. &aodbc; Libraries The &aodbc; back-end requires access to the &odbc; interface of &acl; named DBI. This interface is not available in the trial version of &acl; Initialization Use (require 'aodbc-v2) (asdf:operate 'asdf:load-op 'clsql-aodbc) to load the &aodbc; back-end. The database type for the &aodbc; back-end is :aodbc. Connection Specification Syntax of connection-spec (dsn user password) Description of connection-spec dsn String representing the ODBC data source name. user String representing the user name to use for authentication. password String representing the unencrypted password to use for authentication. Notes None. &sqlite; Libraries The &sqlite; back-end requires the &sqlite; shared library file. Its default file name is /usr/lib/libsqlite.so. Initialization Use (asdf:operate 'asdf:load-op 'clsql-sqlite) to load the &sqlite; back-end. The database type for the &sqlite; back-end is :sqlite. Connection Specification Syntax of connection-spec (filename) Description of connection-spec filename String or pathname representing the filename of the &sqlite; database file. Notes Connection Passing filename a value of :memory: will create a database in physical memory instead of using a file on disk. Some operations will be many times faster if database integrity checking is disabled by setting the SYNCHRONOUS flag to OFF (see the SQLITE manual for details). FDDL The :owner keyword argument to the FDDL functions for listing and testing for database objects is ignored. The :column-list keyword argument to create-view is not supported by &sqlite;. Symbolic SQL Syntax &sqlite; does not support the all, some, any and exists subquery operations. &sqlite3; Libraries The &sqlite3; back-end requires the &sqlite3; shared library file. Its default file name is /usr/lib/libsqlite3.so. Initialization Use (asdf:operate 'asdf:load-op 'clsql-sqlite3) to load the &sqlite3; back-end. The database type for the &sqlite3; back-end is :sqlite3. Connection Specification Syntax of connection-spec (filename &optional init-function) Description of connection-spec filename String representing the filename of the &sqlite3; database file. init-function A function designator. init-function takes a single argument of type sqlite3:sqlite3-db, a foreign pointer to the C descriptor of the newly opened database. init-function is called by the back-end immediately after &sqlite3; sqlite3_open library function, and can be used to perform optional database initializations by calling foreign functions in the &sqlite3; library. An example of an initialization function which defines a new collating sequence for text columns is provided in ./examples/sqlite3/init-func/. Notes Connection Passing filename a value of :memory: will create a database in physical memory instead of using a file on disk. Some operations will be many times faster if database integrity checking is disabled by setting the SYNCHRONOUS flag to OFF (see the SQLITE manual for details). FDDL The :owner keyword argument to the FDDL functions for listing and testing for database objects is ignored. The :column-list keyword argument to create-view is not supported by &sqlite3;. Symbolic SQL Syntax &sqlite3; does not support the all, some, any and exists subquery operations. Oracle Libraries The &oracle; back-end requires the &oracle; OCI client library. (libclntsh.so). The location of this library is specified relative to the ORACLE_HOME value in the operating system environment. Library Versions &clsql; has tested sucessfully using the client library from Oracle 9i and Oracle 10g server installations as well as Oracle's 10g Instant Client library. For Oracle 8 and earlier versions, there is vestigial support by pushing the symbol :oci7 onto cl:*features* prior to loading the clsql-oracle &asdf; system. (push :oci7 cl:*features*) (asdf:operate 'asdf:load-op 'clsql-oracle) Initialization Use (asdf:operate 'asdf:load-op 'clsql-oracle) to load the &oracle; back-end. The database type for the Oracle back-end is :oracle. Connection Specification Syntax of connection-spec (global-name user password) Description of connection-spec global-name String representing the global name of the Oracle database. This is looked up through the tnsnames.ora file. user String representing the user name to use for authentication. password String representing the password to use for authentication.. Notes Symbolic SQL Syntax The userenv operator is &oracle; specific. &oracle; does not support the except operator. Use minus instead. &oracle; does not support the all, some, any subquery operations. Transactions By default, &clsql; starts in transaction AUTOCOMMIT mode (see set-autocommit). To begin a transaction in autocommit mode, start-transaction has to be called explicitly. cl-sql-6.4.1/doc/glossary.xml0000644000175000017500000001315510667176647015112 0ustar kevinkevin %myents; ]> This glossary is still very thinly populated, and not all references in the main text have been properly linked and coordinated with this glossary. This will hopefully change in future revisions. Attribute A property of objects stored in a database table. Attributes are represented as columns (or fields) in a table. Active database Connection Column Data Definition Language (DDL) The subset of SQL used for defining and examining the structure of a database. Data Manipulation Language (DML) The subset of SQL used for inserting, deleting, updating and fetching data in a database. database Database Object An object of type database. Field Field Types Specifier A value that specifies the type of each field in a query. Foreign Function Interface (FFI) An interface from Common Lisp to a external library which contains compiled functions written in other programming languages, typically C. Query An SQL statement which returns a set of results. RDBMS A Relational DataBase Management System (RDBMS) is a software package for managing a database in which the data is defined, organised and accessed as rows and columns of a table. Record A sequence of attribute values stored in a database table. Row Structured Query Language (SQL) An ANSI standard language for storing and retrieving data in a relational database. SQL Expression Either a string containing a valid SQL statement, or an object of type sql-expression. Table A collection of data which is defined, stored and accessed as tuples of attribute values (i.e., rows and columns). Transaction An atomic unit of one or more SQL statements of which all or none are successfully executed. Tuple View A table display whose structure and content are derived from an existing table via a query. View Class The class standard-db-object or one of its subclasses. cl-sql-6.4.1/doc/Makefile0000644000175000017500000000665111345753563014160 0ustar kevinkevin#!/usr/bin/make ############################################################################### # FILE IDENTIFICATION # # Name: Makefile # Purpose: Makefile for the clsql documentation # Programer: Kevin M. Rosenberg # Date Started: Mar 2002 # # This file, part of CLSQL, is Copyright (c) 2002-2010 by Kevin M. Rosenberg # # CLSQL users are granted the rights to distribute and use this software # as governed by the terms of the Lisp Lesser GNU Public License # (http://opensource.franz.com/preamble.html), also known as the LLGPL. ############################################################################### DOCFILE_BASE_DEFAULT:=clsql DOCFILE_EXT_DEFAULT:=xml # Standard docfile processing DEBIAN=$(shell expr "`cat /etc/issue 2> /dev/null`" : '.*Debian.*') SUSE=$(shell expr "`cat /etc/issue 2> /dev/null`" : '.*SuSE.*') SUSE91=$(shell expr "`cat /etc/issue 2> /dev/null`" : '.*SuSE Linux 9.1.*') REDHAT=$(shell expr "`cat /etc/issue 2> /dev/null`" : '.*Red Hat.*') MANDRAKE=$(shell expr "`cat /etc/issue 2> /dev/null`" : '.*Mandrake.*') DARWIN=$(shell expr "`uname -a`" : '.*Darwin.*') UBUNTU=$(shell expr "`cat /etc/issue 2> /dev/null`" : '.*Ubuntu.*') ifneq (${DEBIAN},0) OS:=debian else ifneq (${SUSE91},0) OS=suse91 else ifneq (${SUSE},0) OS=suse else ifneq (${REDHAT},0) OS=redhat else ifneq (${MANDRAKE},0) OS=mandrake else ifneq (${DARWIN},0) OS=darwin else ifneq (${UBUNTU},0) OS:=debian endif endif endif endif endif endif endif ifndef DOCFILE_BASE DOCFILE_BASE=${DOCFILE_BASE_DEFAULT} endif ifndef DOCFILE_EXT DOCFILE_EXT=${DOCFILE_EXT_DEFAULT} endif DOCFILE:=${DOCFILE_BASE}.${DOCFILE_EXT} FOFILE:=${DOCFILE_BASE}.fo PDFFILE:=${DOCFILE_BASE}.pdf PSFILE:=${DOCFILE_BASE}.ps DVIFILE:=${DOCFILE_BASE}.dvi TXTFILE:=${DOCFILE_BASE}.txt HTMLFILE:=${DOCFILE_BASE}.html TMPFILES:=${DOCFILE_BASE}.aux ${DOCFILE_BASE}.out ${DOCFILE_BASE}.log DOCFILES:=$(shell echo *.xml *.xsl) ifeq ($(XSLTPROC),) XSLTPROC:=xsltproc endif CATALOG:=`pwd`/catalog-${OS}.xml CHECK:=XML_CATALOG_FILES="$(CATALOG)" xmllint --noout --xinclude --postvalid $(DOCFILE) || exit 1 .PHONY: all all: html pdf .PHONY: dist dist: html pdf .PHONY: doc doc: html pdf .PHONY: check check: @echo "Operating system detected: ${OS}" @$(CHECK) .PHONY: html html: html.tar.gz html.tar.gz: $(DOCFILES) Makefile @rm -rf html @mkdir html @XML_CATALOG_FILES="$(CATALOG)" $(XSLTPROC) --stringparam chunker.output.encoding UTF-8 \ --xinclude --output html/ html_chunk.xsl $(DOCFILE) @GZIP='-9' tar czf html.tar.gz html .PHONY: fo fo: ${FOFILE} ${FOFILE}: $(DOCFILES) Makefile @XML_CATALOG_FILES="$(CATALOG)" xsltproc --xinclude --stringparam fop1.extensions 1 --output $(FOFILE) fo.xsl $(DOCFILE) .PHONY: pdf pdf: ${PDFFILE} ${PDFFILE}: ${DOCFILES} Makefile @$(MAKE) fo @fop $(FOFILE) -pdf $(PDFFILE) > /dev/null .PHONY: dvi dvi: ${DVIFILE} .PHONY: ps ps: ${PSFILE} ${PSFILE}: ${DOCFILES} Makefile @$(MAKE) fo @fop $(FOFILE) -ps $(PSFILE) > /dev/null .PHONY: txt txt: ${TXTFILE} ${TXTFILE}: ${FOFILE} @XML_CATALOG_FILES="$(CATALOG)" xsltproc --xinclude --output ${HTMLFILE} html.xsl $(DOCFILE) lynx -dump ${HTMLFILE} > ${TXTFILE} .PHONY: clean clean: @rm -f *~ *.bak *.orig \#*\# .\#* texput.log @rm -rf html ${PSFILE} ${HTMLFILE} @rm -f ${TMPFILES} ${FOFILE} @rm -f ${DVIFILE} ${TXTFILE} .PHONY: distclean distclean: clean cl-sql-6.4.1/doc/catalog-suse91.xml0000644000175000017500000000326610667176647016012 0ustar kevinkevin cl-sql-6.4.1/doc/ref-fddl.xml0000644000175000017500000025103010667176647014726 0ustar kevinkevin %myents; ]> Functional Data Definition Language (FDDL) &clsql; provides a functional DDL which supports the creation and destruction of a variety of database objects including tables, views, indexes and sequences. Functions which return information about currently defined database objects are also provided. In addition, the FDDL includes functionality for examining table attributes and attribute types. CREATE-TABLE CREATE-TABLE Create a database table. Function Syntax create-table name description &key database constraints transactions => Arguments and Values name The name of the table as a string, symbol or SQL expression. database A database object which defaults to *default-database*. description A list. constraints A string, a list of strings or &nil;. transactions A Boolean. The default value is &t;. Description Creates a table called name, which may be a string, symbol or SQL table identifier, in database which defaults to *default-database*. description is a list whose elements are lists containing the attribute names, types, and other constraints such as not-null or primary-key for each column in the table. constraints is a string representing an SQL table constraint expression or a list of such strings. With MySQL databases, if transactions is &t; an InnoDB table is created which supports transactions. Examples (create-table [foo] '(([id] integer) ([height] float) ([name] (string 24)) ([comments] longchar))) => (table-exists-p [foo]) => T (create-table [foo] '(([bar] integer :not-null :unique :primary-key) ([baz] string :not-null :unique))) => (table-exists-p [foo]) => T (create-table [foo] '(([bar] integer :not-null) ([baz] string :not-null)) :constraints '("UNIQUE (bar,baz)" "PRIMARY KEY (bar)")) => (table-exists-p [foo]) => T Side Effects A table is created in database. Affected by *default-database* Exceptional Situations An error is signalled if name is not a string, symbol or SQL expression. An error of type sql-database-data-error is signalled if a relation called name already exists. See Also drop-table list-tables table-exists-p Notes The constraints and transactions keyword arguments to create-table are &clsql; extensions. The transactions keyword argument is for compatibility with MySQL databases. DROP-TABLE DROP-TABLE Drop a database table. Function Syntax drop-table name &key if-does-not-exist database => Arguments and Values name The name of the table as a string, symbol or SQL expression. database A database object which defaults to *default-database*. if-does-not-exist A symbol. Meaningful values are :ignore or :error (the default). Description Drops the table called name from database which defaults to *default-database*. If the table does not exist and if-does-not-exist is :ignore then drop-table returns &nil; whereas an error is signalled if if-does-not-exist is :error. Examples (table-exists-p [foo]) => T (drop-table [foo] :if-does-not-exist :ignore) => (table-exists-p [foo]) => NIL Side Effects A table is dropped database. Affected by *default-database* Exceptional Situations An error is signalled if name is not a string, symbol or SQL expression. An error of type sql-database-data-error is signalled if name doesn't exist and if-does-not-exist has a value of :error. See Also create-table list-tables table-exists-p Notes The if-does-not-exist keyword argument to drop-table is a &clsql; extension. LIST-TABLES LIST-TABLES Returns a list of database tables. Function Syntax list-tables &key owner database => result Arguments and Values owner A string, &nil; or :all. database A database object which defaults to *default-database*. result A list of strings. Description Returns a list of strings representing table names in database which defaults to *default-database*. owner is &nil; by default which means that only tables owned by users are listed. If owner is a string denoting a user name, only tables owned by owner are listed. If owner is :all then all tables are listed. Examples (list-tables :owner "fred") => ("type_table" "type_bigint" "employee" "company" "addr" "ea_join" "big") (list-tables :owner :all) => ("pg_description" "pg_group" "pg_proc" "pg_rewrite" "pg_type" "pg_attribute" "pg_class" "pg_inherits" "pg_index" "pg_operator" "pg_opclass" "pg_am" "pg_amop" "pg_amproc" "pg_language" "pg_largeobject" "pg_aggregate" "pg_trigger" "pg_listener" "pg_cast" "pg_namespace" "pg_shadow" "pg_conversion" "pg_depend" "pg_attrdef" "pg_constraint" "pg_database" "type_table" "type_bigint" "employee" "company" "pg_statistic" "addr" "ea_join" "big") Side Effects None. Affected by *default-database* Exceptional Situations None. See Also create-table drop-table table-exists-p Notes None. TABLE-EXISTS-P TABLE-EXISTS-P Tests for the existence of a database table. Function Syntax table-exists-p name &key owner database => result Arguments and Values name The name of the table as a string, symbol or SQL expression. owner A string, &nil; or :all. database A database object which defaults to *default-database*. result A Boolean. Description Tests for the existence of an SQL table called name in database which defaults to *default-database*. owner is &nil; by default which means that only tables owned by users are examined. If owner is a string denoting a user name, only tables owned by owner are examined. If owner is :all then all tables are examined. Examples (table-exists-p [foo]) => T Side Effects None. Affected by *default-database* Exceptional Situations None. See Also create-table drop-table list-tables Notes None. CREATE-VIEW CREATE-VIEW Create a database view. Function Syntax create-view name &key as column-list with-check-option database => Arguments and Values name The name of the view as a string, symbol or SQL expression. database A database object which defaults to *default-database*. as A symbolic SQL query expression. column-list A list. with-check-option A Boolean. Description Creates a view called name in database which defaults to *default-database*. The view is created using the query as and the columns of the view may be specified using the column-list parameter. The with-check-option is &nil; by default but if it has a non-&nil; value, then all insert/update commands on the view are checked to ensure that the new data satisfy the query as. Examples (create-view [lenins-group] :as [select [first-name] [last-name] [email] :from [employee] :where [= [managerid] 1]]) => (select [*] :from [lenins-group]) => (("Josef" "Stalin" "stalin@soviet.org") ("Leon" "Trotsky" "trotsky@soviet.org") ("Nikita" "Kruschev" "kruschev@soviet.org") ("Leonid" "Brezhnev" "brezhnev@soviet.org") ("Yuri" "Andropov" "andropov@soviet.org") ("Konstantin" "Chernenko" "chernenko@soviet.org") ("Mikhail" "Gorbachev" "gorbachev@soviet.org") ("Boris" "Yeltsin" "yeltsin@soviet.org") ("Vladimir" "Putin" "putin@soviet.org")), ("first_name" "last_name" "email") Side Effects A view is created in database. Affected by *default-database* Exceptional Situations An error is signalled if name is not a string, symbol or SQL expression. An error of type sql-database-data-error is signalled if a relation called name already exists. See Also drop-view list-views view-exists-p Notes None. DROP-VIEW DROP-VIEW Drops a database view. Function Syntax drop-view name &key if-does-not-exist database => Arguments and Values name The name of the view as a string, symbol or SQL expression. database A database object which defaults to *default-database*. if-does-not-exist A symbol. Meaningful values are :ignore or :error (the default). Description Drops the view called name from database which defaults to *default-database*. If the view does not exist and if-does-not-exist is :ignore then drop-view returns &nil; whereas an error is signalled if if-does-not-exist is :error. Examples (view-exists-p [foo]) => T (drop-view [foo] :if-does-not-exist :ignore) => (view-exists-p [foo]) => NIL Side Effects A view is dropped database. Affected by *default-database* Exceptional Situations An error is signalled if name is not a string, symbol or SQL expression. An error of type sql-database-data-error is signalled if name doesn't exist and if-does-not-exist has a value of :error. See Also create-view list-views view-exists-p Notes The if-does-not-exist keyword argument to drop-view is a &clsql; extension. LIST-VIEWS LIST-VIEWS Returns a list of database views. Function Syntax list-views &key owner database => result Arguments and Values owner A string, &nil; or :all. database A database object which defaults to *default-database*. result A list of strings. Description Returns a list of strings representing view names in database which defaults to *default-database*. owner is &nil; by default which means that only views owned by users are listed. If owner is a string denoting a user name, only views owned by owner are listed. If owner is :all then all views are listed. Examples (list-views :owner "fred") => ("lenins_group") (list-views :owner :all) => ("pg_user" "pg_rules" "pg_views" "pg_tables" "pg_indexes" "pg_stats" "pg_stat_all_tables" "pg_stat_sys_tables" "pg_stat_user_tables" "pg_statio_all_tables" "pg_statio_sys_tables" "pg_statio_user_tables" "pg_stat_all_indexes" "pg_stat_sys_indexes" "pg_stat_user_indexes" "pg_statio_all_indexes" "pg_statio_sys_indexes" "pg_statio_user_indexes" "pg_statio_all_sequences" "pg_statio_sys_sequences" "pg_statio_user_sequences" "pg_stat_activity" "pg_stat_database" "pg_locks" "pg_settings" "lenins_group") Side Effects None. Affected by *default-database* Exceptional Situations None. See Also create-view drop-view view-exists-p Notes list-views is a &clsql; extension. VIEW-EXISTS-P VIEW-EXISTS-P Tests for the existence of a database view. Function Syntax view-exists-p name &key owner database => result Arguments and Values name The name of the view as a string, symbol or SQL expression. owner A string, &nil; or :all. database A database object which defaults to *default-database*. result A Boolean. Description Tests for the existence of an SQL view called name in database which defaults to *default-database*. owner is &nil; by default which means that only views owned by users are examined. If owner is a string denoting a user name, only views owned by owner are examined. If owner is :all then all views are examined. Examples (view-exists-p [lenins-group]) => T Side Effects None. Affected by *default-database* Exceptional Situations None. See Also create-view drop-view list-views Notes view-exists-p is a &clsql; extension. CREATE-INDEX CREATE-INDEX Create a database index. Function Syntax create-index name &key on unique attributes database => Arguments and Values name The name of the index as a string, symbol or SQL expression. on The name of a table as a string, symbol or SQL expression. unique A Boolean. attributes A list of attribute names. database A database object which defaults to *default-database*. Description Creates an index called name on the table specified by on in database which default to *default-database*. The table attributes to use in constructing the index name are specified by attributes. The unique argument is &nil; by default but if it has a non-&nil; value then the indexed attributes must have unique values. Examples (create-index [bar] :on [employee] :attributes '([first-name] [last-name] [email]) :unique t) => (index-exists-p [bar]) => T Side Effects An index is created in database. Affected by *default-database* Exceptional Situations An error is signalled if name is not a string, symbol or SQL expression. An error of type sql-database-data-error is signalled if a relation called name already exists. See Also drop-index list-indexes index-exists-p Notes None. DROP-INDEX DROP-INDEX Drop a database index. Function Syntax drop-index name &key if-does-not-exist on database => Arguments and Values name The name of the index as a string, symbol or SQL expression. on The name of a table as a string, symbol or SQL expression. database A database object which defaults to *default-database*. if-does-not-exist A symbol. Meaningful values are :ignore or :error (the default). Description Drops the index called name in database which defaults to *default-database*. If the index does not exist and if-does-not-exist is :ignore then drop-index returns &nil; whereas an error is signalled if if-does-not-exist is :error. The argument on allows the optional specification of a table to drop the index from. This is required for compatability with MySQL. Examples (index-exists-p [foo]) => T (drop-index [foo] :if-does-not-exist :ignore) => (index-exists-p [foo]) => NIL Side Effects An index is dropped in database. Affected by *default-database* Exceptional Situations An error is signalled if name is not a string, symbol or SQL expression. An error of type sql-database-data-error is signalled if name doesn't exist and if-does-not-exist has a value of :error. See Also create-index list-indexes index-exists-p Notes The if-does-not-exist and on keyword arguments to drop-index are &clsql; extensions. The keyword argument on is provided for compatibility with MySQL. LIST-INDEXES LIST-INDEXES Returns a list of database indexes. Function Syntax list-indexes &key onowner database => result Arguments and Values owner A string, &nil; or :all. database A database object which defaults to *default-database*. on The name of a table as a string, symbol or SQL expression, a list of such names or &nil;. result A list of strings. Description Returns a list of strings representing index names in database which defaults to *default-database*. owner is &nil; by default which means that only indexes owned by users are listed. If owner is a string denoting a user name, only indexes owned by owner are listed. If owner is :all then all indexes are listed. The keyword argument on limits the results to indexes on the specified tables. Meaningful values for on are &nil; (the default) which means that all tables are considered, a string, symbol or SQL expression representing a table name in database or a list of such table identifiers. Examples (list-indexes) => ("employeepk" "companypk" "addrpk" "bar") (list-indexes :on '([addr] [company])) => ("addrpk" "companypk") Side Effects None. Affected by *default-database* Exceptional Situations None. See Also create-index drop-index index-exists-p Notes list-indexes is a &clsql; extension. INDEX-EXISTS-P INDEX-EXISTS- Tests for the existence of a database index. Function Syntax index-exists-p name &key owner database => result Arguments and Values name The name of the index as a string, symbol or SQL expression. owner A string, &nil; or :all. database A database object which defaults to *default-database*. result A Boolean. Description Tests for the existence of an SQL index called name in database which defaults to *default-database*. owner is &nil; by default which means that only indexes owned by users are examined. If owner is a string denoting a user name, only indexes owned by owner are examined. If owner is :all then all indexes are examined. Examples (index-exists-p [bar]) => T Side Effects None. Affected by *default-database* Exceptional Situations None. See Also create-index drop-index list-indexes Notes index-exists-p is a &clsql; extension. ATTRIBUTE-TYPE ATTRIBUTE-TYPE Returns the type of the supplied attribute. Function Syntax attribute-type attribute table &key owner database => type, precision, scale, nulls-accepted Arguments and Values attribute The name of the index as a string, symbol or SQL expression. table The name of a table as a string, symbol or SQL expression. owner A string, &nil; or :all. database A database object which defaults to *default-database*. type A keyword symbol denoting a vendor-specific SQL type. precision An integer denoting the precision of the attribute type or &nil;. scale An integer denoting the scale of the attribute type or &nil;. nulls-accepted 0 or 1. Description Returns a keyword symbol representing the vendor-specific field type of the supplied attribute attribute in the table specified by table in database which defaults to *default-database*. owner is &nil; by default which means that the attribute specified by attribute, if it exists, must be user owned else &nil; is returned. If owner is a string denoting a user name, the attribute, if it exists, must be owned by owner else &nil; is returned, whereas if owner is :all then the attribute, if it exists, will be returned regardless of its owner. Other information is also returned. The second value is the type precision, the third is the scale and the fourth represents whether or not the attribute accepts null values (a value of 0) or not (a value of 1). Examples (attribute-type [emplid] [employee]) => :INT4, 4, NIL, 0 Side Effects None. Affected by *default-database* Exceptional Situations None. See Also list-attributes list-attribute-types Notes None. LIST-ATTRIBUTE-TYPES LIST-ATTRIBUTE-TYPES Returns information about the attribute types of a table. Function Syntax list-attribute-types table &key owner database => result Arguments and Values table The name of a table as a string, symbol or SQL expression. owner A string, &nil; or :all. database A database object which defaults to *default-database*. result A list. Description Returns a list containing information about the SQL types of each of the attributes in the table specified by table in database which has a default value of *default-database*. owner is &nil; by default which means that only attributes owned by users are listed. If owner is a string denoting a user name, only attributes owned by owner are listed. If owner is :all then all attributes are listed. The elements of the returned list are lists where the first element is the name of the attribute, the second element is its SQL type, the third is the type precision, the fourth is the scale of the attribute and the fifth is 1 if the attribute accepts null values and otherwise 0. Examples (list-attribute-types [employee]) => (("emplid" :INT4 4 NIL 0) ("groupid" :INT4 4 NIL 0) ("first_name" :VARCHAR 30 NIL 1) ("last_name" :VARCHAR 30 NIL 1) ("email" :VARCHAR 100 NIL 1) ("ecompanyid" :INT4 4 NIL 1) ("managerid" :INT4 4 NIL 1) ("height" :FLOAT8 8 NIL 1) ("married" :BOOL 1 NIL 1) ("birthday" :TIMESTAMP 8 NIL 1) ("bd_utime" :INT8 8 NIL 1)) Side Effects None. Affected by *default-database* Exceptional Situations None. See Also attribute-type list-attribute-types Notes None. LIST-ATTRIBUTES LIST-ATTRIBUTES Returns the attributes of a table as a list. Function Syntax list-attributes name &key owner database => result Arguments and Values name The name of a table as a string, symbol or SQL expression. owner A string, &nil; or :all. database A database object which defaults to *default-database*. result A list. Description Returns a list of strings representing the attributes of table name in database which defaults to *default-database*. owner is &nil; by default which means that only attributes owned by users are listed. If owner is a string denoting a user name, only attributes owned by owner are listed. If owner is :all then all attributes are listed. Examples (list-attributes [employee]) => ("emplid" "groupid" "first_name" "last_name" "email" "ecompanyid" "managerid" "height" "married" "birthday" "bd_utime") Side Effects None. Affected by *default-database* Exceptional Situations None. See Also attribute-type list-attribute-types Notes None. CREATE-SEQUENCE CREATE-SEQUENCE Create a database sequence. Function Syntax create-sequence name &key database => Arguments and Values name The name of the sequence as a string, symbol or SQL expression. database A database object which defaults to *default-database*. Description Creates a sequence called name in database which defaults to *default-database*. Examples (create-sequence [foo]) => (sequence-exists-p [foo]) => T Side Effects A sequence is created in database. Affected by *default-database* Exceptional Situations An error is signalled if name is not a string, symbol or SQL expression. An error of type sql-database-data-error is signalled if a relation called name already exists. See Also drop-sequence list-sequences sequence-exists-p sequence-last sequence-next set-sequence-position Notes create-sequence is a &clsql; extension. DROP-SEQUENCE DROP-SEQUENCE Drop a database sequence. Function Syntax drop-sequence name &key if-does-not-exist database => Arguments and Values name The name of the sequence as a string, symbol or SQL expression. database A database object which defaults to *default-database*. if-does-not-exist A symbol. Meaningful values are :ignore or :error (the default). Description Drops the sequence called name from database which defaults to *default-database*. If the sequence does not exist and if-does-not-exist is :ignore then drop-sequence returns &nil; whereas an error is signalled if if-does-not-exist is :error. Examples (sequence-exists-p [foo]) => T (drop-sequence [foo] :if-does-not-exist :ignore) => (sequence-exists-p [foo]) => NIL Side Effects A sequence is dropped from database. Affected by *default-database* Exceptional Situations An error is signalled if name is not a string, symbol or SQL expression. An error of type sql-database-data-error is signalled if name doesn't exist and if-does-not-exist has a value of :error. See Also create-sequence list-sequences sequence-exists-p sequence-last sequence-next set-sequence-position Notes drop-sequence is a &clsql; extension. LIST-SEQUENCES LIST-SEQUENCES Returns a list of database sequences. Function Syntax list-sequences &key owner database => result Arguments and Values owner A string, &nil; or :all. database A database object which defaults to *default-database*. result A list of strings. Description Returns a list of strings representing sequence names in database which defaults to *default-database*. owner is &nil; by default which means that only sequences owned by users are listed. If owner is a string denoting a user name, only sequences owned by owner are listed. If owner is :all then all sequences are listed. Examples (list-sequences) => ("foo") Side Effects None. Affected by *default-database* Exceptional Situations None. See Also create-sequence drop-sequence sequence-exists-p sequence-last sequence-next set-sequence-position Notes list-sequences is a &clsql; extension. SEQUENCE-EXISTS-P SEQUENCE-EXISTS-P Tests for the existence of a database sequence. Function Syntax sequence-exists-p name &key owner database => result Arguments and Values name The name of the sequence as a string, symbol or SQL expression. owner A string, &nil; or :all. database A database object which defaults to *default-database*. result A Boolean. Description Tests for the existence of an SQL sequence called name in database which defaults to *default-database*. owner is &nil; by default which means that only sequences owned by users are examined. If owner is a string denoting a user name, only sequences owned by owner are examined. If owner is :all then all sequences are examined. Examples (sequence-exists-p [foo]) => NIL Side Effects None. Affected by *default-database* Exceptional Situations None. See Also create-sequence drop-sequence list-sequences sequence-last sequence-next set-sequence-position Notes sequence-exists-p is a &clsql; extension. SEQUENCE-LAST SEQUENCE-LAST Return the last element in a database sequence. Function Syntax sequence-last name &key database => result Arguments and Values name The name of the sequence as a string, symbol or SQL expression. database A database object which defaults to *default-database*. result An integer. Description Return the last value allocated in the sequence called name in database which defaults to *default-database*. Examples (sequence-last [foo]) => 1 Side Effects None. Affected by The current value stored in database sequence name. *default-database* Exceptional Situations Will signal an error of type sql-database-data-error if a sequence called name does not exist in database. See Also create-sequence drop-sequence list-sequences sequence-exists-p sequence-next set-sequence-position Notes sequence-last is a &clsql; extension. SEQUENCE-NEXT SEQUENCE-NEXT Increment the value of a database sequence. Function Syntax sequence-next name &key database => result Arguments and Values name The name of the sequence as a string, symbol or SQL expression. database A database object which defaults to *default-database*. result An integer. Description Increment and return the value of the sequence called name in database which defaults to *default-database*. Examples (sequence-last [foo]) => 3 (sequence-next [foo]) => 4 (sequence-next [foo]) => 5 (sequence-next [foo]) => 6 Side Effects Modifies the value of the sequence name in database. Affected by The current value stored in database sequence name. *default-database* Exceptional Situations Will signal an error of type sql-database-data-error if a sequence called name does not exist in database. See Also create-sequence drop-sequence list-sequences sequence-exists-p sequence-last set-sequence-position Notes sequence-next is a &clsql; extension. SET-SEQUENCE-POSITION SET-SEQUENCE-POSITION Sets the position of a database sequence. Function Syntax set-sequence-position name position &key database => result Arguments and Values name The name of the sequence as a string, symbol or SQL expression. position An integer. database A database object which defaults to *default-database*. result An integer. Description Explicitly set the position of the sequence called name in database, which defaults to *default-database*, to position which is returned. Examples (sequence-last [foo]) => 4 (set-sequence-position [foo] 50) => 50 (sequence-next [foo]) => 51 Side Effects Modifies the value of the sequence name in database. Affected by *default-database* Exceptional Situations Will signal an error of type sql-database-data-error if a sequence called name does not exist in database. See Also create-sequence drop-sequence list-sequences sequence-exists-p sequence-last sequence-next Notes set-sequence-position is a &clsql; extension. TRUNCATE-DATABASE TRUNCATE-DATABASE Drop all tables, views, indexes and sequences in a database. Function Syntax truncate-database &key database => Arguments and Values database A database object. This will default to the value of *default-database*. Description Drop all tables, views, indexes and sequences in database which defaults to *default-database*. Examples (list-tables) => ("type_table" "type_bigint" "employee" "company" "addr" "ea_join" "big") (list-indexes) => ("employeepk" "companypk" "addrpk") (list-views) => ("lenins_group") (list-sequences) => ("foo" "bar") (truncate-database) => (list-tables) => NIL (list-indexes) => NIL (list-views) => NIL (list-sequences) => NIL Side Effects Modifications are made to the underlying database. Affected by None. Exceptional Situations Signals an error of type sql-database-error if database is not a database object. See Also drop-table drop-view drop-index drop-sequence Notes truncate-database is a &clsql; extension. cl-sql-6.4.1/doc/TODO0000644000175000017500000000147211746263021013172 0ustar kevinkevinDOCUMENTATION TO DO LIST 1. Variances from CommonSQL (Ideally, this will be extremely minimal) 2. Underdocumented CommonSQL features: - Retrieval immediate - SQL operators: ||, SUBSTR, MINUS, INTERSECT, UNION, NVL 3. CLSQL extensions to CommonSQL - SQL operators: group-by, limit, not-null, ==, is, having, the, uplike, view-class, coalesce, except, exists, substring, concat - SELECT: additional keyword arguments accepted include :INNER-JOIN and :ON. 4. Documenting lower level, non-CommonSQL functions (some of this is already done). - connection pools - database-query-result-set 5. Notes on any peculiarities of each of the backends (e.g., unsupported features, notable extensions etc.). - MYSQL - SQLITE - ODBC - ORACLE 6. Incorporate the threading-warnings.txt into the docs. cl-sql-6.4.1/doc/threading-warnings.txt0000644000175000017500000001004511746263021017032 0ustar kevinkevin============= suggested addition to documentation =============== == Threads and thread safety In a Lisp in which threading is internal, rather than done using OS threads, CLSQL should be threadsafe. Thus what follows will consider the case of Lisp threads also being OS threads. CLSQL attempts to be thread-safe, with important exceptions. The database pool used by CONNECT and WITH-DATABASE performs appropriate locking, so that it is possible to use pooled connections from different threads. As long as database objects (representing connections) are not passed among threads, WITH-DATABASE and CONNECT may be used by multiple threads. However, the database object contained in the VIEW-DATABASE slot of a STANDARD-DB-OBJECT persists even after the database is returned to the pool. Thus it is possible for one thread to read an object, return the database to pool, and then still possess a copy of the database inside the VIEW-DATABASE slot. Then UPDATE-RECORDS-FOR-INSTANCE, UPDATE-RECORD-FROM-SLOT, and UPDATE-RECORD-FROM-SLOTS (which always use the VIEW-DATABASE slot, if not NIL, rather than any supplied keyword argument DATABASE) can use the database even as a second thread as retrieved it from a pool, resulting in serious problems. Automatic updating using the internal VIEW-DATABASE slot also may be triggered by the global variable *DB-AUTO-SYNC*. This problem may been addressed by defining a new object class, and changing the method used to select the database during UPDATE-RECORDS-FOR-INSTANCE, etc. ;; define a threadsafe child class of STANDARD-DB-OBJECT (defclass clsql::threadsafe-db-obj (clsql-sys:standard-db-object) nil (:metaclass clsql-sys::standard-db-class)) ;; for this class, define threadsafe database chooser method that never uses the ;; internal VIEW-DATABASE slot (defmethod clsql-sys::choose-database-for-instance ((object clsql::threadsafe-db-obj) &optional database) (or database clsql-sys:*default-database* (signal-no-database-error nil))) ;; define a new sql database table that should be threadsafely UPDATE-able (clsql-sys:def-view-class my-table (clsql::threadsafe-db-obj) (…)) Alternatively, users may redefine *DB-POOL* and *DB-POOL-LOCK* on a per-thread basis using LET before entering the thread, which will prevent any cross-thread sharing of connections, possibly at the cost of having more connections. [** is this a valid approach **] *DB-POOL-LOCK* no longer necessary, however, if connection pools are per-thread. ==== Thread safety issues for the back-ends [** my best understanding **] * sqlite2 - sqlite2 is not threadsafe. * sqlite3 - sqlite3 after and including 3.3.1 is threadsafe if compiled in the default manner. According to sqlite3 documentation, connections may be moved across threads if and only if no transaction is pending and all statements have been finalized. * mysql - the mysql interface is missing initializations required for thread safety: 1) mysql_library_init() is not called in a multithreaded environment; 2) mysql_thread_init() is not called on a per-thread basis; and 3) mysql_thread_end() is not called before a thread terminates. The second item may lead to corruption according to mysql documentation, and the third item leads to memory leaks. Another issue with mysql is that it resets sigpipe in a way that renders SBCL unresponsive to interrupts, requiring additional saving and restoring of the signal handler. [** an example? **] Nevertheless, the present version of the mysql back end often works successfully even in a threaded environment, albeit with subtle problems. * postgreSQL - is probably threadsafe [No information] * postgreSQL socket - Is probably threadsafe -- has been used for a while without any observed errors. * ODBC - the Clsql side doesn't have additional issues beyond what's documented above. But this depends on what odbc driver your using. It appears to work with unixodbc and freetds. * AODBC - no information * Oracle - no information ============= end of suggested addition to documentation =============== cl-sql-6.4.1/doc/ref-conditions.xml0000644000175000017500000007541210667176647016176 0ustar kevinkevin %myents; ]> CLSQL Condition System &clsql; provides and uses a condition system in which all errors and warnings are of type sql-condition. This section describes the various subclasses of sql-condition defined by &clsql;. Details are also provided for how they are used in &clsql; and intended to be signalled in user code. Finally, slot accessors for some of the condition types are described. *BACKEND-WARNING-BEHAVIOR* *BACKEND-WARNING-BEHAVIOR* Controls behaviour on warnings from underlying RDBMS. Variable Value Type Meaningful values are :warn, :error, :ignore and &nil;. Initial Value :warn Description Action to perform on warning messages from backend. Default is to :warn. May also be set to :error to signal an error or :ignore or &nil; to silently ignore the warning. Examples Affected By None. See Also None. Notes *backend-warning-behaviour* is a &clsql; extension. SQL-CONDITION SQL-CONDITION the super-type of all &clsql;-specific conditions Condition Type Class Precedence List sql-condition condition t Description This is the super-type of all &clsql;-specific conditions defined by &clsql;, or any of it's database-specific interfaces. There are no defined initialization arguments nor any accessors. Notes sql-condition is a &clsql; extension. SQL-ERROR SQL-ERROR the super-type of all &clsql;-specific errors Condition Type Class Precedence List sql-error simple-error simple-condition error serious-condition sql-condition condition t Description This is the super-type of all &clsql;-specific conditions that represent errors, as defined by &clsql;, or any of it's database-specific interfaces. There are no defined initialization arguments nor any accessors. Notes sql-error is a &clsql; extension. SQL-WARNING SQL-WARNING the super-type of all &clsql;-specific warnings Condition Type Class Precedence List sql-warning warning sql-condition condition t Description This is the super-type of all &clsql;-specific conditions that represent warnings, as defined by &clsql;, or any of it's database-specific interfaces. There are no defined initialization arguments nor any accessors. Notes sql-warning is a &clsql; extension. SQL-DATABASE-WARNING SQL-DATABASE-WARNING Used to warn while accessing a &clsql; database. Condition Type Class Precedence List sql-database-warning sql-warning warning sql-condition condition t Description This condition represents warnings signalled while accessing a database. The following initialization arguments and accessors exist: Initarg Accessor Description :database sql-warning-database The database object that was involved in the incident. Notes sql-database-warning is a &clsql; extension. SQL-USER-ERROR SQL-USER-ERROR condition representing errors because of invalid parameters from the library user. Condition Type Class Precedence List sql-user-error sql-error simple-error simple-condition error serious-condition sql-condition condition t Description This condition represents errors that occur because the user supplies invalid data to &clsql;. This includes errors such as an invalid format connection specification or an error in the syntax for the LOOP macro extensions. The following initialization arguments and accessors exist: Initarg Accessor Description :message sql-user-error-message The error message. Notes The slot accessor sql-user-error-message is a &clsql; extension. SQL-DATABASE-ERROR SQL-DATABASE-ERROR condition representing errors during query or command execution Condition Type Class Precedence List sql-database-error sql-error simple-error simple-condition error serious-condition sql-condition condition t Description This condition represents errors that occur while executing SQL statements, either as part of query operations or command execution, either explicitly or implicitly, as caused e.g. by with-transaction. The following initialization arguments and accessors exist: Initarg Accessor Description :database sql-error-database The database object that was involved in the incident. :error-id sql-error-error-id The numeric or symbolic error specification returned by the database back-end. The values and semantics of this are interface specific. :secondary-error-id sql-error-secondary-error-id The secondary numeric or symbolic error specification returned by the database back-end. The values and semantics of this are interface specific. :message sql-error-database-message A string describing the problem that occurred, possibly one returned by the database back-end. Notes The slot accessor sql-error-database is a &clsql; extension. SQL-CONNECTION-ERROR SQL-CONNECTION-ERROR condition representing errors during connection Condition Type Class Precedence List sql-connection-error sql-database-error sql-error simple-error simple-condition error serious-condition sql-condition condition t Description This condition represents errors that occur while trying to connect to a database. The following initialization arguments and accessors exist: Initarg Accessor Description :database-type sql-error-database-type Database type for the connection attempt :connection-spec sql-error-connection-spec The connection specification used in the connection attempt. :database sql-error-database The database object that was involved in the incident. :error-id sql-error-error-id The numeric or symbolic error specification returned by the database back-end. The values and semantics of this are interface specific. :secondary-error-id sql-error-secondary-error-id The secondary numeric or symbolic error specification returned by the database back-end. The values and semantics of this are interface specific. :message sql-database-error-error A string describing the problem that occurred, possibly one returned by the database back-end. Notes The slot accessors sql-error-database, sql-error-database-type and sql-error-connection-spec are &clsql; extensions. SQL-DATABASE-DATA-ERROR SQL-DATABASE-DATA-ERROR Used to signal an error with the SQL data passed to a database. Condition Type Class Precedence List sql-database-data-error sql-database-error sql-error simple-error simple-condition error serious-condition sql-condition condition t Description This condition represents errors that occur while executing SQL statements, specifically as a result of malformed SQL expressions. The following initialization arguments and accessors exist: Initarg Accessor Description :expression sql-error-expression The SQL expression whose execution caused the error. :database sql-error-database The database object that was involved in the incident. :error-id sql-error-error-id The numeric or symbolic error specification returned by the database back-end. The values and semantics of this are interface specific. :secondary-error-id sql-error-secondary-error-id The secondary numeric or symbolic error specification returned by the database back-end. The values and semantics of this are interface specific. :message sql-error-database-message A string describing the problem that occurred, possibly one returned by the database back-end. Notes The slot accessors sql-error-database and sql-error-expression are &clsql; extensions. SQL-TEMPORARY-ERROR SQL-TEMPORARY-ERROR Used to signal a temporary error in the database backend. Condition Type Class Precedence List sql-temporary-error sql-database-error sql-error simple-error simple-condition error serious-condition sql-condition condition t Description This condition represents errors occurring when the database cannot currently process a valid interaction because, for example, it is still executing another command possibly issued by another user. The following initialization arguments and accessors exist: Initarg Accessor Description :database sql-error-database The database object that was involved in the incident. :error-id sql-error-error-id The numeric or symbolic error specification returned by the database back-end. The values and semantics of this are interface specific. :secondary-error-id sql-error-secondary-error-id The secondary numeric or symbolic error specification returned by the database back-end. The values and semantics of this are interface specific. :message sql-error-database-message A string describing the problem that occurred, possibly one returned by the database back-end. Notes The slot accessor sql-error-database is a &clsql; extension. SQL-TIMEOUT-ERROR SQL-TIMEOUT-ERROR condition representing errors when a connection times out. Condition Type Class Precedence List sql-connection-error sql-database-error sql-error simple-error simple-condition error serious-condition sql-condition condition t Description This condition represents errors that occur when the database times out while processing some operation. The following initialization arguments and accessors exist: Initarg Accessor Description :database-type sql-error-database-type Database type for the connection attempt :connection-spec sql-error-connection-spec The connection specification used in the connection attempt. :database sql-error-database The database object that was involved in the incident. :error-id sql-error-error-id The numeric or symbolic error specification returned by the database back-end. The values and semantics of this are interface specific. :secondary-error-id sql-error-secondary-error-id The secondary numeric or symbolic error specification returned by the database back-end. The values and semantics of this are interface specific. :message sql-error-database-message A string describing the problem that occurred, possibly one returned by the database back-end. Notes The slot accessors sql-error-database, sql-error-database-type and sql-error-connection-spec are &clsql; extensions. SQL-FATAL-ERROR SQL-FATAL-ERROR condition representing a fatal error in a database connection Condition Type Class Precedence List sql-connection-error sql-database-error sql-error simple-error simple-condition error serious-condition sql-condition condition t Description This condition represents errors occurring when the database connection is no longer usable. The following initialization arguments and accessors exist: Initarg Accessor Description :database-type sql-error-database-type Database type for the connection attempt :connection-spec sql-error-connection-spec The connection specification used in the connection attempt. :database sql-error-database The database object that was involved in the incident. :error-id sql-error-error-id The numeric or symbolic error specification returned by the database back-end. The values and semantics of this are interface specific. :secondary-error-id sql-error-secondary-error-id The secondary numeric or symbolic error specification returned by the database back-end. The values and semantics of this are interface specific. :message sql-error-database-message A string describing the problem that occurred, possibly one returned by the database back-end. Notes The slot accessors sql-error-database, sql-error-database-type and sql-error-connection-spec are &clsql; extensions. cl-sql-6.4.1/doc/ref-oodml.xml0000644000175000017500000010562412064366222015115 0ustar kevinkevin %myents; ]> Object Oriented Data Manipulation Language (OODML) Object Oriented Data Manipulation Language (OODML) provides a Common Lisp Object System (CLOS) interface to SQL databases. View classes are defined with the OODDL interface and objects are read and written with the OODML. The main function for reading data with the OODML is the select function. The select is also used in the FDML. However, when select is given a view class name, it returns a list of instances of view classes. View class instances can be updated to reflect any changes in the database with the functions update-slot-from-record and update-instance-from-records. To update the database to reflect changes made to instances of view classes, use the functions update-records-from-instance, update-record-from-slot, and update-record-from-slots. The function delete-instance-records deletes the records corresponding to an instance of a view class. *DB-AUTO-SYNC* Enables SQL storage during Lisp object creation. Variable Value Type Boolean Initial Value &nil; Description When this variable is &t; an instance is stored in the SQL database when the instance is created by make-instance. Furthermore, the appropriate database records are updated whenever the slots of a View Class instance are modified. When this variable is &nil;, which is the default value, &clsql; behaves like &commonsql;: instances of view classes are stored or updated in the SQL database only when update-record-from-instance, update-record-from-slot or update-record-from-slots are called. Examples (let ((instance (make-instance 'foo))) (update-records-from-instance instance)) ;; is equivalent to (let ((*db-auto-sync* t)) (make-instance 'foo)) ;; and (progn (setf (slot-value instance 'bar) "baz") (update-record-from-slot instance 'bar)) ;; is equivalent to (let ((*db-auto-sync* t)) (setf (slot-value instance 'bar) "baz")) Affected By None. See Also update-records-from-instance update-record-from-slot update-record-from-slots Notes This is a CLSQL extension to the CommonSQL API. *DEFAULT-CACHING* Controls the default caching behavior. Variable Value Type Boolean Initial Value &t; Description This variable stores the default value of the CACHING keyword for the select. Examples (let ((*default-caching* nil))) (select 'foo)) ;; is equivalent to (select 'foo :caching nil) Affected By None. See Also select Notes This is a CLSQL extension to the &commonsql; API. &commonsql; has caching on at all times. *DEFAULT-UPDATE-OBJECTS-MAX-LEN* The default maximum number of objects each query to perform a join Variable Value Type (or null integer) Initial Value &nil; Description This special variable provides the default value for the max-len argument of the function update-object-joins. Examples (setq *default-update-objects-max-len* 100) Affected By None. See Also update-object-joins Notes None. INSTANCE-REFRESHED User hook to call on object refresh. Generic function Syntax instance-refreshed object => Arguments and Values object The View Class object which is being refreshed. Description Provides a hook which is called within an object oriented call to select with a non-nil value of refresh when the View Class instance object has been updated from the database. A method specialised on standard-db-object is provided which has no effects. Methods specialised on particular View Classes can be used to specify any operations that need to be made on View Classes instances which have been updated in calls to select. Examples (slot-value employee1 'email) => "lenin@soviet.org" (defmethod instance-refreshed ((e employee)) (format t "~&Details for ~A ~A have been updated from the database." (slot-value e 'first-name) (slot-value e 'last-name))) => #<Standard-Method INSTANCE-REFRESHED (EMPLOYEE) {48174D9D}> (select 'employee :where [= [slot-value 'employee 'emplid] 1] :flatp t) => (#<EMPLOYEE {48149995}>) (slot-value (car *) 'email) => "lenin@soviet.org" (update-records [employee] :av-pairs '(([email] "v.lenin@soviet.org")) :where [= [emplid] 1]) => (select 'employee :where [= [slot-value 'employee 'emplid] 1] :flatp t) => (#<EMPLOYEE {48149995}>) (slot-value (car *) 'email) => "lenin@soviet.org" (select 'employee :where [= [slot-value 'employee 'emplid] 1] :flatp t :refresh t) Details for Vladimir Lenin have been updated from the database. => (#<EMPLOYEE {48149995}>) (slot-value (car *) 'email) => "v.lenin@soviet.org" Side Effects The user hook function may cause side effects. Exceptional Situations None. See Also select Notes None. DELETE-INSTANCE-RECORDS Delete SQL records represented by a View Class object. Function Syntax delete-instance-records object => Arguments and Values object An instance of a View Class. Description Deletes the records represented by object in the appropriate table of the database associated with object. If object is not yet associated with a database, an error is signalled. Examples (def-view-class tab () ((a :initarg :a :type integer :db-kind :key) (b :initarg :b :type string))) => #<Standard-Db-Class TAB {49B01845}> (create-view-from-class 'tab) => (defvar obj (let ((*db-auto-sync* t)) (make-instance 'tab :a 5 :b "the string"))) => OBJ (start-sql-recording :type :both) => (delete-instance-records obj) ;; 2004-07-17 11:07:19 foo/bar/baz => DELETE FROM tab WHERE tab.a = 5 ;; 2004-07-17 11:07:19 foo/bar/baz <= T => Side Effects Deletes data from the SQL database. Affected by Permissions granted by the SQL database to the user in the database connection. Exceptional Situations An exception may be signaled if the database connection user does not have sufficient privileges to modify the database. An error of type sql-database-error is signalled if object is not associated with an active database. See Also update-records delete-records update-records-from-instance Notes Instances are referenced in the database by values stored in the key slots. If delete-records-from-instance is called with an instance of a class that does not contain any keys, then all records in that table will be deleted. UPDATE-RECORDS-FROM-INSTANCE Update database from view class object. Function Syntax update-records-from-instance object &key database => Arguments and Values object An instance of a View Class. database database object. This will default to the value of *default-database*. Description Using an instance of a View Class, object, update the table that stores its instance data. database specifies the database in which the update is made only if object is not associated with a database. In this case, a record is created in the appropriate table of database using values from the slot values of object, and object becomes associated with database. Examples (select [email] :from [employee] :where [= [emplid] 1] :field-names nil :flatp t) => ("lenin@soviet.org") (defvar *e1* (car (select 'employee :where [= [slot-value 'employee 'emplid] 1] :flatp t))) => *E1* (slot-value *e1* 'email) => "lenin@soviet.org" (setf (slot-value *e1* 'email) "v.lenin@soviet.org") => "v.lenin@soviet.org" (update-records-from-instance *e1*) => (select [email] :from [employee] :where [= [emplid] 1] :field-names nil :flatp t) => ("v.lenin@soviet.org") Side Effects Modifies the database. Affected by Nothing. Exceptional Situations Database errors. See Also update-record-from-slot update-record-from-slots update-records Notes None. UPDATE-RECORD-FROM-SLOT Updates database from slot value. Function Syntax update-record-from-slot object slot &key database => Arguments and Values object An instance of a View Class. slot The name of a slot in object. database A database object. This will default to the value of *default-database*. Description Updates the value stored in the column represented by the slot, specified by the CLOS slot name slot, of View Class instance object. database specifies the database in which the update is made only if object is not associated with a database. In this case, a record is created in database and the attribute represented by slot is initialised from the value of the supplied slots with other attributes having default values. Furthermore, object becomes associated with database. Examples (select [email] :from [employee] :where [= [emplid] 1] :field-names nil :flatp t) => ("lenin@soviet.org") (defvar *e1* (car (select 'employee :where [= [slot-value 'employee 'emplid] 1] :flatp t))) => *E1* (slot-value *e1* 'email) => "lenin@soviet.org" (setf (slot-value *e1* 'email) "v.lenin@soviet.org") => "v.lenin@soviet.org" (update-record-from-slot *e1* 'email) => (select [email] :from [employee] :where [= [emplid] 1] :field-names nil :flatp t) => ("v.lenin@soviet.org") Side Effects Modifies database. Affected By Nothing. Exceptional Situations Database errors. See Also update-record-from-slots update-records-from-instance Notes None. UPDATE-RECORD-FROM-SLOTS Update database from slots of view class object. function syntax update-record-from-slots object slots &key database => Arguments and Values object An instance of a View Class. slots A list of slot names in object. database A database object. This will default to the value of *default-database*. Description Updates the values stored in the columns represented by the slots, specified by the clos slot names slots, of View Class instance object. database specifies the database in which the update is made only if object is not associated with a database. In this case, a record is created in the appropriate table of database and the attributes represented by slots are initialised from the values of the supplied slots with other attributes having default values. Furthermore, object becomes associated with database. Examples (select [last-name] [email] :from [employee] :where [= [emplid] 1] :field-names nil) => (("Lenin" "lenin@soviet.org")) (defvar *e1* (car (select 'employee :where [= [slot-value 'employee 'emplid] 1] :flatp t))) => *E1* (slot-value *e1* 'last-name) => "Lenin" (slot-value *e1* 'email) => "lenin@soviet.org" (setf (slot-value *e1* 'last-name) "Ivanovich") => "Ivanovich" (setf (slot-value *e1* 'email) "v.ivanovich@soviet.org") => "v.ivanovich@soviet.org" (update-record-from-slots *e1* '(email last-name)) => (select [last-name] [email] :from [employee] :where [= [emplid] 1] :field-names nil) => (("Ivanovich" "v.ivanovich@soviet.org")) Side Effects Modifies the SQL database. Affected by Nothing. Exceptional Situations Database errors. See Also update-record-from-slot update-records-from-instance Notes None. UPDATE-INSTANCE-FROM-RECORDS Update slot values from database. Function Syntax update-instance-from-records object &key database => object Arguments and Values object An instance of a View Class. database A database object. This will default to the value of *default-database*. Description Updates the slot values of the View Class instance object using the attribute values of the appropriate table of database which defaults to the database associated with object or, if object is not associated with a database, *default-database*. Join slots are updated but instances of the class on which the join is made are not updated. Examples (defvar *e1* (car (select 'employee :where [= [slot-value 'employee 'emplid] 1] :flatp t))) => *E1* (slot-value *e1* 'email) => "lenin@soviet.org" (update-records [employee] :av-pairs '(([email] "v.lenin@soviet.org")) :where [= [emplid] 1]) => (update-instance-from-records *e1*) => #<EMPLOYEE {4806B53D}> (slot-value *e1* 'email) => "v.lenin@soviet.org" Side Effects Slot values of object may be modified. Affected by Data in SQL database. Exceptional Situations If database is not able to be read. See Also update-slot-from-record update-objects-joins Notes None. UPDATE-SLOT-FROM-RECORD Update objects slot from database. Function Syntax update-slot-from-record object slot &key database => object Arguments and Values object An instance of a View Class. slot The name of a slot in object. database A database object. This will default to the value of *default-database*. Description Updates the slot value, specified by the CLOS slot name slot, of the View Class instance object using the attribute values of the appropriate table of database which defaults to the database associated with object or, if object is not associated with a database, *default-database*. Join slots are updated but instances of the class on which the join is made are not updated. Examples (defvar *e1* (car (select 'employee :where [= [slot-value 'employee 'emplid] 1] :flatp t))) => *E1* (slot-value *e1* 'email) => "lenin@soviet.org" (update-records [employee] :av-pairs '(([email] "v.lenin@soviet.org")) :where [= [emplid] 1]) => (update-slot-from-record *e1* 'email) => #<EMPLOYEE {4806B53D}> (slot-value *e1* 'email) => "v.lenin@soviet.org" Side Effects Modifies the slot value of the object. Affected by Data in SQL database. Exceptional Situations Database errors. See Also update-instance-from-records update-objects-joins Notes None. UPDATE-OBJECTS-JOINS Updates joined slots of objects. Function Syntax update-objects-joins objects &key slots force-p class-name max-len => Arguments and Values objects A list of instances of a View Class. slots * :immediate (default) - refresh join slots with :retrieval :immediate * :deferred - refresh join slots created with :retrieval :deferred * :all,t - refresh all join slots regardless of :retrieval * list of symbols - which explicit slots to refresh * a single symobl - what slot to refresh force-p A Boolean, defaulting to &t;. class-name A list of instances of a View Class. max-len A non-negative integer or &nil; defaulting to *default-update-objects-max-len*. When non-nil this is essentially a batch size for the max number of objects to query from the database at a time. If we need more than max-len we loop till we have all the objects Description Updates from the records of the appropriate database tables the join slots specified by SLOTS in the supplied list of View Class instances OBJECTS. A simpler method of causing a join-slot to be requeried is to set it to unbound, then request it again. This function has efficiency gains where join-objects are shared among the `objects` (querying all join-objects, then attaching them appropriately to each of the `objects`) Examples (defvar *addresses* (select 'deferred-employee-address :order-by [ea_join aaddressid] :flatp t)) => *ADDRESSES* (slot-boundp (car *addresses*) 'address) => NIL (update-objects-joins *addresses*) => (slot-boundp (car *addresses*) 'address) => T (slot-value (car *addresses*) 'address) => #<ADDRESS {480B0F1D}> Side Effects The slot values of objects are modified. Affected by *default-update-objects-max-len* Exceptional Situations Database errors. See Also *default-update-objects-max-len* update-instance-from-records update-slot-from-record Notes None. cl-sql-6.4.1/doc/catalog-suse.xml0000644000175000017500000000262210667176647015633 0ustar kevinkevin cl-sql-6.4.1/doc/html.tar.gz0000644000175000017500000037765312064371653014623 0ustar kevinkevin‹«óÑPì=ír"G’ó×›Qgq–¿¦ú„ò íøo ,2\›‚Ð×ó„úþ˰I”ÏS@ƒ÷Áÿ45P Ç‘ý 6ö0%t4b®{Ï`d{¹Ú·@ËÓ2mÿþÀÕ8.æa¦Â%=˪É:úd (Â$Íuli_ßQ&§A™7„¥åpîG"lX€¶³ðY¢$'®µ‚í~Cø!¼Ÿ “Ê'ƒÇ•¿àꮵ¯á ˆH­}j‡yFþ÷¿ÿ‡Ü1oî˜.¡Ç#Ö˜h@¾!u‘[Ý©ë9–9ñ)|Z–?œ–íäÁ]6òªþÜú Ó£Oþ´tÍ®VµVõ¨!§ˆ‰6G‡)Xî´lW‡ùçÿœ‚ÊõŸŽ%BùvˆT§elÒ&_Ó™ý-0œ²Y€šmÐÃv04og=‚.’}NËlÖÞÐ^'Òåìë‰÷-9ÅetE²>Pc]æÎ l€TsXºuœÉ|b¼15ò‚rcT¬WZ•“zš†Æy ŽŽ3BšAWÍ€ÿ¼vyXP3x¦ˆ_g+ÈæOaiJšd™út`t`»<ˆ2vÜ7•ëË+Å<ˉRÓ]̆¬´jr¤‰À—²¨m3™$ž¦™¿P¬á/À9ò8ÕGS¢±1n»Ä³b=§ôN¶/*hïÔ÷6?%~Ùf§Ôàš» 2 æÍ"ÝeîÈÑm±h£’||\«’j¨ײ¢’˜Áæ +ʹ‡oBiqCÃ%º©ÔFFî¯deF’LkHŽ¡»)VÈp¡°“¸Î؀ěR i,¤ò&8ˆ†­çh É(hX$"ÓJärœ IDJÒ ¦…TWpù(œøÉXlC±]ǹ>Ò1ÌCá6úMBÞ{‚­ÇXÒÕÃzXW«VË{ÞÈa –G®ÚÕÈ ŸÉ¦åßæÄŽSÈ{`›ÿÌ›€·À¿ õ‰²Bò À[ †FÖ ¦ÖFžjšƒÏèÏ¿X:X5yhàÇBâ#Ù“ŸµÐê%øÃıВÆ?mlj¿öèè_<î;à_Ô‘Îá§&þÄ',žêæ”A/ÿ˜ôâOËV®‚øêCg(:³lõk€Š! ?õÍ™0¡ªeÓÉÄa`õ†P'&GãÜ7Õ·ue?®\l0 ÄWwJ5ë14-Ë”Ž¢x®1›™Z@X·yÕÖì†R}HPYy‹¨x`ûž>R¬âìöÅ9!ÒŠôÆcøqI¨šÕZÈŒ µTzÛß7®Á1öwí”k©ÃaqÝùø¨y2}‚†KgSÚYûˆÙÒïèëÞœûPq*5«‡£ðÒOê³zõ#õâÔ`{ ±I¶CŠsh`:gùJÈ+ì먢¸Ìûôã¿IãQ¸z8–|ŠÎ¬ò•@ÁÚJò€/îzAOúÀí6}¸»¯Ò#NÖÚÑSxß«Fºn1nÇ}ÕøQÉ8(s³H\[ÞÒ^Ô<ª7CòÀ›¤–¿¥!Mú0¶,± ‡7e¨Áï 4ö2HtòUÈ užj´Ò'㸯 Á*ù̓½®Èñ6“&DÏÚß[&H3×(*¿ÿì•bZñ)=l羸ø?§ÕóÄþ7Çÿ+õV=œÿ©½©TëõVí5þÿÿiñÿK\(/=ò¿MïpxßýÕ(ŽÁv4ŠÌq,' àßw«bïîîænM d  d:†=¥CÆ<˜‰œ¢°_:üŽ{Œes\?cì_ñxǨ"3†þy«­CúK Ø2žï€>`>÷8yò+Cö @¬Fž†šØl„‘&‰=­Fm°Øxàÿ¢%§÷Î|kLäŠv£ü¤°JP8­"V1Ä!ÇØ(öܱ-pyÛ<qaèÐ ±åC Α>›‰Z®‹;~6ƒ4¥4¯5Ô–[5ö-Í™ ͘*{Öf:‘Û« Êí?¤,{ÂX3Z{77Ô4ë‘ú^ÿѪU_í¿Wûï¥Ù¨2zŸnïzýþåÍõ—Pâòüs,Z3e¤Ïw}DšLd¯5 —ÌÀ5¦êßVê$b?ÞÜöî: àg´ò–8¹»¹·•‰·‚»Ø} ÔßG%G”b¾9Ý;öXÏOXQ<¯0ñ:N­`d2v¬H…m:ÓäÑr4BUåÀ³T{TŽ+‡GG{«öˆÒÒ¯ôP©Ñu B‘·\Uï±Ô<ÞÔºé[«„Xzl@¿ˆº“Êñáq8íóÇÕ,ó/¡”AUš”v)šXb}ò@\'E+h¬‚ è†OÆ:svÂhI¼1Cò¶»–$žéi`À¾æÿäéC#âÚl”r¼´k'a(Yõ>*4 m¦˜¢RE!û®O3míÌÒv0R{l|kð`§UÛƒ_€¡–·,5¡ 2½l͆:ÖuPü/ðÝPf¡{l¦ÿ‹irÑÏÄœ€gyØÍ‘îŒxÄÁЃìšëas4°H ^«Àÿ.bÇâwŠ•1eW¿ ¿RCˆËã·áŠ4ÁdCßz"d·™|6d–ö@¬åË´ÅfáÁŸˆ‹ „K?‰ýñsÑai*ÿ…áÏÌÏHO´3­Š3ý"’e¸”ˆGyžÁ´H®X¬Ö›Z¶ŠÅ˜gv"ŒÑoÆ–EN{ð›!uTaá_¾6¼oy°¦Øÿ©‚ÿ^v{׃bg0¸»<ÿ8è‘÷77¥óÎ6Ï-û¯ `Ï;ÿÁAî­®ZoÕ*•õÅp¼¦f×Ú·jý¨Ùh¤«}ã­Z?>:J]ÒÖ1 χ¶rbé² ˆW%T?ö{w2ŸÚ^@„J§‚ÚjWŸ–K£A<7Ñܵ$ 0iE” p]ŠŽ` IùÚ~Jôª°Ôêx‰^bÀr m·¨‡Kä\ÇRÀN$É”ƒD©îÏPŠWm´ZÇ«JñâÚâE%:÷]rÁï¡è.ex7k*ô¤?#ËæOXk÷bëÿ"…¡tý_µQm…ó¿U¬ÿkT_Ïÿ¿æ_\þ7ÓYì?}‘` ãcMy`ºCŸ/CœõÜý®Å‚Qjþ±•‚K¼ØK©`†Ë&v¨'T›—05³p-eÕ¡MO7=ÇÚzb ¨ï¾FR*s#*óá'lfO)ÏŸ²Y[–…D‧íX°Zñøê8„Y÷J¦5¤èòç5´Èq*èÊ3%Ò9¤3šÌ[DîLI!'%#´•¦ o…ï7ŽÜsÉÛÄô·pž¥R§fäÒﺆTâú[Ñ¥ÇöÒ„µÈñC„yáâžéˆlÆÕC¹”~/ÜâíMÿRd#RbÞgÒÏVP÷Š7¸éæu”‚§Üˆ»×¨¥ºð(:ý¬ºÀ¿j½•–Òúc‹/ëðâ¦èÚsž\L]Ë|tQÅX_@â.ˆxÍÛ}iù?uc”¨Á*ÌœxÓý%7ÜÿѪ6k±û?«Ðü5ÿ÷šÿ{aù¿wÝÞûÎÇ+0À{¹þ®xÕ»þnðý»/á ¨e-]~#ÎyÜ8:nÚš\ÆÍ͆+Á…„8ZQE„>–t®»»n±{^¼9ÿ÷ÞÅ`sj‡²ðèF‘‰IBÚzwó¡xæpÿ3¦ W‹Æ®¹Á¤Í˜!ÌÊì=丣¨+hí§÷³=M]1¾0¨ååµbP´þq™ª»†Ubèyf0ë!T~‘pŪ¶kÖZõp±]Ð̯›ýê½þdÎgÙJ:/Q8¨!N>FF<®5¡šàHK5èºzïZ³=ófïpV Ði5ZµµGÅr_]¢'æ–'|2>†Ÿ`.r_­º6Ô'—eþDÆÕ]ôÃ`tÎv:×rÖwy îBñ³D³À3aSú€Ñ%!g¹¯ü²ÝqáoÄqö¦€­:§Š˜Ï]q¼ d3÷•´÷v¿ ¸u\¯VÂlHs0óH¡ð.qɾ#G•·x«k!ÊâUHA\÷Z(Pr"Gò®òØÂPþZ7:KHøh$I¿…O¸º¾¯nwX¼àÃõa¸ÿlU:zµû_²^?YÉ‘o7 .WˆæüÈ?àÙ?ÕXƒh> (^@‡ÖADA¤À& †¡;–gñŠ|hTÍ aÑØ`dÁþå¦á\L ¸Ø7 wÕH¡C~èÜ]|ß¹+Òäœ_„½MÆZ•ìŸGkû+ £€‚ µýç˵ý}°|øœ†ttÏL V©Åe^V2äÒ(IZ@B¬\2áÄÈ5 h¢Ò*Ýa†fíhU¥{¶#ËÕ¾yÔZUP=ÀÎ/0f!ì±ÌäçH@bPB.@:,un/_héujCgÛJì ¼‡Bì¬VN¶Ï’Áürâ<1£û5âó¥ÇFÓJÍ­Ô>Ïý¯µf«ÕŒÝÿU¯ÔZ¯ñŸ×øÏK‹ÿp§ùØš”ÜüR—ò½èÐhé<ÜŔڰaüþ[­zÝ7s@ü¸5¡ž]aE"=˜š_cð¸!}Ç y@óóuø½×ÒÝÝ£C£m/‹0mõ¤|vªbcÅÕâC¶oŠV¬ÊTUåµhU¹:Ó>2uNÈÐâ#ß ?ªÕš‡Òy~é@ã~9§ê{Jçll‹÷ˆ®¢)½Âòëœ9 +P·ç–¡ì·â\aÀГ+¾†§kîð<1™!y0Òî›xSÒíT7t›|‡þ¨kÏý7Yo×þG˜Òj¥y¨Dæ/cÏ,…VQp:t¾]E–ü0œKúXÑêG Š(ñ÷µ-¬9¯#÷˜ÁYˆŽ’#Õ5üD·„ÔéáU îÂõÀõ,ÜuÏ?ôßò~⢠€r’Xžé¾ MwGÉ7á„~ÄWaÉú ?Åg†óyÔñ^aX£Ê×\qyBúÞz$üåA„ÑÑÔ¯ Aa¦èι‡ ‘W”-Aà êfJþÜä}L¨ÉРæ}z0¶8%à¿HH(%cý þÓb’j’ èëðõ4zaÍš»á—i‰  îpL+%ÞTHáz%Ò³ÁXNÖÜÀПä å±q'Ø)@ _I/,M,L’5B6ÅòS¸šÐ™¨`—(…ŽtLU¥;Lm"¦¯›„ÒÇÉúWkaÌÉ6Ø ;‚§þ«ô@®˜”Ï QÙ­£hþ›¾DƒÆù‹ØèÛ! aB ±N€mX…W&˜(‘ô’¼ȱk‚Jˆ²…‚æAâ<è4 <4ó™ˆÀêêtI¨’ ó¥’¦mp5м qN‚—üç³€g\øe¨¹ RKa÷ÆE:¢†±Â€Uä³ó‹Ò4Fƒ ÍÅPœŠs3MŸÏð[ìK Jø xàËå øÀ7qÑ¡b>Ö£•‘>À/@0¾œ˜…Ñ Â¢¶cM:ã+Þœ€{‰ö>Ü^ÝüÔë‘Á“隸yäf@®?^]s>2§P?z{{ÉdðëŽëñ«ýdd²V¨WÖôÄ2=Ñ1kO6£ºûÍï vñš®ò¥k8ÓLÓ{£#)$M¿ßÛ\”®7n;×?YCãePÐ…Dù‘nŽxÃŽ¸¸QKòm.È«¨*Èä,G¤¥']&^Ç f9oõ»˜Rƒ‚ õñÇÐMI‘£õõùPŸÁÉógÊMCW*÷çñs«Þþ;²ŒùLÝËKŠ\4ø–)§•jã@„©Íé€ÿ¢c‰›‚0§ºÁ{¤rá@@ÓËqô'ìŽ9\ʳJZ*ø Á-Ë S†¹#jc¥ƒkaÖ±8¤ìD°*¸Qlý ß¿¾Yû e©<¢TTî®ïž)!ãçÚƒËØlæ ?,-oŸ†¥Uƒ‰u‹‘`¤sCþ'#ŒÅIM¹3¦›ÔY(.…ÂÁ¹ÌµÓãËÇ+2à8xu ‡l Sðþ«Âñ>5ÞÜÔÁÁûäÜ`¢8öÁŠQÑS‰¾6œr?FŒ»x\ÙôböÊëb¡[ NtÇ›ÃÂ[9ÝPŽ«7Î %,͹TÚ,^›¤Ëáè@¾D}ßHdÏ#þ›^¯éqƒ+­ÇÅ]rRÎ-/óFˆÎ¨;þä ¾ªäÚO” ™ …‰ïK#)r x´ /ÇI#K•ŸjJJÙ‹¹êžèìÑ{ôP—$ #!“G p‚3N¢5ç¿;U–ª=÷ífüΜä/ß•“œLê<ÙF¶*†˜›‰­b+yª)5G¥Òt3¤§B›*'B‡éÞ€³q7 ™,îOVìíø´áÑÆ )$"—öG·WQQ Šp……±´ÒvCÿÁÒµâƒ¨Ë oeWºk+RZмzX,i -à±Ñ¸ýLM0^Ðu–öY‰ƒ”U|ëº\ú=vf †œÃL»‡ ¶°%– ʂ˹ }â‘ëÐabÛÑ1ˆ\Ã;|×qƒv0©ìˆ˜àPmˆÂ¤T‘TêoB¡ 4G"Cö+õ/þ™á’. v†Æsßb 5ˆŽæÈ²u¸ÊBtCÖqÄÈß”'çÿ½ßo9ÖDÑõ¯ø8ê½WIuDï¢äãÚÃ’XݲU’,²ÜÝÓ»Þ JXE4@–Z^{æYü,~²yA&îA‰åfÏ,E™‘·È̸|ïš'®"lÏPÚ¹†ú|Œq~3¶› ²ºjUY™ˆB÷T ©uÓ‹a%ðP;ò²u„¬@jû‹ äcŸ÷ Ó5²ý,~±pUœiü4J}´°æcºþèJE8¯¤•Ãva,¶ç¤¾¡”'ÜÐVl<™”6@.>QûÝß2ô“é©'Rí¬Ž)q>á§Lz˜Þ[¡”ýëÏŸ>ôïЄ·Oû…4}Áª|X™.Ê `gB¾ÝŠ'*†µÑ{‹Ô€_6ÍfœÓ1oó1íÇpÁˆ]œÂ¬A3Øæ<ôʱÃ*8_ÍqQ2—fŒA÷lp@U_n&("2GÂB Uó+ç¢&S ÚíùWgúUÚi• O{>¢H‘ãˆu‘„{˜ØPK¸/ Ì˜Ó Ô-Frðlÿ­åTK;úÍèlKâWËr,Ê ØÈ÷¤-!ZóÚ»üýþ#Ú¦«69éGVU¤ó”dJákœ4ZAüÇV«¾³ÿìì?[—ÿß¿êA³œ÷«wýó›»‹Á7‚ÿ8Ë‚ÿøIä ‡@?%"@*ÊcâbÃÆzeJŸ}¼ë~è_$؉V‹1Bëp=ÄÐuDz±Ÿo/’†C¥U½&p@ìDYÓŒ×Íe A&ý:–¦ôá,ÃîÓç *dä.W¢õ)FŽ Iþ_\³¼bÿú+2s}£ÂÃÔñ< ³]H_À„¤îúŽþR|¶û*Ô¢ÿîû¿btÅ9óêÒåAò…s€-qOülymRâ6ÖîM-dtí¨tñôLðyî,è†#®ÜqÞéÈa/Já?§æÈÂY#@àX35 8†¾@ÅÇØÇ¯äRܰ²"Þiæ¿ô‚rÒP)УÞ`Ý£Ô#Ð…½!‚*Žq^¸ù:íÀ˜á²þïaü)ëdÛ±‘é(jÓgå1ûšÏºq@ÛT«Ö¨·kɶ)¶.=Žýµ0+éXƒӌǑ©ÁyKÁ`7 \gdû¨Žùj;fÑzEÄdqlÏ¥ÁŒ²7èRL™@ÂNWn(Të´ž842‡F…#‚ÊD:SO³Óséy •Ïßëh¢iРÃÞã¿[§jõn«Í Ac‘AADQ‰Kõ°!1P齃Ÿ„ñ£·ÆRà•Êÿ0žP*B*Û×F¡÷ý4}_蛪P¶}•…LŒ(ûå·ñ ámT‘"5-Êõ‡?Z­U­Të'F½~V;9«Ÿ¢qèݽéÂÿýƒ«V¶ x£Qùñ‡þ]?›Æv–‚°¯ÿh …dPj†M ÎÂFŸðECÓ¬sªâ$«Oú8ÁB%¦ŠLÏÀ;:0?;(êýsPžnSÕOʃ¾8·mëy”‚øàšâ¸”Iäà¡íJXG÷äp™[£pL|†õŠ g`/W“+ÐŒÓù4ú¿E°ÓXâòÂô v™l¾äÔ4h“†€ì­&{„ÇX ÉûjOa•SàÝ î°“ç@RJo^Ùc* Õ0®}G ÛpéiÅ‚ëû'쉆àœíô!’ ƒºä2¡‘_­¢s,“¶Uk¢]%“–mH÷ìòÇýšrë0P–Šåd×—¡~ÞOº°íǹô"”˜Äö}\h$)³Hø9=M½ˆ2”tÍÖGzñÑÒêöÝ|þ˜K'­v'ÆRÙ»ä53L$Éލ¿©o2ä¾²‡Oˆ”Ž3{™F%²Õ¸ÊF´H+{|y޶J´²T'¤Ê@8Œê="©æõ,¶Bj Ƴs‹‹Xg"E„¶Ç “Ýp°ºò¬¼Ïb6ƒ\N™°Ij |3Iš`ž†ÿd½ùøÏz³sr´ÿ7íýgÿß6û,úïœþ)ž@.•³'Þ #¹åõ ý±3bM;Bn1ñSÔ•aÚaûÇÓèý«DÃ~tý:ͳOÒB&ƒ—±æo€_ï´juÈd=~ôèd³ßûB0hÚUú?ÍÙâxgH."°†ï&¿BÛŽ9âV‹×ô`$Dí´ó¾ƒ„®Op"¨HS/êA`÷²GsÙ­¹D%dÆôµ“'ógNüùû?jÞ¦t|Îî–6.f§Šës_ÑÕxagµ²ÔiÄfjP%Ù1‹÷å,3™)Åëê%2ÚU’‚ ÞJhÙµ{7n‰'ô0!ˆ§Âš(™ï<˜3wu—°8ˆ‚yº¾¡Ê¤Û dÂfücpÛj·›Ú<¶Ãy²%¦JšÇ`3^Âo½WPYÑlÍ»ÐÊpjÕNkͦêÏïÔš8:µ|Ž;•Í.Í5õñæ†XëN>žœ_¤¸¦ "IZ‡»ÃtðD ûPØþaiŽèš6ÜøÓ1ç‚/ŠüŽ›7à–é:-Íaå–ùäxKÝñ;8?ù —éD´£²GM02KxgAŽ26JÓ"‡ðòp3¥Õœ"~Øseñ 2Ä%Ý".9 C6W߉rTÙ›!ÜgÈy"½L –€rAË÷AwkµZŸ‘’7"ì®AŸúí¹þ\©ì­?Y¢9ÿNk§­F+žóçøoÊѲÉ#LfG‹ë,’¹š/înn#în1òD—ìÌXäÌdŠàV<­7O»­XׯùÊE”DÌ'D½øŽOÏ >€„áQ6vPª^ei×ã’ó ®óÕóXóÞžÚËgålæ­¶£ØS*ô”?tÌaƒ_²‹ìÄôˆ*“á¥ïè‡åH€¦6R´<ŸÅNG”Ö3 @ÀJÖK„i¾ìãŒýDŠL¢ôŽø1FCÎÓr«(Reå›Å—} ÿÁµ”¦Ý ™5ÜQ´BÙ÷O.{Òvðkf5&åòùĘ!·ÀñÄóz™¤òÿЉZay Lóÿ´:ªÿ§þµz«Ùnìü?;ÿ϶ù®.ÃêåõEÿ§þ7áõ™„œ>ÂN §ìxGÀÇ4wžÑ"¤£ƒuO‚[‡Þ“œèÁ$x·Úÿ ºyP½}E·N` ×uæú+§'û˜­ã»‰—2|7jWÊS·ºã”è§Që"ïÌYçÑ„€5jÀýb¿Û€¥ÑmvkåyPÔÞfÆŒÞlbÝL~öiŽ æ™Ý$‘ž•4 Ã/ÝQÒè¶›u-”öå’,‚ÝeCÖ#¹{ª=Ýž w˜h,s:• ­Zù/áu¶'ØÀ-Ý>£Bà¼ÿ²ÚX©-ÓýY 2¸@&;ŽìÌ—­ß0Ä#O_Ñ=ËôhlSqÒKk»XzùFVŠM öâÄ)Å!Ñèvšz²C"¬Ò¹d:g©KÞÍ’¡ ïÌÆ9§¯‘Kø,2éÚáÞýe²Î,S0+‘­ŠoÖBv´ fŒÔÅ^´Ær›OJgÂýckî,}“e!`ïňQ¤GÖ7‘OÀצ†ŒúB+õÆ!1r ë™hô‘]Aù3{éé˜6lÁR6ƒì?fÈö-ý”ø Æ`²šòèj¿4ƒå[›>ñ–>ßáÆ~„tþ$$ÌhŸ+Ë‚[‹‹ìM©JÔןA> Õp8÷_Ƚ¾ ˆ^SÌÌE㣠Iò)¯ Ÿ`£{ÒhÔº¹|‚êéÏwÈ j¼Å¸NsB8úlŽÇ.}¸7ÝýCÑŽŠ^Žq}úæà|øWãþþ¯‡~ù²¿ìòüÐ Í“NšÿO|:sëØ(Ç·5뙆Q¾½b‡”Ò}d k§ÕÊžWµNEº·@¥ÚK§q'u”ùƒÅá1Ãûäx3z½¨?+Ù¸‘è»*Zo»H\ýzå§5ºÝF³Ýˆó“Ée“ý[>$š†flµC&Õ&TÔ 3)Ó “Õ*”Ë ã/¥-ð»èkë÷†&ñßw/çÿ©´µ@þO ®;ÿÏÎÿ³øïpâï ù½ês2¼žeŸPÜ6`Âk_|ton,|Ô¸” ¯`ü« ðþþS2¼_y„"ЧѤ@5{’ÂÍ™ Ò0òTû¤ÇÌœ ¶Ní{) PôÄxo5º1Þ€Œý1É€{³„ÅH'T£ÖŒuΊ”üpv|ôŒÅZ®í¬¼¨rw˜ðb޶kš‘¥&<_“Ì–=­\¹<Î,§6™ú»²˜ W {ƒáTa&Åm‚­Ç«%ã{j/.ª~¿¾²Gn öP¿å4í„Æi«NÔ”eÑá#§ZsX5%[rX=Z\/^Œî]ÇLoi°Z)až®M>Þ-öåÈé1SÔ¬Ùþyû¤Þè–‡îwgÎÐß%ÙŸ¾Éh^èÃVW £§¡`ìfêe =3T¸²cCùôÖ@á<@ÅZ@âª:~éâ^ dy£È%ZU”W (E‚”TÖˆU~ùÝÌWll2’·Õî¢ÌÉ›C‰s‘¥*GC!Nr_¥L?áË®3Ûæ¸ß ¦áU:Ã=¨”y<2N„¦H n è ]CTr¨¤#Ò¿2QÓÆ->f¡d#W±«|lnÁͱ+—Á(Ð>­µTଠ– @ùBJ,ßß–ãž!X–r^èa±~™7]¼ Ë´<Ôûöi£Ñz`K¨¹Ùî¶²[©8 8}û´uÚÈDÙ‹âº@ ‘ûs—‹ö@Zž?½üïÂ%Žã›ÜH,ù;8G·OêõA[Æéô•pÄÔædª´Óê$VšôùãÇˈÀ ’dë¶ZMÆ>xÑ.½ÎN  PÑÃÔžÍøÇöÆ%^°Ñ-b²SΜžtjè¿òëŒo±†˜" ·*³,A8oL 5Ÿè—ÊW…çy¨\ÖÚîiSûsoå&Á?*³Í:S¶›qî>â´ÑÁ©õaeO“ºû\ðhM–Ë#Ðí¨Å_DŽÆk|Ü2— ±0—¥ÉxÒBkf²ŒþR,µîFƒ² ÷O,Þ—;ªjZdvñ`GÕ|ÎJïïÓ8¥_½ùÞ¦=FŸÞ|5»·\v˜A9ÈRÅdÑ-óˆ«ÀÖ hÃڛᄳËÈ”J3pPÛmÑetŠ08% ªŒZ¥ì sô‘ì8á66õGÇýâWK»²•Vº”¢™*üT«Ì.;¿Ìm}Mž_™Ø¯ÿ+C*ðC¹‰àéø¿­ ÿc³y²³ÿíìÛÿ+ÓðÃï4ÜOg‹Kû<¿¹¾îŸc^£’»ŸŽ(&ÓÆ•7캽¹ëÝý¼©àÑs „˜áèŽÝŠœðÈ!*+„8¢CµxâˆÝ©äàâ (Òø3žfáÐäó‘=âè XžåexÃô©f^,9¼sZ;Uø6˜1$2¡s">d“ "|—¦¾KSOMSïÀaA O‹ˆQÍ“N22 Õ­–"ÈPKº²{G~þ÷túÌ „Y\ÆE¨9Å´q‹]ë}LOWù]$tû­ùœn–¸¬J°ÉŒn}¬a29ž%¦üMÀcÚq˜ ‹³„¼äèø±Ó¯36¡ØíŒLÛœ–ü“I`Îô«¤ÛSâéíùˆc·b”X_ÙãW[A²þMŽÒtœk0Žœµ>³£š†¸¡ ’ QçlcrœïÍÑ—ª53ÅÊð”‰ôÌÙ³fæ|i<–ûc3««o'•nÅ €ýÐAvÐçêkÏ…(I69+d}»ù±°)ºß@3öt5›{ÆÜy'¶5{‡¬<^L%ý£§Ø¯þ G•sƒ¡pžeå‚í¸ ¹á f>ã\¤_¾fì¬õjUÆ]ó`MÚT§l’Ä3½þÿåuþ,ã ùŸÐ¦ ¸7ñ¿Þò‰B×ÅÕ=lp8Áp[Ø cª)¶`áY¿™3ö—jÜÔ¢gÔìÑ›6S›öɜ۴̳6îÓÚ³ç°û-‰pŒ2¢éÓj-à-–…L¬åè‘Ì(ª¶æ¢—Ék­½ƒC¨8¼³µ" ž¹°h£‰ a(t´ò¼LüzõQ‹¼ø!ÝUEñ8w0‰A.uÏpfÅv:Þû̓kÎfHà¸7åkÑ;¾á~ÊóôåMƺä/ø1ruB‹4(Úq%§'_· &r±Ý]|ø4ˆ.Þ¸³˜Já\Ùp惪öPu,F>?6¼9:œíÒ™,Ÿp‹ÁʨVfX¼Ï}i¨´=ç-fB,‡”,žnàÂZÐSN(ô:XÙ–í:OÌk+önŸ†6}DX†?"Ói\Œ(:K‹P˜µ“‘£ã<­§„ØBäD]À‚ëá™Ø–ÆM?¹§¤,B26fØW`æö®—ü.ìŽ ±Nh`'‰m&³k£µ€mß'H¾~9?³ïœdo•–VÞ^XF}Åúê‹Ü·iQKnV® q&C¥×Öà‘4cfÙtiè3©mYrÌAh¥kÆLI˜ïS˜ÏIÛùBRןš~T[4>Šþ Ÿ"gõ}l…Ö×áq† QÂTRX‡þqSÇ\:3{d¬à0G‡zÄÍââCðWÖP$N…gæø¬vª÷VÔVv;a˜å%÷;àWãWÛzb}òWø3´Ì20†-lj>ó8ÿPɃì'Ôì±åÚ_9šÎÏŠO‹Þ1<œRy_mSîÚécˆ‚V©|q –‹=TÒÓF<èi…êø¾*%};C}òõÞæV÷T†µÅE']½šC#ÙZRJ‚KAÏ3Im/áÛupüœ¿# ûÄEå¸TO@šý¿uÌÿh·ëõýgÿß6ûÿåõ`Ø»>ïWïúïúƒúßBê‡ãŒgÓ€1Ÿònà JÖÁ$“ÌÍÍŧ«Ão€?%Sа>xÕ™ù[ujb‰ß^ô?ö>_ «Ÿo/ÊùæÃŸúçÃAõSï§êUÿúmBžG±S”žH¼HP6>Q…^ Fde]Ú#Ø \Ãï gÆÚ Y‰ >²û?ÃDy6пÊá3È'0·Ø3÷èP#ø:ÈKÅŠö¤¬Âã,úÌžÓtSã3̺RÏI³ÖÍx>u–U6Å-xÖy¶¬ºñÆš™öT‘Ã9dnÏÿ‡cd-ñ„½_9€ÓŸá}À88ð ;${êçÀ\ûÿ›¨K.à¨lC¡áô÷ðÿ‡;R’ìÊi·¯ê!MtãÍÄv½e7åħ ùü¡C £} ¦'›eFÄ~Ðÿt{uós¿hüw«[?i]œ^ü/ŽåN#‰ÝÆmœÁª‡ÞþåÆ/JýþïôÉÿjÔ5Î&p¸ZK!Ï $*£ºZp£iS]‡ÚˆŒ`Ö¿=Ì0^ü”ÈÏXÆ/B¨ÞüZ]˜ÐyÆ›ƒƒ_¨ _ý¯Ç¡Bë„¡¶Óo‘¿õýRŠ„ÝOs…Ugö_§æØžÙ®q…5gšâ¥56bË£¨ÕšíN7#À3õ²­[è?P²Ï,£Íððm¡çËGÿ¯ÕZ]•Œ)ý`ÁË@Ò¯Õ:F,’¾š|µl YŸ¦x ®ÈçÃxü|ugй…-rfàF ´×j§ífçÛGi/v/ø¯˜rJˆùÏ} ÏeO3õlÝ>ÆZô;Ê û?Ÿ»ràΤM†Íâ?ÕÚõ€ýÿ¤UßÅÿïìÿ[gÿçšLê‹w7Ÿ¥ñ»÷h7 ¦Fð°°Ñó^dýÆúppu3$ØþyÁtòU´Sd¹X–:2¯hûO™/kz’{{«íÿ‰ãY†ý?©çåA4iß+Ñ'$ ó,…—Ç'Ñå0„U&Mm½ GðNi.¤¾,ìÈÈt[ˆºV3D–H][‡kÍ7à^ Øb6V,¨ô%LÔǬöà— q¤¾ ÃlFŽY²ý )gƒÝZ…k½So´º‰¾¦¹X$½ª¾8ò7àöXy"#Ê!Bc˜•«tÉ£Ÿ <»¯lE£iöÄTÁÕPž3²e–Z±v9î‘aOнËX+ƒr(ñßGQ{è0Ü£ç)§6þäØsš),UÛByqÐùŠ…Ï!wé¨ôÿ……€äªÁb|ŽM^`)•z§Ói磅–E‹¬UËl³%™Á¥ÃâmJÖLÀT×:N€°a?»W ¯S é”@-Ñ3ª ¼ÖùÐnJŸKró7jþ®wºÚ¬H4t˜s¢•=’pŸØ¹'u,+oý¤vÒndcå-É:}ÁóèTž‚ã ËY\õ“f£ÓÊM|Y@½ ʼnÝżÉ.\Kñ'ÔOÚÍÖ‹3ó®uï~Ÿ|UZ€”6`tÇ}!ÚÖ lϺ[Xš`Zq ¨­Ÿœj1/ߪë#¯ýa;œ¹M¹œq¶­-pvÄ,ÓÏÆïžÿc4Åœ>–½(þS³Þ ùðê¹óÿìü?ÛæÿéM潵Ĭxã× …úˆlp]ø `CYcµ%Á±“ù%Õic.Ö|lDíñoÿõÏÞñ¿þ)á)>pèLïÝ5‡wM·Ö—9½4$Ô:Ž}LÊð´dé4yþUvš,YD GËùÔ†¯pÚdøžN9°—r?SÎð°UµOÕè%yLßäe ÑeaðªO¦‹ÙüÕ{ë¦yÍâí‡ÞùŸû×Õ{w×—×ßW?ôèýõòæîíþûøßÔ#eLõ(bU@ETÁÕå`Xôÿò¹}Þ‡ –þwž+ÝÈ=Z %€ ElË«r{b ç½óúÕaïÃU¿ Ý]öUr„MMú9ska²zK¸ÃÏ"Ûû—«ê`x×ï}’-ö¿ÉÕf†rUµ'UÊj÷‚-eè©ÕËÕþOPÏ€Úú2k«¨s£D%ÚÂþÈÓŒñ}Õ\-ª÷<³þ>T{Ÿ‡7ÕÁÏ×ç(¼öwV¹Ñ=%ö_/û? ©és.¡¶ê˜tEÁKóV‰k“ßei€C@:Õ±íÑÔÆ™åÒ΄ݵ4›äÕÍyïêêçêÅå€&0N,˜Vý;ì²aï'hnÚ#ëô¡+¥tEÏQýÁ~ÈÑ)Ö|²¥ ý¥Õ¼¿Íã}íàŸÖ<„îÛáÃåþûˆ/3ÈŸ”¢ÁþÍw”Ä…–– ÈGÿf‰òùi´ºJÇÎõüÜY½EA_8þ…æ‹2´$ÓÅÆD¿‘¯zƒ¡".þY@Tecñ"ÅV¶Œl‚úežæ M%¦9×ýŸÔæàŸ¹šjb·KêªÛTà‹LMXÒ• jVúCºˆÙ©ÿ] Qf1&ñåõEÿ')?ý•Qx9 Ç‹bFìû·ÜêíÍ€3$F~] E¢öÈF‰ d»ÄYšö÷iˆâQ@!æ’AAFIHšPŠGe“-#¥ögÉñ>)8^"¥ÜøGv±óÒ"G²£l sgÒ3±Íbž¿sÐ{­…Ê÷GŸÎëË œã¾©±|U•GG`¥ WDxÊEnAõº÷Iiý™·-ÜL˜Ðn ´‡[¸E<`aÚÆ]ã·ýó@+ý2¶7™ÐW~,ÔœðqU»*¢g<¬êØ©Rÿt çîToþß9oóJ,m ë#[ð\èglÂ:(¶ç?BŸhý¯|‘¯kà}½MíÌÔ@‰nÞÍmÿ®ço@òÏMKjQ°!Eä&¯ñWáãÌ\^Õòú*c+Xÿ Ajnë48ݲ¶(_äkæÒ<Ç‚/à|wó³r ~“±-Q]¥öQTçd>›99ÁŒœÁ|œØ®HÎ8µŽ5ÖÒñZ®&G^¡!òÎèÎÚ {f9«el.?õo>µ¨_“.ÎÔÇ5n7Wˆ[ú*c£w#®EŸ0ÐJsü¿sµÅ‰²ß^Üó­ø”QàØ‹vP)r>qEÔýðâîæVÜýÏY¤]šî²ªé¨€ÔÃÞݰª©%>üeîVDß IxÿF¨ý™¹9Š3ª1ŠiR4Eù*wC"î$6¿5úŸ³É¿\y!¡‡Ÿ$)ü›[¼ðå$bWCù1“l8jI3Ç*8Q‚ß’?öB(å×®ƒQßfh 3“F› ™1Ô·êçiT6a¼o0Ý'ß@w5ÅÛɆwŸ¯ÏuKYè«\-eþä#1çí¡ÿSÿãh%ë]Ãæø"CsRÑ>2&Q''·goïsL×~}¬t«ögö–æNˆú6ŸRóÖÄ嵿å¹Eˆ`ý›ìM ÆÞgZˆRÏ×FØMcV=í¢Êª×ÿ.Þº¬8±QøÅ¼ÈIQ¾“¸0 Äý’·ùI65g‘-º˜ð}Øße-úß¹›À†Phœ¤±Á:%Ø<ýל¢8HÄ‹ŽBîÎÚð‚S±9Ù[J¡RºÇ5*hJ÷³Šð©À·ÚKçŒh5@G _ hoQbcBíÈÒLnŽÙ€~¼þ l@ÚŸ¹› _ÂòÓQK ÏÿÊ,yb9¡%Zø:w‹bœ Ô Åÿ©ÿµ]±×’]»¿ÉÝÈøv›ö.Ùþ—Ö„$ú—­ÉÕK :/’š§¹~b^zhz®L<Šß‚´»´|‡×Í¿£ü¯‰¸¤ ÖFù†’ÿU#ü¿v{—ÿµËÿÚ¶ü¯—h½ˆµ$l?`”Í!š”c £…Ågƒ•hŸ?¥òzÙaiƒ¿fZX¦NÍ™.3´ë$ÉA)#w,±KeÂUâöTbY¢4”?VÙëϸâ]ý}…ØC÷.¦e- &•Á¤¢ü3uZ1?²@3¶H<â÷ égK€ô«×šv‰,?‰ý.0ý^œ¿ZÙ®µjYöï D#cÆá A…f·•ŒƒF[&Û¨••:Á¢á²ÓæÆ±ñy>µ¿¨èheº“Ç4e8 P »qSîædébËWÅã8`î3Bì|±¬|†%Șs-ä>®ìÑúd+QòÚ°¦‘‘•×èƒõ"ðMg:¦!c>*ZËL;³¥¼D0?Ieð_p‚”n/ ø^D/â\ÐÀïooQHB=™ÏX),OB‚È…ÊX2H3IýêFˆ‡;&ÒØã·ÄÙDL7D3K—8~[ ÆcQKü‘]©C«¥àF¼xrÜ/ÞñÈ™½;#Z^ÔöwÓ§výÝùÕƒw`÷}7ùÛÔ1ɸƒoºpfÚÿ]|ðûˆÙTJ£Ùâo;ªVÎv_ÅöSí´wr’Ú·8®4¬o#a4 "é ìšHH„Ûž€$½Ž\½Öj´[­X9¸©ÂÁp, ˆh¹¸Ð(†ÎIJ­àtÞì?Ó€bas,—nïÀžWE:ôÙìY|>„_(%û,Q×ÃcÇÇÇ•½?üALCÞ£Hà±rqJÃ\ƒluºY)G>1¸4¦}åpÓÜÿîÿþ…æãwÿ÷¯å`©d¸Ã&b©åÙƒ2à™A•'ÍV~<³8<©ÜPd @W"[w_,¾!¾\0ÖÛbfsgÉ9·1"§U³†äå¥P§Èž³Û×Á„«×Úí–J¤aÂùŸçößW„-¨¸ÍÅnx&?ºª¿X³€l¨ûž#˜¨ÉôÏÁbX2lºx‚ˆ/ýܙ͜9ñ‡·¡®àº(P: K0ˆ'^µsÙÂSl0[`%gÈ:; º×ÁóÓó6QGÿO½ÓRìÿõÿ€¯ÿÏÎþ¿uö‘›ºý†þXçùÐÿÁø† xH0õçŽ Ž7ç§$꿞a_Žêšü˜¾Êk³ u öz·—aµÛÓvíð¬|ØFesôgl&Ø›kV®‹gVµ×7À–S¯ŸêìÊkšÖYŸ ú&in4@5¡.‡Áº¾¼’Å”m ¯Ÿ¶j_½NFr˜žÎyð‚Ô09‰aôw'yiaJ&„ívUʨGHÔü#nÑWøP*EXpŽÐ€ÎõÁô™(K˜’à¥y#gÁ¹Žmqd°µèá¦?°¸zñl4Ôû/+o÷Öƒ9/ƒa½õv£–‹a$[.H/`AKFë_Þ"u2ˆý7hül[Ó1%g{ÆÜ'Ê`ïw-åW#¾¾!þ¤göæ.¯Q£¹7Ý_ú¡Ÿþñ«±É}ŸÒ$·ØuQFå€^6™‹ô‘ZYiöìF­ÙÊlÏ>Wç¥?«ýù³"3Ž,„uÓ’ù‡ð…1Ýé3ù˜$ñÐ|̼J!Së«5­¨:¨)––%Ñ—@çµ;ªJ¢/Fµfmæ&ácñ8£Â]ŽºRñŽ,‹€IÏ a5¼Ï¯CÂ\”⨠õ’ G™Ë‡@Q ú3œLòú ²¸/Nê§Œì’I»æ¥´Òć \ô&õà›„?‚kлø+†íçÇFO–ËsXÓÅãr¹°lšˆŽa{Â]¾¸äV§¬ã…ë< ”ı¡óõuìœ4íÓÆK;vò'Ÿæ\4yœ ihrÙÖ×&“Åb$S@’r@cäK(¼€¨y€Åâf‹VDò&)ÄÈ,fÎ¥“&,íî·O8”ÙÀRÔ.z}/Nºý%—+'¤·ÀyãClî<8ߢÿ'ïóÅü?ÍZ;àÿi7ëÍÿgçÿÙ6ÿOÌíö»‚&ãq BÆáÆEĜքE_™ó‡F |¼¸¸:Lð å IHñÈ ÙûzÞ¡¨1_ÓQÕu9½DÙ‡p­dðð”á@ŠæÇÕÐNT¢[)T+y˜†Ô#Ó5¨Z€Ù‰å=_¢.mÀ·Ô¬·š55ökMßR¨…Ñ'Ù»4§®R¬½RΨ;íÅ x±\Ë[M—¥»ª ëá`ò*®ª`wG¸©äÚhËÄ·„ÉWŒ³a‚´cî8â\VhàÃMBÁ ø¼¤k(¿è¡O—½'åKõG’m2ÊhvfN§Â³U^c2º Cí ˜c}XRÆ|®»ÒÚ'VN¾Ö}@dB3~Ò”âOlÖÛ-_-Ÿ˜¤ž¸\#² ݘcéQÀkÎ)«)ÇsyläZniN_L÷ÏÒ±ÌdÁ°òì g>}–ÝçXº)xñˆé¡ zÝœÙðÛq'zx+°}ÕÄ‹[sg‰r“j v”"J¾:ƒ"*;7E ጜ# ð/Kñ5 Jð7ëF·ÓÊå'˜ŸSu”òÿJskb gC%6OtkÉG‰ó "‡pK 9Ið æ[›¥;À@ÖÎékæï€Ýšê@}7O>N‹8ï¤^H‘$Ì ªqÉ8jEÒXrÐhÆ%¨hErŸdeÊI»c`ëÊm“&Àœ®£…HÅÈ]ÜI¡Ë÷å4ë'-¸.Ú—“÷jHût©)E°ÂIM»yl¥O)›-¦¨CÉ·½•‘”Í“ˤkœmHÒ©¹v¥ðÿàL• ^éy@iø_ív]ñÿ4þ£VouÚ';ÿÏÎÿ³uù?äy9KÅ<{Kk¶íN "o‡==™©Ðã½=kØ¿bŽPÜÈ—â ömNg=UØÉ“<*ý=.TÓ-Ø{û±~Q"TQ×~—ga}ËbÇá¸1z¬ëÇᦻ´çK×É$¶(@ºË==/\ç+¬Jæ‡XyøÁí5<í–̨‡QÀåêqað->žÌ%ÃQ×ä\ÔÛ‚Ub±,¢U– Û"2\¤…Œ…®ŽÉÎ{Ï!ZÐâ¬L´î:‹êr…×ðàqûæö5µþˆ®Ëþ tËš`>I³žy60¥Xbyú†W¾›”igåuYõr‰ëÌ2œ¯»ŒøÇòL­b¨=l/+›]¹‰–“NyUÞMâ”|p@€;xKAÐ1ÝO+8Lyžª©úP0EP~"Q{’_aÈ#oè…«ÄužR>²(A­æiFÆé²Q‚‚CIf5àÌ5҆䯃“4e¢d˜ç%Ñ X^Y|‡<¥Шq f/—A?‡…Ñ^c¡~,U.£P ³j.áöIó”ÆÁjµïѺ>[,ŸµØÄBó=’U 0·e¢©•a½›Ï?6ÌåÒµïW oz:vNBoO$˜˜2Ù—æ‚áSíø@޶œ¥²žÒúJaE–H)g2 ª)®ÿèʱTƯÈFv#Y¤Df :6ÐàmÔóïˆRwŠ?z‹S÷7Z«n+þc@f°v–öÈc©$¶?ë˃Á î%‘³Ÿö$áÊö”ýrºõ qM™º$1[:ìÝîj´¤pÜê=œáÅæ ŸoÆkH„פª <’yþ`ä防IƒšH­:Ê"ܦ²oï¬⻌Q “ô ó/èQüÑÂAàt yöYLâaäï°Øh^¢Â—¥ºÎ“ÁÎûÌ +¼½4á+YT~Ò+‘fæ3¦g´ È3u3³_ÎLÖLÄ“œD‚؃¯ã†mÍ>.-!Úi Ç,:÷~ꌾÐfœ\÷Ü–8\Zo± ³êÐÚ Ý23á kêËWÛŒ÷bãË>aº×Ÿ¯bUR—s¦ÄFˆ¸T—¤,Ϋ)C2ÞP‰°=ñ^¥¦‚ 1§äžÅÔf‡šM¶î­õO¶Þ4Í¥o¥Xæéa.@ æKB—ÚãÉÅ/ǺN.¤ +,{ê<©ËklAA.焳%mQÈ< 2QÄ#âý–â{–ŽržYXîÒ´‰†s¹q%ä‰ÄAÝc=ë’ *©ØX"‡$®l̼ë‘8ax<÷vIÊ&ÃTP:³³‰\‚÷ëëBÀ¯x»ÒaÑŒÀJð4Ú,Ù8à3-ì± €©bÐT]á1à«¥#´–Ĩõ¦.¾Ì&Ï &)-HWê=·žŠvºÜyæÝTߨìcëøˆŸÝ¦–`—bÊÿǹÿWÛz2ÎYN÷¡¶31•M2×¶LásÎj>K‹Ù}T~2¿R¨G•)I¯ñf9®&¸17e`5¶NNš'\XBÑž9Åä!Ô ‡·)ìË#ÿ¥m–ìã%õUÎ!cÿ7k=ãíËÿÇÿnµÿÿýî3Ààt󑯲IÌKD>4©Yå“i·p} #þcåÖÑcs\«ù¯ý€±Œî‘qgÎÇ ÙŸŽ£^«uñµvMáá[³ÕüÞ~€«ÙP_—´‚ûBØ}ãØØWš%T¦Ö*æû×›ƒC¢÷SebÂü"ès‹Ø%m Ò8Ï–õkÅHøïŒb…ª0ï”"~eæ…ƒÅÊ{dCÄ!!øGÙŒŸ-ÐJö|ߨºÎÒûò ŸKsJ_Ýâ þ½²æôïŸÝ•7zDcýþ÷Ž{oÒgªlÿôÖÜšqà·®õÇ9=Ö›#¢¡ó5[¯(]òFt@†6 x@•iIËx#Ÿ:ÜŽ†—†€Ú:9í¦! þ*ßB۵žçÈÆ<íTœäuíKq΋£n<£‘9>^HµÕ­7Tv¾ˆÀ<á“YðP[ÝF§‘õrî¯@‡MAÛy”3:ÖòïBìQ™Þ°HA®ï˜ï»\´ùjvo¹aƒ¬¿ÿåÛò8)§_¬bd”E*>žrêÛ,±3³„M} {îj¡ô‚Ì¢·¥(²l«Û>©¿8àÚv©¬Qm3sQ¨ìSï¶š\¡|±@¥ ذ—QÕÞÞ]^S*V^.9™ä´ƒt…YcÝÊñ˜«S²—²Ú:m¶;qÑ~xK-tùb=?Áä—'eÇ}sØ«¹î†ƒƒ¼?(2Ð@GªÇ¶«‰ôXû7ÐSìX]•ÇjÊ䟩Þì)÷f{[à—ìË/;›–Ì—Á—ŸYÛVDéÝÜî__2þídγ<ꔘ†ÿÚj5ùßmøwÿ·‹ÿÛºø¿þ`xwó³„Àùâ9ÀI  ‰zBûö%±ÔÃY›9âcÿ8ÿ‚¦(‚$¢s¢®sWÊíÝ͇@!¯ì5C#{/g¬`âÈ­5&¥ÄºÑ ì:eÆ ꤸA^Ÿ§`m€Í¯Ñ¨w:¹Øü’œWJ÷dcñSÀÇÐ[³N¨Ý`rÅßy+šW¥àAŸž¶›×ÀKèÏÈÿyá-ñ•¹~ôVh@"%Ätäš“AAG:m`îó[èqeo‚¬o?wNrWÖÞ^6§?‰õÖôÂí”Ó'5L‡ÈéŒÉÔ|`œdÑþ½!/éHƒ`3žL¯²'î±ÆÉŠPØ‚Ãì½ðÝa¦KCÍmŽBÀ!J Jeå8teOŒ4Ã..2 Ýëx¾ y§55{<‹ç+ äŒ7,MíÑAS žàǰÔÅ?‡Æ™Öãl>¸–÷÷©p +*¹ÒG³é™ñ#A†Â.Çül?õÇDVôn b4Þ¹ŽƒÖž•§ÚìY%·7ƒá÷w}8ÒÁT¾ÿo„11¡¾ñ™‹ñý™_‘kÍX°òÍ;3üöI€}cì`´³dŠPF­:£ÑÊuèÀ/:~ó™AÇÌjïü¼?00¾_i~¬é"i4šµSÍFá"Q´˜ˆw¡–аšS‹á s— vx‰Ž ´QÏNÔÖ›Cßò”(×yš 8Àš•ƒRÙ£ ù»Ç¹y›úKÊ# äÙƒ "ç„·–=z ÙjÇ2Å©‘Xˆ™ã²]:R˜ãBaoy ñ™/-ñæxµˆ¢äqršDqRÈãdÉÆóENúð)¦P·}Úˆ5¥«»FØó¯Î[æ,ðMÑ ´\`×zÙ¼òŽ}`]yT’‹·}—Êí™ã™=‡†»Ü>,Êá Íü k…áаݕôâfäè¶7üAâú÷–,ÜáPXmÑÁ?³gØH„…ž#h )¡múprÃÛÍþ{z‹Ä—±JÌ!W¿i宋m/"Ö/ä:H޳‹¸ªlÔ³Q „…o—!ãU¿¨+A3ê”àMÈzùÏåP¨æ-ð,èjzçcðñ_Õ õ²ùÿõN£UØÿ[µNsgÿßÙÿ·ÿ•Cøÿî,ÿÚ­5À›,pB$Xý}5S]  g(Fvnõöææªñº®þ@¯iõè¹m±ùÇŒHI­¼UDV^[¹¬¼Æ0uc|ý¼zè½V·Õ} ³~¨R ÍæðŒØ}ôéÑb˜ea"“@,¸=ÉŸ„g£ug^MOZ¹_-‘9GSP Ú{ÌÉYÍÇÇÁ^ ‰|¨Úª²)ŸÚGáüBv‘ÝSŒÛÔÉ,w(«¢Ä$ïÔ)ñO‰ˆÙ R¤Ä;doøX¯áÁ)ÅÝP?í6›õFw‡Ð5‹„öŸÝÃy ¶RÍ­‰3¾iºíˆ–7ijM¿ãÈŸ3wX°²j-ÇeAs_®ìåZÜé¯D.D–l[s¶å¨FUï1½€¶[G&L¦aû™JÔšÝ׿Žfe7k„Löã0)9£ð€…„­Lô\ÉDD>ŠŒk‰"=Íù+‡ÆÇOÂ5'KBi´”)L^NœÝÖØ#Ó—kÁÀS#§ß™¬\üVÂyÅ”ªMì±”¼Zª½HZúŽ(7¼¢âøæzgkÚ‡·99¤.5õ4ÂÉ&‡ÙÒ˜{^Éce}®©OD¡)´¡ŽÑr"üî!®Ø„¬…¹ÉO‰ðEó¦D:á.W×ÜYŠrrúÞ<ã`êÚ÷’»ïÝÜz²<{öŽùþ|×a >.¼qªaïGø¸´}’¯Zÿ?—Hɕۆâ&b›Œ¦€£=(âÝ8ß?B÷/28" S¼d˜` }UCÙ£˜úFéLØŽ8ë¿Ëuç"òâ’šçÒ}¬¥‘˜Ø®·d=?ã™Þ²8n ‰ï<„uæîGo¸Ab\»ÂÍniUºšü‚Üóž¿ Å[3ç×¾àì=éúLÍ÷þs0w›¡¹«l¸ƒ0&²–À=Óù(sÄŒWöœˆƒ+/p‹^™~Ën#[uª`Û7ßßj-ú<ŸZ,·陉¢“fãÔøžz¤:3«N@÷(¤•õöâ™3ªŸz?U?Þõû äà-¨¬½D€„zÄäd%0|xD™ &Î ÊùB¾ ²~?òI…ÃIÝD6ÈÅ´ÿjn/Ÿ 5k5g/’ÉËÜp(^-D†¢2%h­ÈÚAB²·UI E‹÷ù=(sä6=Z4‹æLvö’z‚FËOB8nxRZLq9îcé:+¢Ow•“#=uèŸô*{<ý5ñˆ§îfhI„ ÅÍfÝTQè©n£ÛM-ÙÛlLI¤m\,³\cóÄmä6}§ å–œÀ±WŽ­…EHì¡V •ð Eè¡c¤ücrÁäl{©:™:0bl%– w÷Ñ,M¬.”*þãŽ]1U½G¬‡k^¶”-–Ì”!Yñ,•0 øa5ãèrÀŽ“…šÂ5.U¦@pùuå²¢E`À$sÜ`ØæZg£èkL¯˜L{3¤ÊÒ1ŽÑ©ž6ÃÖU—Œe:\•ØeÕ>‡µN{ñ’%VîëWV½_¥3Ÿ>Ëz‘ñ‚UY­é„Dý®ó¤m{©#•õÚGÁ&ï6£«@ð:÷È aÆÇ ’B%‚îåQ•4ñçRÉ+@ú¬Ñ8Ç @^@ÝYSu4Q¢ÖU:µTÆ‹4e35:­F³›‘ ¨/èthgÿ^Y:ËŽ~õßát;¤"D€‹`[ÙªBX´²²xÖT¶YFˆõ£8ÛG£ÉåäeÈ?üpg×ú6É?²!ýÆÐâûk(³NžeÃuv˜@›´Av¥>ß§ã9ÓÕ |®­—c”ÉßGú楆îb3*Ú6ÈÒ|–Ú$ÓwÓb²¤²ûAÖ#‚ß„WK`t²œ@x£åëS F…üñª7¼Í2ÃIw{Üåù^¨F.† ½æŽ5F¶Â»‚–!×Jy,”žã¨cv»ÛíæŠwgÛ¢ LAF{|D1—Ãiv„LìÓ£E!\t5’̜̔^3þhÔ÷%ûÆAÝØÿëÔÛ3Ûõi6êÇív§ÕéÔǵÃÃ#š’ûìuxȯþ5£»—ê&†‘²–ËâLY¯ÆÜžæiÉKÊ%¿W7-]à}x=Bä})óþ6ˆüæoêþ?~å=ÌÚçâKa“¤¤ÂÛû ª9Cኑd.:Ý‹Oc(t2Œ;FÎ_¦®#V½¦v “/ur"RYä3 >º­fãÛ%Ÿèì9›'ŸiÀdlÔjëÏÄsÏ(¬3* ‘%ø6Žu¦T¾h}³ï¶©ØÛ\1$q°B¾-bA´ˆ¾I©4ÄϱåÔ5¿Wþ˜Fq^kùcâî~Öi)ì3ìTkF1`•Í?³mâã²¶‚ç%S\V®Èð€†Ý X6©pwQá¯ÿMìÆ,ØÖd( ¥Æ‚§ó¿ÔñßíV½¾‹ÿÞÅo[ü÷`Ø»V‡w½ëA²¿…Xðຖå ýŒ`„¡€‡„ÐïuËRã¿qçµCÙwŸ>]_1ê;jt׌쳜àQ]»N¤·Ú÷ey‡ºMž…CûJ‰Áß¡Z)üfaaŒ¨R¥q?uF_ŽËƒ3~ûDE¶^3¸;ÔYe Á¥D§zÊŽ•nwkÕ ür¡Ò» Þ˜ ÞR¼ûµn£ÓVï¼ÞýNq/j}Nnä\Žôœ/8ûXQ¸iÛsŒ†XÁ‡iòªuéá2—ØäqT»ÒÇ%ݼ#fÇ+ÁTk´OOµ\þ#{®ªœêB5Lpø/o%ç=ܼM4f„Ô˜ò«_ß‚ͲʜyžqF¡¼FókuaÚ.:~¹7Ý_ú¡Ÿþñ«±çÒýCé{È-69+X•1žÙ¤.ÚKe™ükN½{’bò—z¢·Z:l3œ¢ˆ(a{¨W^=)΂¡áŒ3aúLai<’È9J(;¹K•ž<¢Ø .åkñî7á´,ü®ˆ¥ñ SŒ’¢C¦ÖWkŠ¡ÎÈ&ôH ë­Hc ƒˆL)續smÀ@µN:)2B^òqyBš¯ã“ªuz¦$W‡”f@®O…‰‹p_뻨¬ ‰ºTa}Ù^™st¢œ Ð-ÍNýÅ}  ÷Y6<–q±¨ôÚîn®®>ôÎÿ[_`kËScP_ê5_^«çöj¼' XL!¯À²jJ½ô «½ÏÛ”~׋( *£ø›ó—÷§h9‚Å”î·è sí}âeìýe£,0Æ6ÓÈg¼ýõ3„‹^ßÝfÈåiˆ²\l»­÷§Á·ÿæýdºd¹ ˜dû­Ó¨·ûù_ê'ýgÿß:ûÿ_®ª?öî®/¯¿ÿF`¥§U̹$üm^‚é_ÂPÐÄ š`é×.ª’ÑJ‘he¼w_Ó  ñšöÿ@Çåå}‰§ulÿñ£QŠ'Àï:ßàï-eZÿýšÈîÏsr,—‘ê²|§M„¶T«7/œ7Íþ°†üžÏËpŽß0IFÖ˜’¾¯ØURÑO­º†(ùFøÈ®]ÕÕKjô¥)pˆà„ðEþ¶ì;óýQl¸£þì‘/“Ôga©Îo®/.ùõ)A.YB&É‚OÇ?¹ŒLdÏ8ê1&uk8u³åË‘«@ ª†–€áï/”Îã‘Ëã³&ÆÖÄ be t$Ñn úŸO$5”3Ä݉9²ƒ¬ûž;B8ßLÅI¶þÁ6?jnÎ+cêÕq½ãu9r›§õ“z#.\0û2ÛìM{+oØ©ûë0¯ÚÑ©„«u¾½7×E[ĶàvuœÛݵ·úþoŽÇš¡UX~«è…Yß"ÿwÒlâÿNÚÍöîþ¿»ÿoÛý¿wq¡¹.„¥úÃÍÍŸO±€AÁÌÆ¾¾ð¢c¶Wê¯$£Av¯Íë Ò&Ú¦ƒÔ.~å0¨1*ÈحòÜœ¸e•hhH”†Lº[<óˆ¶B(C$±±0U’bÑ‘·XÄzó¤¡S5¬Œ˜Ø½Ùh£^Y~ö•^¡ÛÝVí5Âcû12vqlQj(ì8“`úøI„5G UØ]KIÛA¥nTj& Ú¡Š+"#®„i%?5 @MåÈ8¨³R"F›'Ív;«}«7{F¡e"pž¼Gg5+ÈsE–Ê‘ MSÑMp(XK½Ÿ1Z”U1üÓ›¿&”ÔZá§0ž§f#WøiJ´hâ6d|÷æ`jÎîǦqphP¢¤±?PÙ–ñy48bð“"zðÝN—¸ÄsH…Qxb+6®zŸ>\ôŒïŒïÿnuûÍ“ófýákZthB=†Òú¯´pÏæIK'DM ÷,´ZȆ8K~ÀœOXÃÖ*kÆTBo´µW©DÚívþ Ê4<³ØáA4'„E‚nŸ9 TX”ª’›‚&Z¢F’J èŠUV%D]bÇuõë.ìrí°ËRnåï3^ ”ÂËGPhž´›ÓNÁPÄL·—ßoXbËÂ6…(f5<äò $¬ˆmð©h6¯2½)2þ¥ÝØó­ýbñõf£Ö Æÿ´vüo;ûÿVÆÿÝõÏoî..¯¿¯Þ~ ¹®C13Æå»ãNüœýZ¨ªéˆ@YÛ۪Ö5)ñ€ÞÒµÌY8ˆg0¼ë÷>½rìŸ>¾ëÆÿÅt]NÛ}h´ÖTG ¬È?¥ã´è?eg)9P©‘LñCË[D3‘¿`§q„'ïK*˜ë½…Vy&‚è•o‘oµº'õf§dÙ¸ˆ¢‰y¸‘Pºlò—Gšñïáp¨¤Ó+úB¼PœžíØØ¤? Õ®5jj&n„?¶Í1^Ñ-2O‚º—Ú^À°J)ù Ôø<‹]Oi·æ,OÞ÷¨¼PÅq‘¦pŽ 2N*S;e©›#EÃT$XFI •Îü  Ê—À3¸«mU™= ÚînœQì¶lš‚l¡âÆ>‰c¡ƒWD?džÃ/¯,F«Ýnj¡Î‰Œ"Fû8oÔÜjuZ Þ‚MÙœ#F8xB(+ýõ>1ËZ+¬HV|þ]¼@Á¢Öµgp»À`vÛ'Ün—"*Ò}èP;/ã¾ØM¥u ­v§USÔÑŽ…ᣕa7ÃûG†íŒ“kù|Iœº.ׄoÖˆ‚6äÆˆJmÙ¢Ü̶•¢Þ‹`Áå䀤Ù^òe~„–×–¤€0[Þ.ñã[ÈÿÀ­§*‰½öÿ`àjÿ¹ÖÙá?ìü?[çÿ¹º «½áðîòÃçað-ø&ãñT/@¹á¨|a‚Ü;ÊrÖ¯ÌùÃÊ|°ŒƒW‡ >!]e0º‰Ç‡ÖWUœ,ƒ$DhØ¡ ÆóØm†½Êôÿò¹}ÞEQx¬é!ŠïÈœ>¢ìúxtÔ0•áA t¬<´ö¦=HɃtÇù…5¦\NóÇ&“ä8ÜHG­Öh–è4 t^¶Ä9õQþ| çiŽWžoÒÉß>é¼J~G°»Óíñx9%Jºà´$ÅìŠÆVÜ*|¢ËXû}~©CƒÅ äK7ÌÆÚ‰ÍéTF«¿´K)ÔžiB þ:–þõÛWÌéCJn£Ÿ&œô5¿Ïdš°‡Ù‚5…-ü´:ò¬?Ÿ]ýµ<èkúBÝšÓôOO6é;¿€5_l þ|Hé³ýX¾(O™Úï>ô“¨Œ£é£ƒgTõ’~éŒöÒ*³ßi 9ƒ+ O·ìG™yÙù%ä uGý–܆çSûÞÃÓÑ[ÆÄÆÌ´/OsLX ø‚ŠÜ»&\š=6 ª©.¥ÞÐXú+(\Ö8¾-ø2¿#hb$ŠëÛU.ISJ­×:§ì }©ï–UöI é¯`PçûpXàòji5O[ÌïG"¹Õtœg «ž3úb-Cãi èû†U­A´â¤Ö*ix£J?­#ôCi£®¢U«wp~n`°C•µáäÚnt×óÙ³¿n?=¯³dý’„„ZWÅÇ3TâI³ö›5Ç0\l§‰P¥[¨‚Ó6iuÇÊßøPÅ_Þ\|8W€æ ¥¬ˆÉ_o´ˆ>·øH l6[¢³æ@†J=i¶Z%Žc°üvý»!zsÖ&Ü*.¬á›Ô O3Óüè•1AÌ`k:µnm-Ý.±uÚXŠ„‹íž–:GBtkÝV z4ˆ½´RG6<&îÒFcÝUªíiÒ<->²E2æ5‡6\.ìðx *ml#jè6º¥ n3ïè6ËݦÒ"ôë!äѺë•٨׻­’ÆW/¸M§äÖª€sb§„v\s4Ë÷†þ(¾ûeq!ÛÝÓ“µ-\d§Ik‡ùlü•M¹RJî¶O׿^…Ë=©8ny»}¨†n³›åZ¥„¥(|Ý»•~—÷ï"f ÃCƒu,Ó=30_Hš.4C6#Ÿ1 Ú’!ýo×ðœ™åÇ%‘{‹W€ÈK‡J§ }½¼–Š3½§š7ŽÇ¸qVÞÊDŒKš3zd)І`÷&ð+àK§o?é,ÐîI™ØÄ[†!žq¿ZÏÎÊÁè/­²¹‰ü˜›)ÚW‰Bž‚±íÂ,p°y,÷„Uß?ƒL"zH¸T“#*©â³ÛσªW—îzw?Wo{Ô¸5Œ±¡º¦"`efÎíÅjjÊ@%ÊL‡ÞñƒQUÂonÁk|ûñæ®ùýµ¬uÐïÝÿ@•ÞòêXR$c{æó«íÑD`È)W'ðïâïÇžcÌ-k̇S±*x«ÅÂq—~T *<LJ\ôãs ‡ì©Åä}ç,–ï&ŽóNö‰èRv:côhÏ-üãͧ„ê-Ž _Ù; óèÙbå=Vy#ª sùhì˪öõZ÷Înšð¢ã©/«·7ƒá÷w}lí̯@ÑÆjÁ+oOYˆ’¢<æ½óÕúÿV*Û‰s÷ÉœhôÈ™Ýc[– àDbp°ˆN7ƒáÉÊ)M®dã«m½ÁÅG ß´Fsûï+ŒiøbCž÷‹w†5Çv¶ú`lMfÖòÑÃÔOÎ`áAÓgÆ™9un8ì{”¦ê,@¬_ô#ãÀúûÔ8 wQ?UùB~C#rˆ€ºüQ\ H4vÀ£øÓöo•bUß|ÁÃD9XYÂ… ê ¾òÝB‡}ˆŽ*²7swÒV‡g/5n0ñ Ô=ÌwM`ZœWÏଧ@86{jÅ. k9z'Ìüöòxj{§býf{-ÓˆJ€­®Êš â2˜‘º¶ª¤ ÈG”Ö¹‰PH•¡”{]V¦qîŒöÏZú GÒשð/ã9¨”+­ˆ[d¹´Ç•­0ÉàÌI °?Õ*Ù™“3ƒgo "GT?Ç.h¤ÿ·Ï¢÷ÂñµN³Ý à6;ÿ×.þc+ñ?‰gñwÇþ‰z7õ3•Qøuq?Ÿ–Àø謭`ýÞÙ7#WÁ>i)æ“jy]šojÖK‘|w;§zë%H¾êܨaM`¦?3‘h3I´RÎN¼±X˵•UîŽlœ“7ë­î·M6ÎéŽj<>F¹Õi´ 0«ëìwÊ3žº«o×xùãRïm ÆÔŽ]¼œûÿj1Æ#–ÅîUÿ˱çe‚@¥ä´Vàþß>9©ïîÿ»ûÿ¶Ýÿ?ß^`~Ú͇?õχƒêŸn.¯¿ (ÇÏ©7 ²âƵQ[fÐ'é©ÔPƒnn.>%¢AqâMeuâ:3Žœ¨×È;opu3¬~¼»ùÄ! ¬¹ùK^Çz3+Ö4$$öiN“BþÁ^ÇÜY‚Á!ª›åá6j +Ñ U7Y$>S½žBÇâh\d#Ì"íz³Õ(ë;ªë²!EñWŠ€EQG勚8îÈ’´'YÞ _ª!t—ä—fæoÕ©5ÏIU>ãI»Îb_Œ*bD£ ‚öTŒ º ØÌH@¥ådÛøj[OUz!Žhã¯ð„Af0ŸWƒI±.RhF´õ­qfÏP+ éÄ÷BUØ­&.ìá´òùº§3˜ gar(oò(( J€»4¨ŠÈX¶ÿ8\’xÍ/ÈœN–J)hzQJr­ÓÃ)ƒ†Ä/J á”+ ”Ä ¬ßð*o/y9KGÔ ß4 ‡€M^uî§ô¦Éž>^p`"V{š’£ AM4.ÒPFM­?“¢•Í¿ñÒ‰P”YFhîÌ«s X_-²=X.½¥BWiCš W-°¿qÉ£QÖ ãGr"1í)‹Èÿ«qÆ(Ò4îÍ%òÉÛÿ°$”;jÌW³{lÜü%ÃLüûÊrŸ <ͱX:§ «Ç4‰"øŒ'‹‚óˆásƒ (ñ £Ûœ¼ kþx4¡WQPø%bo#T=Ívó¤“ÍZ,ŽH²Ùìlè ¢,s±p…K Ö\Å­ŒY˜}¥&‹T©} ¼P dDê -‘îÈ–W¥ T¡…¥,f~Tô§WEÁA$/‡kð˜=rdò3jmU¨R ÃIƒ-²eü•­1H­æ÷Îj>>bdô¼GϘ¦=?ææzqÞ£8`k2÷ügŸ!Î<…N€dàó‡ŒÖ<„Ôœ9<òÿá¿þ?ÆÍi’o@âMŸŒŒ£-—úIÌÔQ‡E ³àW1%dñ‡¥°ò4ONUªñ i ;à_ ««ð§ÞOÕ«þõÛ@™ _O߆“°ÊåcßA÷·NspíIL æ_<.…>¨ÕÑqž_þn{Ç;Ql^’Ø[Uk˜ib¼¼ {×ç}ÕÌ —T|qi‹ÙBSd º ~¤¶ð­ýå4ŸõÝ*–õܶ-§¹·1Sm;\¸!Vë#÷5ðÿÆcæj3IÝT‘OÒ^VçKnàÿo³Þòÿœ4';ÿïÎÿ»uøÕá]ïzÐ;Ç0˜êùͧO—Ãê77þÜÀÊ×Ëú??ÀXO…C5ÚÝ w|U],ôÂ.¯µ>ºMpðëL§÷ˆÜ&U› týÝÍÕÕ‡ÞùŸ©ó_0qJ¬éŽîèœÎߨÁ]ǽ›aÐÊp÷&t¬¿q•èüM„|À ëàÙÀj=a¶[ÍѨ† ”(Ù­Y^äF|µn§ÑRñ¹×ô 'tl6×pø…\îámâBNo"yywlL/FxZzÆØò`ùânC^ Ó·ø’3qîiØ&;®hÀñ °æô2ùÌð2®šÙâlñâ1­*öŠïõb†pÊ­ÙİXÑÞLHw’—µeã=hÎ^ÑÊua§Ï2ÒM®ƒ`èžs7ÉúSëž´ è(‹ó¨7{F%rĽÙÞ£³šÂŒ÷õ ,“#>Od!bXoK]£L™ˆBoÂD¨%þê.j¨(ÉÔ:ÐSs%ƒƒ…‘+[ŒâØ0* ûñÝ›ƒ©9»›ÆÁ¡q°píùÒØ¬è¤Âð7øžk÷¥³å€¼—x&‰ÐÜ.ö_ãàª÷éÃEÏøÎøîýýF¿Ó=%ÿÅa倕vX‰­ÃP|2ey:jÝn½­n:‰žŽ „’8ÆÃu ŸÓ²Ì B)¬DÖt—@OÀɦ–Í]R„ &ƒÏdhw:­Ü|9)YqCƒ.Z„N§¡‘d¹Šf‚µN~ ‰Bê õ é$ŠäÒMe89 Óº­ú‹;9X‹÷d:±ÇZ×µNÈcëW½6q5­O¼V ÆÒnÌï3žüµ Œ»j¼ááÇË᪱b‹)ßóQëž¶k*a´ç£ø…i£Ys[í‹ÉjÆ(ê„ M¯\1­¹\3AKÙød•ÆÎ?óïéÿ‰â{9þ§F£SøÚµÚŽÿiçÿÙ:ÿO˜Ÿnë}>>¡(@\{áêBy`hA²Y`/.3þœ²I–ƒÐØunCi>º»¹•=ýŠžð˜¯éԉ캜>ìc¸Ž§'btÊðìzTžÂÛP‰œ@äµ9§ÚàH.cÎeK7à iÖšíf½<M ¯²9eBÉp›ôÆ”î‡.ì6Ôàß—óÃdIìÑS3ÐXO¸·<¢] ‚Óô#ž{…vÔéÖo W®sAüƼ4¡L¹*˜%Á༎Ùy#†f­¥s€G8Øê§±#Ã,_Fžy`ØóJ1Kl¾¼ùº«Ónå˨㗉ãüª¤ðï« Ú¸ºÐrbÊ }oukšÿ;É\ÞóÝös.íün˜ò¸ã[§ÝZ÷áŽÇüóü¶ðž0TC—û6j{’sÁ!*ÖRñ祫RY1ªb8ò'w$"'I§3~A_i› ÙT‡ç×#桾Ÿ ¶^ʰ¾Ã0µ´Ýò…R ²èã ½ZìÍtºïGÝK„ñ zd©¿v — Úÿ Toc% ´Ž0ðÓ2F«Þ`˜.°Žxñ‹àºÿSæt÷( €?œÕ…ãE¡:öý‰ü—‰ÎˆÈË÷H4k†–%”Ë#sCøýz!2Þ»‹:!|CK Þ‡Œ7ï\Þ†€Uf œ ÚŽ°s.¼þ?e6oü?ÕþßêÔÛ€ý¿Ù¨wvöÿýëðÿûWýóá·aöŸ¥˜ýcàß>¦@ýQ¼]•@ôòoï.¯‡UÐåw?'ü¨w/n”_‰@ íšÖýPÿ¬iÙO¦µlûÚ@”B@=è³ЦR&•O¶ûþoÖhÅÌw RçÁþj`EÈ5íùfPø'ÍÖI»<ƒ>ë.qJ'ü‹8.É–yPó%¢S¸…PøÌé48ÞÐö|´ÌÛç:³?¸ÎjQE›WæWaµc>S榶ë—þ¼3Éë“ã¼PrºLgžã=‚íÉñ<Ë3 ´þ\à‹¶5ºY®·í&—p7.;Ä#Ê3…·(¯¨qÒjž6^ߣ6²ø… “cò¥ñ…€´ÉÆeñÀSúüw-Å\(pVBëm°¿¯fóܵãÒ|jµ™š°LÇ^„6~I‚J>]Š%¸]7×ût„F(pÇFy²Fí0zm¾9mx{]yBûcQ\Çe ïÁÛ TÄ>ÿºC{Œx]±B§”×g—·ZZÞjèˆÙ|ÇýÚñ,Èݩد%¤Ö†¼¥8;$S=q£Mè>hÍÔÕ†Üï)죨1=Cžñø€šÈ˜¤ÅÊ]à(PXú‚ø™“¥~­¼²I¦CqBö éåiuÏ¡f×Ô-jhG~we{‹]PoDˆ Â0ï¿Ç—ˆkW#Ž;rôtFž87%:{µº´PF^ »ËçÙ^‘Í.Ø s˜é_­¹MQ(˜Ñº$æm“ýß $ƾÇ×[œ~Pç›^¹Ý>”c3“ˆ¥)Ÿ–ÚOCfàE9i^fÀµîÙØÕ•#ÚŒUKE›æ=€¶\Æ‹÷BÌ ÷Äøg§†»Ž³ [„kþظÁ‰ûd#à3K·Ehéßé„v¦»Í#E ZS‹–(&áÒ݇ë]çºÃÓòÓEïœöñ6i3Õc(—?Ä7=3‚½Sähä4ƒ1³ì#µ¶I%°N ·Aá6Eç·##Ý­ÞÛ œ¾ÓbÇÖš£×"TÀjá0Ó ¯~CEÄDÊ?vVÐ19›À^ªN¦Œ[É…%ÈÝ}4K« ­*éË23Ÿ±®yññœ-’#†ç(%Yñ,URAf4D ªS©ÇÉBMùCªL!«ÂÒ•ËŠ!\Ã$ƒËè¸<AŒÍ,íèÛƒ5ÇOKGa†TY:›Á!(ŠðSG´ûk5K ¦ãXh,RúU›ø‚Z§½N-M®Üׯ¬z¿Jg;€¨3ßY•U­¤Àp'mÛ[;¦6ä–¤Çf‚fuyÞ½q~u30T õ{+¨œ˜É¥ ºrH¦®u˜,€Î5‘ˆ½ºÕøb=?Ú7Ó#uBÉéB^VsŠ;V&_ÇÈçpæ{ÞtØl`.Œ£G<~V’Ù—çŸpÓ£[ªtÂÝC]&ÖÜgu ª ËÃ#›ûCͰgI!Ï-t½áUÁ¸„‚V£G­€ÜÄ@E=;+cf>C˽GÜÔØ·]Œ`ÆæcÂq|ãü^•Æz3ËZ&Æö—^&éë$Ã$7aÞ ·r•{ìÇâ-/âb]²°ÈhSS’¯çÎlæÌ©"¾Y rá³Àv»Æ¤uWÑϲÙ×`iÊ8VènCÛ‚n9&ž,‹y,î—&ÂdÁúÈOÑÁ É OµœEÄ“4€Kó‘VøIœ³ƒG”BàNá¹l }¬nš‚™EÆ rb‚ÐÕž"6›'Óž¥V‘K•v}:0ƒÎÒcüURÄ ÏÒ‚T„´K„›'n€lÁÍaÒ4w¯ë)æûOƒbK0Ý\¨Þ`XIì0a.dK“5&öøšn£Á)Ø“ ÎïªØßÌ6ÖÙbµäí Ä,-FƒF†[ŽoiE·o¡Ùdß©S$öç…}‰ÛNƒlª2wcuãFœ"m+T¤ÈbT§‡nm lÜÁ};´ß'mÞ98#|ã+6U‡ºÖ'»SΫbÕ?„ùûÙñìÈÌDÍ'oŠÂ—Æ?È8s3²;;µÎÿrŸž½ƒ·zÁM(èåF¿dÞ…È…9di¾1S9àN­8`±ý©×ø‰sÈÑ€Y¸”x\íËb|õÏv .`¾=‡OBgÝKjœòϨìÃ|™Ô¨¯'Tý Ðr=á¿2ìþbbŠénÅ Ï¿#Ó­œwçê%™ï„Ùæ£z}ÁÐxÛYyS<êZsh§·ÂkfêvÕE~KÝ_ÏéMõMòuitŠ¢å>N:  7²’ÓºdC ¡Ø0ÉÑ3çϰù³"ŽÄ¡UærËoMÞÙâámJ àió',7²ƒ²» šÙà(8¶2oäщ©;³äZ…töQ@1F·@zQ¤ LŠV­yÚÈ )Íø9™Ø®·¤½)7qü"˜:}NãLÜ£ŒeÈ7Fÿ)gÉ€cSOŽIÏùܠЀœzÿLhoߨÿl^ø÷Ï|ŽÙsøãÊrÄ?ö>|²¿<šö>]Û_ì¥ þ:5Çpr÷©úýŸW®½X‰î•_FÎ ”Þ/o ÷ ¨ÎÖÔ½=ÿñ3qcÔ*Ó‰ìý‘@·Ëò»¨¾&:Šý¥uûŠwšÿuüI=t t"{Dv%ûSv¨±ß /¨KéWµ_1)>n²E΄3²ðËÔþbáà ¯Æþÿé¸ûØnò‹¿…¦%ÿ>jpØ œuVNµÞÓ‹¯Ð˜®õÇ9fwퟃXpüâÀçï÷7JüþÏîÊ㯬9õïí û™M´ÁҜҗC\_žáÓÏ( øNí&$Ȧž±Ç¿fí)Ex#4-3.Ï`ÇÐJvE½¦Êh~}0~y´0qê×DÕ7EëÇíîééi»Ûkóv'O1/þè?_ÿõÐÓ¿.úÿðÙGöÙsÐãXîßȽ®Ö8cw¥½n(ÂÔ•aKx>ëhDÍÇú~Tg…;HaWæÏTbÇëÕ/÷Öò e¿¼Uú´ö+þÝê5üô믕"m µ¥n4Œ¦ÑÊÔžJPfØ|åÓodQ¾dþbˆÐ§¡.‰Ÿ¥…d ÕäÿDö;èQåa²ÌÍXa*±=Ø‚‚:ƉÑݼ2iÜøÁó[òæà@?,˜Þ½VÁØ‚ï#6!©ä”­ˆëÂÐ~ä«V±÷ð½IèLm‡’:ùPÛ¤|, ‘–TÑ}‹ééÀ—\‰ð2ø¦&·„Ì{[ø¿ˆå¡ÙM_Vsú'ËA-^iÇ+_êèUÍ&\¥ÐI.vQi›*Ÿ"6׈ÓÛV#vÝ ‡@6àr"²¢üY™búÊ“biHl­Z·™F\ò#Ü‹àv—ö=]:,ò0R88É,׌£¢¶¬æ0ÞÓg´M‰»í»×?¯‹ÆÖªžh‰y/Ï8ÒlÕëõf§ãHJ_N-“…³âÕœQš#‹ˆï™S±Òt{ý„_`Òi5t³4:è‘fíåÍ"Ð TA8½P¥*°B\¥Ê˪Neˆ…js ×83QU~êݦÔ)_, ç8‹*…Uqánnâ1Øð­•…íeA–TÎQ×ÿx×üÐ'5½•‰5Öj4ê8Þw'ÃSCÐ}3}5>W”$f6â°›¥^ñÐ0ô¤NSÀ%Ì‚xWÚŒÇã­î×Riœ —î ÚåZãC-%e©„Èâ<ƒ»©”@:ô‹Pgž—Cf4ë7 RÇBèc"æ¸.ô³Ïç3Û#¿1¯–"*¸{c0ð.WÀŒ“f ŸÛù|›¥ù,m•ÏÆQæÙ“¬Öð1™¾•®aŒ„+U&…s2Ƶ5LñfĹä²zàc=¼! ÉÆiFÏœÁòŠøÑµ®—†ß…Â2sÏ ö(–x'T•¶sÜÁaŠ(3SŽ0…Aº=P~@vŠÃøÍJ„ñKÙÉ…à§œ¶½ŸvÀ}ß:þ0¦Ll0ÿ¯QkuTü?ø¾Þj5›;ü¿þß¶áÿ]* eÛQa‡tñ*‚tñüÑ\Àöð¯ÖÿõÏKå±DØ?‹B‹`4‚·§[õ§è¿‘÷÷iŒ Dæ8Ãô mN_ 00Ðkc†:/'*`ì­èHø?ýB©ö×~,ÜŸ(/˜Úï¨bž±œÑÔ2Ý3 ôð¯§zÙ ¥>:xEU¨‘¢6|ãÛ܃K›Ñ\|dù£0)Æ™dnê2+×çöi÷´.Àyñ׬ZÉze@;šQí€ÒY°žéAž; ÞÂá–ÞdzãÉ1FƒÊ­=vÈ ™ ÷å+û‡ô°«æG›ìô.ý°²áÂx lº€;æÔ¾wMLWX»WOÁÈÊêHH‘="¾cK‡yð3ZùmGcò$u‘Ã^ÙSìx-ãyVìÊÎ $øøñR­ïò3»(®aOÚhxÀÖØ!CæÐ €‡Þ$’zåÉIPÙ“ÀC†x\*â(¸–ù'²ìŽù°|r(VjTÙk6BuY¡qÆ%t5ð¦±V¼éz0©£×Êj2±eÔ+ŒCÌcãûêìte ’VF`M4}S¦·qg²4~„}ÜyʶZI‹¡[—´+±CªVëc+N½ÆGƒu y5®>™_,üëxæ}i¡Â<© ËAkÖ=.TíùkŒxdž1°ç# ßÎß*˜” ¥†é"3)MúsºGâÓ8Tóc\\ÉœJšá'®.?ˆ'XkžIÿ²8{(T&•Qí¥.B¡»#Õ¯?Õ>__þ´æìêÔjŠs%¶ XSÙ*j.áDÂbçR&1+ØãDRÍž'Í1l‚Òt͆WK°ç_/¨J’¦é š$­Ð˜Ý¬dœ#´´­Ì©Ö0îž )3ž! „Î2-Ÿ,€ÒpÃ{ö–Ö ØÎúZyZ‚Þ•ñkîYÉ7æ3ŸÖ8ë9ZîGÓÕØâߥÙbÞÿܫɸŸÐçB¯¾ N±û.¬{Û¤D[´õr(éÇÆgØ+ ØF×<‰tjp«ôbXp¡eþ9°sûN‡åcÒñïóüömú«9Ú* #TÅÕ‘°”ó‚g'Hz<±ÂØ _E©•Óä96°SIsËú(?Ëú“éçÚ³·x…rÍiÕµ°ÏoýƒñÏΊò0Æ«ûþÙX¬¼G¡pp\TG_4‡N) Ý€ÁñBix(™8Ó©ó„X,`٠ɰ·¡ÞÓO>±§w+Ï}ç=‚ž}‡‡ýwxúy'–\eO¶.ñÆ€ýc|w»YÜ<£»¼à½'ŧ‹vI+ø¤ÕªeYÁPcÆ•éÇ\ €ÇbŠÞ?/,mŠA PÚ0@ðÑsF_¬¥Ý@¸¢(Lÿ†7·1µy…)GFÄúM«ðˆxW]ÀGñ+X:ÙÛ|é‰BÖZ•DÈ”…há…( ,¼ 5?òTû$° "cb—+H.,eYi}y/2ayZø–˜šY׳*b÷Ò¾N³Í¾µW]£Ñju×Ü7c¯ÜQ§/ײ¶ÓX±’öSÉe¹2”±­~û‹z}º¦nÀãnX5P_áá¹âÃcʽ 2r…JÒúÇ•"7)AµÐ/,Š×2ÞÐ_([ÕYoèíÈxÜ?ˆ«"5Ëè hb‡€»ô42¡x+8pxäáÚº©Y“º)¶’¤s9ø”—DF/ÊQAf2­7èH|D¨ Šhl¨E1Ë,uzc-Þ9)˜gY¥#ŒB0u"(~þŒ}<¦1 ñM¿pcÉ¢Ö6§=tËMì‡H'C:Y)bOÍÇ쇒³—Åò¥ ¸Ï]Ùƒk O]ÜC†Q‹(Rs5&3`9­3©ì‘š$™Dvw´L(Œ÷î®ß»øÔ—ú¶7Y¢Ù•¤Á‰—·= …'±»š£,ÚäN1n)óø,A ÁU>Jði!ÔIň>Îlk,Rç^‘h¤°·„ˆ¤dŸ_¾h$µá[¤y“s`é wóï2މâÌñ˜z@9Yæ¬ô äøŸzþO‰ÿi`üO»µ‹ÿÙÅÿl]üOï⢠š£:Âæûé[àeˆ®óC—ïnŒ;ñsBèO@3¨eðŽHâû´¦²Ç”qÑ¿êûÕ@Q¯óÜ5£~‚mÎò¢µØ>£‡¡ ÚO½Ûä KßSJ¤Õë#:P´r˜>ž`ǹwá12ñ KBx 9 .rYPbÆÏƒ†£¼ Žs² ÊÐV§vÚè´J£ Õ»X\KR˜&Õgsq…¢7üeZluêÍFóU˜Ãý‰d‘ÞÂ阊ö_aAp|3²øMø%VØâD6 G; ’‹DŠ(íÑñµ)Ín¦Â1˜PÌÈ2ã‘íxÇC¦ñUR{p3ÔcE€ÂÑ`Jö¾ ›„×nu!:^v.O§­æK?ŸN1äZHÃâÄÝ/z˜Ø)ßWÕr±ZŠQ:d8eþî*Áʰ™ØHƒ»­tlàë?¦°ŸixÝyT“w}qw Ÿ‘ 6fΙ›KÜŠâá½·ˆß$–†+¨ “Ä èÃ##nhãT`E:2ªeI²dgËâY¯r^ž-زØZ‹?oIT9ŒË€Žkuš­f^踥é.é,å zFø²ÒGåM¡|T—N•sÇx‡¨MôC™á…ˇ”üEE¢Dšݰ° VJéLÔŽp.øƒÑ¨ÕZÕÚIµÖ0ê'gÍîY«Ð®Ëwhy}‡ŸøÑl÷±ó¡ÁD9"AWêH"L‘ÆÇ»›O¼Ô]³ÿUÕ CÀ˜@C …á&â§ÿá9_mk‰–IÓ0 ‚X᪋ÂàƒñSàñJ tæb·`¸)ÇIŸôÇ+-Ã`À+ô´l1Œ/ü“öx¥ÍʶÇô´€†10š>éOw qY$*Ö¡$^ú¤?}ÕKCbÍ#ñI}¼Ò5 ƒeK4ãA|Òž>aφIÂacàÓ3ûè“zM‚£áßextöK5ßéÖjÉ 3Z¦¹²÷ö-\ÈP½3²É«ƒ«=SjvävƒNAQS¹Å¡Ó@[»Ýæë¢Ó´:­Zý$?:Mq"Á`@€z[Uò/±OlbÃÞÝÌwýó›»‹Ëëïca=" +€3’Á:+@Ðv 3&¯a/E&XPd;¥„ ¼Ëå`¨H2ˆ‡z S>Ì ÌÛn<ÌJê:Ù¯gºq³(C`e•ÂÝø™ËêO©m@c.¸,Ãþ_ÂÎW^oU¢O(Éœâÿm5š€ÿ·Ó>Ùùwþß­óÿ~¾½è ûülWÅ‹iupu3| ž`Ç‘ÈF¢„F¥p#à .ê“ uÅá Œƒ››‹OW‡ nâ%¢×Ó d^¬ÄÀ£‚9KKdÙXJg5 ^Ñ­œ0gÖt0'öxNosþ©°Ž;:}PËðLÇõ¼<‘Çí{%z«ãd ¿õgªßçf!»ž$VØV™'Fú¤'}Ò^„Oº^otZÊEÚ[Ï'×¥Ù¼ÓÂã”Ùˬ–Ë›]È=]¾cº^ïtTLÛ—sL‡»:ʶ' á/ò¼äôBâT®Ò qHŸçÈ÷7²Ú×q†¦GR}Â)f^3¢¶d Øp'– tF¿p(hà=Ã}Ã}g{¼Ã-Ø­åxhë ¸qt=´LG{~SÉÑq}®$A8(™É«¸Hi…Ù‰GÐÉÊ\ËàÑ Mç#r$¾ÀZ”Ë?ƒ”‹"·á¼Eý)÷I[¤Õù bètœÁ™ŒÑ_Ù“Br Ô…€ù_fí l† 9~#³Aßàbá: ×öɜ٠әp&pê6Éa(æŒ>õòM!ž——,8»yœ0O™½M¢¦@§ê‡¼À¾Pãÿ­H4`ŸIÍ;6>®\|~Kè(çððï-{ñB£”·?Kq6×›íF«[ˆ§,ƒg7š(‰#KEÝ¡Hìqcgã­UkŒà“å¨Q­Ð“¬–Êïo418w‹äGyÛ‡’¡…þ›T×ÙTñ —3âQê ùX¨Ø}ˉ‘T…±ùÕœÃ+£Ç}YÿUl ¬fcÿë±-Ö:Pó{å îìËË?`îl_P?¤`£SÂoz|ÛÊãÿ€qÒê¦ðTö>1§¨'#„¤n-ÉKZov»êÂŒò’î]ƒîBOCùÒz«VW)DR¤{bocíef€ õ¶¦ûH•$Õ²)ŸéZv¡÷ù®™\‡ZI+Jvd0!…±)› â“Ý‹)IÒYœøÜj}ûÎÆœ†®¢žGÅBZ‚×±˜+—2fÕl72É»sLn›ÿ/œÂü‚øï ¡jµ þ{§Yßùÿvþ¿móÿi)ï¿/øGÛ#4 ­ Ø— D4døë¹ç‚Cº¦ONë¦myÀÚ`ï:àÉhï‹@á g`ˆrâ½#4ɺ@ä'õzt\% 6h°ãÙ°æ—Ž@CöAÓì¥ç§öÀjVØzŽþ*-þõj¥Þ¯¸ŠÁoócÏY¹#kŠÚ:ž[ $`ï}=»ÿ7:7*¼Œµ‡Býu~Õ»Žè/iÑ®ìR@«KŠ+e:!çúÓ©Óê¤N§üp /=ëGAïOav½Ûà@Çv…gJ_KÂÓw\ T©!2½KЩ–[Ù;ÈéhöÇyX|™Í÷‡¸.9ª~eo†™YhmIX‡×ƒKƒ¡ØWDôÀפØŸgRºh¯9§»­V³%¸²`«¾-ÃÏH@`eóøÖ¶\×2>™6< +%qZ3`E>¯*§>·á;6ï8~kŽa°Y:U^ãR×õǩӆÉ,õ¥ài"ÃLD”«t`Óyp¾bJ“ô¡z¢a¾ gR*Ô2#ðóÜƒÕ øz’æ,†"tÝÌþ‡5ævÓÕ4òÊ‘ýã¾³€‹˜íŽh§¶o¼ô–ø¸uÕãхk̆ÀÓb¾úÍø­ÛaÑ5•=øø·N‹ýeÜ:O–{{~d|t-ëÃàÂh·è„¢m¨ìýt˳¾§ö…ó÷Éq¿Hˆ€¯­ã&‰Z¡i2Vö¸Æfe<ÿôÙïôz× JîÇÊÞÀ™š˜ƒ×8îõÓQðMÊ;øà‹[ƒú[r’ÔŽOë_–ÊÞæ…QºîþßKvÄ ¬ÇOj_Ô[bîÓLª×ÐßÛûtÑ O5E°w«iÆ«‹¯Ÿ ¨Ì} }zÒ©ukÁ} ¡ç}À¼ìD¹úŸ«W/€8"<‡Þ7 u5RL‰†NÿÚ¼¼¹–£§]Íñ-F„Už¼¡›Ú+†Ì5ŠâÆòCoÐÏ"‚^VFbêÍP]D-qOÓˆh/¤>,'mê ‹µ\ÛYyQå&Íölä丸Ĺ‘:+´Ú’û){›—Nê\ñ°±I_Ýz»¦f¼F$}Q2[„Bñxx¶áŒF+—pÿˆçÕg‚’9JþJaYEŸ,×XyŒÉJmÌ⽡“)^ž˜ó¶™Zz(Sî(Žõè³X^ê‡å‰|Qí'y•þ€CÎõž¦w¬nL¼Ù@ 3Ã¥¨ç˜¤\· Sä3†  é÷x»#jŽº¢«„àñ×E„PfMXÍOØ’vÑŸæº|±Œ7¿Ü¸(*Óí^kdBbljl†úHðCΊLñ:µ›vBw¼ #ç'µ½îbÚìXIÊ™ƒùÉôˆ’{ú5j¼ìùÈF¤Ñ­%ÖWöøµFɯ“£4‡}ɵGäËZŸÙ‘[[`Ê 1dß•/ÇùÞ}©Zó1c{ ¨èõ_ö¬‚Žxbªíñ4Va\•nÅ €s‰ƒÈÚÏÕמ Q’lrVÈúvó#a~Ì`8áüêg")Ǧ¦[Ë–žº—°®gâSíìhm”á\8žgßOŸ ;=}bDøˆ åÏu›Óôü¹!ÇxðÏãþ=çz”ÿMõ$«-‚‚'.\(чµý÷ÖoKkîÅÄ&n´i&»]Ñ<àI¶·^ŠM/7°©fËÝ ß”²sêmÄÿ7BØ÷*u(‘Øåf¦ñ?6OTÿ_ý?à«v«½óÿíüÛæÿ;ïÿЯ{®úÕ¿|îß]ö¿ èÏIùSä:˜ÓD¤Ç)˜ŸŠ£ÊôúÞFô\õ¢ÿ±÷ùjø69}Ðr—ÑxŸ—׃þÝp >£gÅšÞÃÔ®ÍéGÌ3âkæ†F¬ 'cD'ËÃzD_•èlŒ¨™ލF\gÊL» Ñ"M8¾—„Ã"ðFè$ëÝN«¡:2Ö¤“ŒèÅl¨ôJN“wÅfI%KG턎ïÖ4l¡Cí uuF6Iœ›·¸¼6S™G©ÄqÙ¹Ž*-1QŒHáº2ì²Gj WÂ^PR¢ZH¸w¼Uqõ.UuŸ§ žãÑd‹çÞ‚5fý†eÐØÏ\¶K€c=mŸ¶[µ¼h¬Ë‰‘Øjc)À4‡•ïËž4~™8ί3Ç›ƒƒ_“}M–{¤æ4~y´ðõ«1™:æ2ê†zÀÏmÖaÔCH(ŠgÎ_Aùh°8TE#Úc샴ûþ#”²#Õ¹Ï@§îg—×ÖÑ2@EõCã`ŸÉ?|¼ºé »F×ÿ %‡>ÜžÿлÉù/$þÁ¾žøkïŽ=ÒnógŸÖu¼k¾B·7;)Ý.¬×j‡™úÞ8ã«€©øŠf'v(øÐ 9%ÁÂz<9Qi"Si9ÉC‹6 ÿ îhFˆ  á\_ZvÚ­%ÁËn Nµ$“ÛûÂÚ¿0bØÜF îÖíWäm´è“xi^ÑowPÃ^sè†Æiò­¢Î°ÀõOÊžÍjÍåNœxÛàÖœ;?q>ÿ/‹±ÆÒð’þßz»Ämwê;þÇÿwûü¿,Yª!3–ßH(®ï@JPû|l\ 36º0Ö1 ž\isÆ. p…‹ì¯ëÞ§þkúq#Gw]?®Ú]ys?“†h'mÄ`”⣠w ï£ ï1eúhÃ5“öŽdìnxÿJ+؈‡¶Ö>mÖ»­ò<´á>Fë4'¨òBÉÞPhd[¿ —ë ÍѤ›l˜eÜË唃î8­u»éé…bXy<³—4I‘ýŽË{dØÇpq";ö£ã…$ÈP½´Ô"U3C9X(Ú½bÊÛž^$÷ÍŽƒ‰‰#sÅö¡>ÄßTtùƒ=¯¢z=3jÇm{þƒG N|¹tÆËbàd ‘ôåÁ ó«)-€LBÏ"z^ -焃¹"†OÓ«+ض'6vœt»ÍF3VëÔšÕ,‘Á°!£°&^_^Éß7s{jìcZÛæ H²¹SûÄ"eèi›Æ™¦* ûî?§Ë?Фz{3~ׇgþG©‘ÿnu›µçöÿÂU xp`x²<{&E`ÿ„¥˜=G ðég¬›þ7Píy»w¡WÕ19ËÂq.Ú~´wË¥¢z²‰·éºpŽì­O3·}ÒH¡#[P^ƒì‡ç`E'µ“F„EöƒBøUÓUUÁ@•Qc&±A•ÉRVëÔkÝff–²<Ãi]…úuÍð"ÖU¿÷ŽË¸·äšìÔb‰7¥¬s({upK_®1²ƒaoøy[{¥@]°±ù:#Z|yíŸÂckÖ H&B+b„†™Ö=鯡ƒy‹lÎÉ·Å52Ž”b×71g¼?æ²0ó…±¶dÍñonJfö_Lys­iùÔ_Yì¿'íVÐþÛlµOvößýwëì¿„ÓugMÅÁh»m¿¸®c˜¿Çÿú'#}ÀÒ†+Ø6§IfßÇZë5'(Ê$½› „Mâ%ØI׉B/ꆡ{œã/¯ËäuMÀj×åÃK C)BôĈ®c%ÕÚÄaž-›:LlcìÔÆhÞ0¸X]¢y=ô½3Ÿ>ÊGŒú**ì¢ÿéöêæç~_¼Š¹ù‘žß|ºí]ÿ,#~Yå¼· x@q–cŒsšÙsŒr…åæU¦öëÈØÿñÑÁ§¿Nͱ=³Ý7ž13çÐîÿµO¿šKbø2çÏÆØ’ÿäxÖÄ@šŒÊÄ¡‡ÐNË4ãýN‘œ?ÚãTV—óÑñ>an ù—e$÷Ï•ÿrì9јܤ²v'¶îù¸ÂAÐ*Ø¢ïUüñg|C×Âu\s6eñа1 úWp|4&¶ë-ÿ†ºøˆ¨Öé£ü³²qG¢?Ä•úÇúw}ùó1ÿÕOúß1ãžÑ»¾þÆjú#ô¤ÚcnCáÍ‹¨Ì­ã/€hZ‹bâ÷Š%êÝWš õ» ž¼²`DuÉã'ŽUöh}Emàßåk ÕÛ’ªxl°]7|.y”•¶ã„.ãÑy²àÈe{je¨Š°9OÎj:6p–€b†úaœèÔð…Ál21Ÿ˜ßê=L¶RvƒíÁ."3ºáÁ±È@eC`+L<èŠÚª* ÎXµv9o ÌF:Ìñ8À*‚•T¨j†É“šdT#¾êwǦ½|ãeÒô 4F´Ëu°m/±o= 4K_X8±ÿðì*Ÿb¿ºÆ;P5òùjàñ}õ >3ìqåKL91èÛ*ëñâž°Ožá¶ŠÙŸŠÒÜ;›0š½ðpÐ&_Ãa@U"b“Ú$rژƃý=R¬ÀÞS~H³2,!Ë#ð7xºb/ÿ/œ½Ñ£k„GWLNÑ¢‰åä7Î:xåauŒ…”úà ˞ªì¹tàÏVÕŸô±Ý‹V©÷ö↾Tø ‡u ƒ*ÔùiÉBú¿¬'œ,'J<|G•-8åpáÞ ;tÚš°£–¯æ¤JUU Ž+)Î Wœg麗º^±¿xy~o…­x$w·ù ~ïɳEþ¾+w{T”<.;™ †è_Õ¥S…ŽÄçp‘â'ñ¿3Á¶Ò»w¾ÒæD‡wrlûÑø)eUä›x|\²Mš²[1[ wYؼq~ÌðÖkÄTZùˆ‡(ÁB-ñàH[È uÅã‰ùc˜_M{JwYgÁ {™ÜQ–gR_¡Œ³•·äY^Ï H-~³EtxôCX´L03Aû.°tbJU°Hãó¦a:ÉDSã±ÎÙ)EƆT(ÑPˆ–üQú鋨)L‚úžM¸%üÉâV8`¯œ Ê­ç {6öÎ'–ìJ:àùfYÁÌ9ä]ñ„!ÚŒ âd8¦¡?üg\‹k–¢ÌfèËŠæ4SÜ‹ñSéѲ*Ã^ô÷I<¼Rä®S*yø_¦Ö‹;­9g‡Cÿí#ƒC${xn÷¿™¯žôÄA1‘*µ)BÝé Á5uàŠ,Z{†qf8=X2ÇnXâ2é„{¾»|²²D%©6õRy!Š>¶•/ÍA,`ùäð»´Þi†›ÇT”‚EWÙ-—#þcbv‘šÀ'¼5{LiQb§ù óSrq>Ätu#¾N–!FÏ-*4ìR¾°=ãÞq¦<ÆD²'ÆÄœzÐw Q—XŒ·V¦š³µnªû„ÐGlÁ¯8 ±h  €›ÅÒ]Yh"¢Ãc PmË8RŽÇq‰N ”ÎçñÊ¢T0Û-©KÃý§Ð¦A¯ 1=ž×l²ÅM‡¾ó(êÇž—«|YZ9ßR+îÅ,Š”>|OGd6A"÷V؆YäÓqH²€´8Ê7p‰žÍqd<‡æI£Õ’™N)U%°d–´ ίp¦;oP.2Ù_ø7ýÄÿHÿ}„Å/L×™e³éq; âùÕÍ@†YžýÜt©$ì9LA{iâ9¦1,”ñ”….ÚóÑt5¦Ôñ)ÇXr¦«ÌNU ßd„-Äž‹[Ü£=³¯9<É Ö¾g<ã&"Ã%½Ñ£53Ñ´ЇI‡48¯DcŽÈ SÜCó3ÓØ|CÖ9þ+ •±‚kæ•Ç͸61@0èZÞ!>LèˆZêŒ 9¤x:j.ëº\óѰƾ=E2TP¯ccMª¸o³ à%ê¬þõ²ÿcõüª7ˆFÑ‹PbB¨jTu3ÇÕ@/¤x[Æ‘ìñ)ÆáûòJˆßÈâÙɼá,uoATHÀAùo"ã?6û‘!þ£ÙnÕñÎIkÿ±‹ÿغøäð‰m)ò¶&öÉý_’‚?r‘¼RH)QëÄŒDð4ç ¡§Š‡~h˜üq#֙㎠D‚¨Q<âcíQóCDw?ou/j…³ÉÏò,­)áœóy>Š¯ŠŽ8ÑwBµ+œ'lç¤*ÌB<1¸óô,Ũ4:‚ƒ½8H~G§@bGÊŸlœ µšL—V¤6[6}Ì/žÞßU¤8õð:)âyyÑ*]ÇÊ-(àX¶÷šZ˵˃Ík${?¯¼¨¶*9”±a`ê\ÛH ŸÓ(œ>¯cCÀ|ªÇœJÒ %_®rð÷Gvvë ®î_­©³ ·Ž»Rì» ×A}ŠeÐ$a°†è5 Ÿ®mç–f¯¡Š¸l¨«Òêã3A3xÚóP}ºÓqZƸ­×% !C%¼µšYÌÿÄ\§äàÅtWsfOm8j“Bxtž*i3ŠÚ¤ °#òÜø1'ÌÒthxuro!°$ õ Ùƒ.I± Ì|‰ÙêV¾G3ši¼é³ßf‰Îé9¢ù¦1³çŽ 5ÁÁa·~[` y»è|Cû²ü.˜¹V5²l̈ž…±=™Xh:ó§MíL]!“äDS`åe,´HÚ#f!ss%Aɺ0GyÌù5áwòçÉdÍî­ñØç™F0 .,Mš=6ë~&«ì¢)|%3³™#0Ç‚@u DEš Y œšàÇø|{Ñö}‡)j(fQ­:áµ-š!¦¤ñd>3÷â*óNìœPÜ8@kí¡L"Gcj`™3?%³ËZ^ —èÖÊQäªó(Ì“p”E;–DH³Ê·Ð¼O¬L¥=u…­<\Yp¤º·çxy"‰>ÃlËVc“]vgñ€.+ØYÇáôW{$_¬×ÄšÇËï4CS¨òvAì…ý„×öè‹q…ÆYÑä`ƒ÷÷¶ù‰²Xy=á§ZeZyrù€Tà6dñnÜ ñïà"µ5F UÅ% 7(Ëœ•ë Jñÿ´:µŽâÿi þc£³ËÿÝù¶Îÿsw·a¿ŠH;ƒá]¿÷é[@d@À0žh(ãòÝ œ'øÏ Žs<jçâBéç¡Üû¥‚D®.C¥œ×äó‹å5Ý9Q˜Ó¡¯uü;ÑcQd¨ó¤i6´Ë”ˆÿª•£?"— 3,@{Í—ì’Žw¶{×1Ç#´ò.`ZhË Õøî ÔŸgÐ/˜²³¬Èì|§§Ò°"C½ËO{V!óûsÿç4@Ÿ‡|cT~¬ÿK‡°„¾ïœvj¯Aèî~ð%Y¤Q•ÆL—MÒ½""î­+[pî¥õáÍÜÆCßvÃS- f{õÎ*éd‡B7ÈèæèǸÚðsc2^-Y,¥4{'¿\* ㎜0½ÿ²ðæï=¡¼ò,uJB7_O±ë¹ìÚV礙ÆÈöTf÷ôVœŒ/ö|ꃷDîÈþ¶Ü›EBíÇþc¸êìƒé|‹Á]ÊÙjºÅ ¸¼ Jö»·XÊ$£rJÌ—ÑUÔQ|þ^Œ^òÓ½2jʱµ°X˜ƒƒi9å¢Ð¤¢!÷ y¦#-‚øÓÙ‘8›¡ä(c tr¸NON¹`wƒ'kãŒAÖ¢L:ŽëÀŸÛc¾Îàã‰i›ðºxÆ[vOwÇUgµ\¬–oEݼk4ÀÜ„ÂKjDi4b0ÝzGÅ)MåSôA@—`ÆTïŒlŠ@»`qb1ò f1*¢R»6¸ÙéÖèÅÖ$¿Ê 2´k*ÓKsqè…—F‹E{ ›üq†“a*ÛÐåõ÷I«Á !»:‹d‰nn3 ,ªˆ<êûÕEÈ®äËQ½—D/¤ Q)Íö_yàD’½ÞÖ°¸úõ" Èm²O´Âä³ä&§e/N”`1åÃ·àš¢p¿UnºlöÄ¢pÁ5SBÂYv{c.—£¾Ú¶Àéœë[ï$Tùß6•–ìÿkÀ‚ æ5›úÎÿ·óÿm)ÿÛïŽóÍæþCa a4ÕzÚËëËáeïêò*L\Uœ'ƒ·Iia1ü“‰Äb¯ÎWF’Wr·n ]\ìø”H$Š+ŸŽ\‚õ ]‚²³–ü-“6ÂW¯5sñÀe"Iñ°ù-¬¢9$ìÓCˆ¢ä"ìIÕú Ãð 8öª9‚ Ç™æx£os.¢oÈ)¯ÞÖ˜ß^΋˜0Ô‘þÜIîÍÑ ä⦲‘º"Äw¤94ƒ4ù›>’™Ëþ€e‚W„ÿ‘›ì?=+•±´*zM&˜z ް1 +á l$EF“§d’¨ˆZ<„ŠAÏ>Ž”ž#Å0áz·—Z+/ÞŽ¨ÇþÆë Ñö±!—i$_by¸ð´·)”=éEPgÓ¿éja-'UäŠdVD8+=Ë"ÎB¥ kA¶T-«5‹w?¡½I V/ìI˜€ Vhï»·¦Î“äS˘Z0IlK8 ÄÇË¥ê–ñÑÆpeðþq¡«²/JqÿÅêÅÈ*{… ïœí öGá¬>®èÞBÄeiy·'‰úÖW”…ÛÔí‘Mm“©ùpŒèi)G0âp w-U+7ÑÔÚŠ•®Ú‚pƒÅ£ÕAÁø€Mð¨KÅD} ûåÛ2•ÁB ·2|#îõåUùÁq»_9»†‡œ2ˆ| ·øž­µrÐÒ.YBZì±@I]4ê µ1[%^褭bE9ï g:ÊÂd^/Ú©„Ö¥.s.‹T=M8q>Áòå²2ro‰RhìÒ\ràúÀÎlµÒ^V®Ì ¦O0ð¢¦y´àØ$™|}7{R½P'à5‰£ÐÝÆ†ªLoUÔ®ê S¶5+HȪ £ØyUÍá+²›úƒª ŽçÙhàŒšÈ=æ„Á«¨Šµù¬}è@ë)^u|÷S4O(늃Dê‹<õ>™î¼šX¹>þ/ 9‰ÏjVZ@Ÿú)sã=ûNõe%»ÄƒkÙá‰Øm,×u\|n¾Sô°1©ò-|C`gR¡Q)ë6oú,¶níߤQ¬ IÈ”þ£4¢ðÈÆÂŒRc}GZÅuá12iQÅÅ;Q•[ËÇ—ÙÖ˜7}öè@«Ã-ZÁ²)Z‡P:Eoëç{T†Á)jx&‡fÃpd|µÍйvDtšGO3öfUlïó?85¿‰'Øn_0!Lúh…‹Óqæ‹BäTò ØÔD¢ú9­ õP;¡H261ÖÑ$é È IüB¶N“ÈMTŸ%„¾œ>G „êø>Œüð Ltÿ•È#¡wàŸk´½^:ËÍ>x U î-ÿ^Žüõ®F‚¶ž?JÒ{†Ÿ­@œ HE®}aÒ1A‰•,rêðÏŒ &Cg’-TàX÷À±N°a­Ý©7Ô˜¯ Á†1ýd¼9ØG”}c&åÙ3øÄ¿ 32‰X>úöö="É᳦uN l…³þÓÏHWOÿ«1Õך‹ÿÅbµ6o“D,AF,›Ê¿œ‹©ipÁ™ÿ#m.¡q ÷KÄ^’¯•tQË0Ô°c¿bÿÓÛ‰>VÊ8+wd)õüÁøhOá›w ÷¿ÞѨ!~þßñhªˆs×gÁ~ç8„ý»»›;ã eVy•}wY½ø`°ÕnSÿ;ðÇŠI}׿ÅÝ·ý¸’ŒƒAøäû|54¾;Œ¯R µV_Ò˜g¬“7U­¹ö«Q˱è[íúÇ6[ô{ëǃúlžjÑ¢1Š]U·éá⺇»Û#G‡¿Õ F•½àž ¯¸Ö‚¨ÖA‘q±°LW0bÓ^†[v„ƒUX¨ oòàðÌN»î½³š OGeO i$*…”¡·;Z79@™ap¬§ËóÃâpçÃ&ë@PÂEÿc¦¬ðv_&«0†‹”5“C¬ã$“D¹ârX•.UÔX‡E¬˜ÂI/G©”ñZû¤®“Cƹù=ÖŠÇm»ú¿ãöüŒÉs{ž5ƒUÉ¿àWb™#Ä΄šÍïˆvm~]®ìÑNw=ÀË©÷cj¥kÇ”"ýAôñÊ ›m‘ðÝ~…ø&2÷Òâ8°ŽŽ›'ÌÈèKˆtx»†!™yG° ,‰ ré:+øª²‡VI©IïjMb—Ÿ½¤&ÉYh–á·Š_ .3[/ïŸh>¹ŽÝº»ï‹‚ÇÇ‚ N[R4 J9_\Ìwò1Bcé*÷1úšÈw¼N¶ÌýNS -~™l…B¡SïsoC¹BÓm/2øìâràÇúÄÜûä«êŨåˆj1!¹VùbJ‹(ó1"Õxn4€.ÌÇËkÄŠåDÈ—¬b.W^(eføy”%¯”î_kwÛ-5…I ÷¦8)BIh(Ø+â••©å¦ŒZ:PT& jÂrÑ ­ß–ÖœPP·2¹!XdÑDMa”Á«“'P2W¦CRdíä=Dì2ÿ&9ÿæÿ1ØJÌÎAê-o#) )øo“zCÉÿ¨ÿG­Þªµj»ü]þǶåPzRÙ ¾…Éx< œ}¨õ8HãàãÅÅÕaB2ÈØu¤-Çû»›[ꛄD¢÷ã®·@Ú0r£êí+&whC¼f~G §r¦sd¬ur;"†¤Œ¬¿å‰ÜßeJÌíðëáˆohkUI¶¥Ý‚íoÈ»ÝŽ÷¿&r›ßOâ 1[ÃyýóB°ÕÛ§FíU’'BÝ– vÈ£ô ßx$s:•á7¥g„è µ'nT7«´öÑêùœè4jÞñ&A´êZ½iVS\2=$•£p7ì­†© -!¾)}ÜûÄÐLVÆÖL%ĵNºÐÀ:ȇ†Öy3ë2Ë)å/'ùddlì¬ã‰ðY c3YüöýQ¤EzcMañ»|e‚öñ9‘f3‘•ZK€Ä‚Ù}rÚmå‡ÄbœQÃŒý‰k÷%’œ¢æöÜûÛƒëÀ ö°õ ¶Ðañð7 ¸IÀ'w…RÒGv¼ ŒŠ}¦³´ø­Þ>õ…øóoP¸ö}é={á/±Zñ­V†íD–_G•_Ç–Då„D¦bÂßR)âë(B¯p‰¢¾O-̃+‘¯„ŠS~ ¾H¥F¼ù7ôê}µ—ÏÊWBï(¥LÑñ–µÄEŠéSFèòÒ ÇêzM;$BŽÁ¼Šs­CÍõv»‘ û«PæLy_µÙl½"FÐÒÏÞ/ãucaÈáK0ð¡kp¬—͹ˆw-íöë[/¨4ó½=®r­€ò=õN£VkuÓp2_¸èd°!§ËvK¥š,ŠºZ|cT ~–ŒF‹\¹‚¶À¢-ª:RþS@½¬ý¿Õl·ƒöÿz»±³ÿïìÿ[‡ÿäoï¿c)¡˜ãÀ°÷᪯Ûñ£]™¼¯„ï¤òš>€¨ÎÚJG@pç/ÚI; sx'¯)âɯ‰ü2 ^3ÿoÆú_«ŸæÂvJ¶þ‡o)Vü9uC~l'3¨¬–Õl^Å“rŽ·0O«JIìU‡Û?7ëœØ€[¢Ö鼦Sp\³‘E¨d>V ™Ž8µ º$pñé°wˆÌí3½Ü®"ÎQŸöfz>ffõ”(IâºÏ"φX³Y¶“z»~ÚQŽšs‰bB‹‰c\äY¶[๠]àƒ1Œ3Ÿw›ÏËì_&I±Yç©:G”°D$?_€áª¥cƒDNcã!gÍ*< 3¹¦DV´ï º_-1[Þ^¤Xçμšîá¢ÝéH:f„slçøå»ÕbŒGŸfn®(o‡ã¦k5ê¿þ*L•ʨòí¯¢ M:éŠ:Øÿ“ãY¸Ó–pÒ†ã4FÀÇÿá9Ъ%ÞJ÷™";Ø¿²gwè:Kï ú=–ì“ö0öÚþb/MxæÏîʃY÷¯ý/ücÔóX¶=†‡>¸Ö?çôü=ÿõüÏ+׆Gzs<ù;ø´É?F=ýg>±©…çÐskþÅÏ#ñ9ê­Oö—Gxì{ǽ7y+Äç¨W>8®žŸ-PzTÛ3ûõð_§æØžÙè¼]1Ùø¯öìáuÿÁ>MŸ¿á”A’é¦é³_a ¬„ÓÚIVš^H;ÛóÜ»Eiî§vÅÿ6ÜOífã´€û©ç'ç)Ifö$çÆÎÒ}°ÁôSvoƒÚÙ‘ZÞ~ˆOÞ#̱Š¡ÃXØ WxBž@ƒ)ÃI×n"´ÅK;é^ÅS¥Ž‡Ìè†ú·òе[õV·ûí3¯d³çm…—,ƒE/—‡L·ín›L.å]®ÑZù?tS îÚåySü jþ—N­ÓÙùÿvþ¿móÿýx9ü¡„ùݱÁ0u™bÎ:H¤˜Ç{ÿP&Âõ4 m:Õ^Ê=.¯ç Œò5Ý‚}¸-l/Á±)ÃÙ‹ò€¹ÿ”茬ü„ý߬ъ…8­ÃÄØbƒ9q—$Ü’©˜0·žvÓ¸¹í_ÿ zà´}Þãp¤•ƒ©µ4$*©q@øÁgJޱ6³fŽû|¶€ˆ†q©N YŠð°NCòciþTÖPš‘ºÑìÔ5•÷b)Ps£~ÚxUzs¡Pê¹äs*5<\ìÄ^^ÕDnVŽ/…$;±—fюܸ…U;¼ÛÈÒÛÎ:¦a…Në´gV] å`IF[O3ßhÞ'ŸŠƒfE_â,߯ °Çjä˜ãû"§O&l×m4OÁ·`æEâ©s£IÛlbÎt7ÜÈ«,·Å\VfmÁm‘9Æ$ñobr&û/ A©"‘gðeY€Sì¿° wûoí¿­z{gÿÝÙ·ÍþûùöÃÌW7ÃêÇ»›OU½»ø,ÀŽ3ž’AnX¤ík£³ä‚OæÜ^¬xü€Ÿ^pssñ)1)„뛢„F–ªG®pÞ‰—׃aïú¼¯vä ÁdÌ+`‡O¯ú_TYð͇?õχƒêŸn ŠW´ÇO–5mÇé]Ó”œ"¬c_ŽÈ2,Í1½.­1{]‰Öæ ÈÞü™{ò¶q£,Ý$ýx«Þm6;åÙŠcº0›µ˜5=G"VS$¿¥P‰®dë2ŒÀI³ñ:èV¡þŽ Àß“qB« =ÕT ¦ŽçQu|Ó ié~GQ°I•^Єòß}ÿWŒt<ǯ¹,&R\¬k9Α„&ªI2&[€)—p– qÑ4™œ" Œ¬q£ dÕ =þ@>ˆO"™Îo6ÞÛ€y½U?=骊ó:SËž$sûfZË8¿º°'Õ<3óH$J¼ÄÊ’‹9ƒ zÙÏ×0—K×¾GG©OŸêó6š‹…ë,@WÁïìåL f»ðƒæÒ å9#›b¤3z7"Úå ú¤Ø»Â<ªË¡$šEí É)ÒLcl…emˆ‚@,REÐ (ŠK#9X"°i„)ø4²ˆ"ÌàyoïÓ»Éx5Ù„I»w¦ 1§ûPüÞ¬.fæ âKõöfp9¼¼¹N(¢Àò}ÍF½^+œñyOùýÒmd¶l PFk@.§ChÕo§ASÿÞ.²ÿS¯éSð%íÿÍf3hÿïÔwü;ûÿÖÙÿ/¯/ú?©Ä<¿W9Q`Äa’ú©Ÿ”Í!# «xcÒ‹è ‡w—>ÃÉgØ+þCý¦å?Ük[iô›2¬þzwú‡Jm÷)Ñî¯ÕGvÿ¡uÀ¡Í%ûUiÉXwié`«nFÿF·{Ò­•Ç®÷Üf­þß2¹x£{ §ŒÆ·é% A~qÁŽýßžýEH6§µz3ÅÝ‘¤•Y-[[áæøæØÓùy#ž?ÝúÍ$<­õÔeæãQ`P ’%#TcPàB…`ÇfeQ—dLx­þ2`®Nk'íN>–¾í¿Ü›®ôa ˃‡:­uuƒý‹ÁCÖkõú·AA²Ö5¡—fÀÝÚkùU¢.¨Ì©B‡ï4 ½^ÔQ7ùR’kö_-êEI¿ö&zPøëåæa&è.ß\†ùè»Äï×2Ÿå®¾Fù¬·õ\Vyu:oA^·í‚þËŽÿÿûÔ^ZÍMpg°ÿ·Û5•ÿ»ù Õhîìÿ;ûÿÖÅÿÿåÊÆ$xÖ]FsÛ=°Y[ó±( Ç¿½zü¯ÊÐæèK~ð’ÿIS¢ôNi$Xý×M¯ßÐw¯hå?Þ„‡›ŸdÖNPº1§ mðÖ1ü«ÃSÀอ:o?Ö¨/ÊÁC«ö;jžg, ¤2Ý3¸Æ,ýl¶iñãnþ1Äc±zèŒlNÃ?àÛ÷®éÚtæNoGSo‡zLo7ê'y+KyšQò,ÞÍiÞæ÷|>À¥çZ^eoY¨ T!ܼ§$è³1±a‚— »„Õ ¿ak*Ñoðýx·òÜwPþŸ8mà•a_DßõþüÿW5¡Q¯ Öv½èø‘@xšÏ„¼'Y£¬3¦7žœ9 Ü,ã ý5uÌqÕYo;¼Ê;à—ãZ¢ð¥cà£Ær­!?f>i¼Æk´®æ.å’“)ÖpÆ›äùdR…ÁdÀ€vFe nΓlpã*‰怴̀?Q„ˆ"«”IÜV²¸ (¶·9-£Ü†ɾ9±.Ã~@G˜®’ @§su"£~)‡qvG½/'Àf:´+£î“«Šëղ݀Q=á£)t6zô¬¹¤²¯Kð¨ü«xOêRá븛bG?vmÏèIt{Ø4(fNÇÇøKÁYf,Í/h‹Ç"£jŠPGÌ£+cð±t­YxØÏõ”ÐWÕñ=—ùÈ0QGZ ±p0ÈEg”B°_(8M#åÏh·§Ï(ú¹Êó³N«˜¶Þ?‹š}Õ;Ã(ØS Rs‚â™±a¹¬?þ†Í¶?¹åó§Žð}ô— Ú{ ý;Äw´àÜ$RwH49xÞÖöVýOØFœØ¢»5êD ]¦ÝK‹À“LhêÍÉ[³˜ o¢.?1ú¼1Æ‹¸Ý­'¼6 *H+S2h'…³±Áˆê=:öì ×ù W1Ì™ ÷³<¿ãâxÂèòN·wâ8$ší…MÙT…]xÍ´yz*¼RÂŒœo»ô÷ÝõÕy«Ö.d¿Ø ªúwfÿÃsÕ½šFþ@ú.?0õG¶;¢Ú§¶oþ÷–ø¸¼‹°4üL×3C¾ð±ßÂû8sòî 0õ"ác¦” †Ë–à™EjÒ [<>{°¦¦{›°åàÊŒ«„Áþ™ì`:Ûö¾¨± lnNírziàà¶FÇeÒ$>h—™9†¹4ƒ¥81â3£"q*)mÓµ— Y­Ñ4)HZ—<Þžµ”[éàçëóîn®o>´R&SóµÙÍLjLg±‡ÿru9ì£,+è*\ùckiÚSï0ºCÞ­¦—é•°0ÚmqÎÅ·~I„î²òÁôL—±žŸúNnêÛ¨lúøÁà`8w‘ˆÏbŸiÐô8TÙì<˜â¨E¿”;³ãËvŽ*–”Ðd}ñ'yaÃ$çÜ ›Hs®¼¬8#õ¥Å½Õbá¸ÌŸkŽéâìk%Ští¥ÓöÝö‘ì[¾’òd:(Mv‘ˆžCSâ(a òOŽÜÁŽb‹œ Ú*\žYJe¾hñ’·º‡˜û¬ìY'ÖÖ%}%Z‹8•u; Nå4Kp.græ¹Úàsu <ÎÌ+ñïïi&ÿïØšZ>î‹çuj­PþWsçÿÝù·Îÿ{Ñ¿êñŠcb~ù_³”ü¯ž—Ùø~’ðuÓ9}a¯U9°ËÎÇz)ýŸúçòs~óéSïúâ=Ä¡a/‡ÀgÊž<£¸ŽK8r„ÊHÓûTÎõ­¨Äd0½>Ê» º ûN<<ŠÅ„´‘4°v«¥qf®™¦÷™80gÌëÂVçHë" ûM§•ŸÖnukÝWawöož<*?ÏËS¯¨ ¹ê) ³Ôˆn˜R¤+ÈæÁÔ¥‚@ë'/…fT¦Šî—Ïë1fšÓóä$çÑßäM`*;-¬Ý>9í&§…1õìIýìÁææMž¥!Wù y@aÕEËb«CeûÉP^HsÏ25{êþSRêYIJíN½ÛÍ‹³Gä.¿Ll×[¿ý¯Æ/ú#>sò9/Ïh4|ò•JoJ]{Ѷ¦c*Ö3æ>ÓÉÁÁþÏ+×†ÛÆ÷æ¨r8Óì?°O¦–} ‰#‚ÏÝòú½¾¼*/ó«ÝivÛŒ™_ŒÌeÄÝ7˜GÜC\÷¬àãNiÑJyYibíN»®¦Î%¥‰É·Ê’þÕî€Üé_½d`1¨@O–ÇÑÝeOr*-Nh5—‡Y(ÓŠ´žXì‰ÐÒ¾K¸õsƒ%,“{F¨`¹£‡tz^­. ÝìL *•g:³°œ¬»öI­¥¦ýéYwåS Eûì¹g¹ËèKøåõ 7L¥µÑ‹(Nd“ÅB^“(CQΤˆ<¹ö‰Žû“Ølˆ¶fR&kMf3BÂší¡¨ ˜¬¾÷·ÿ³³ãÈ=‚R.Ûlÿ¯uÚM5ÿ«öÿ“öÉÎþ¿³ÿo›ýÿíEÿcïóÕ°zÞ;ÿáòúû·ß‚ @á“9W¹ ß<ãûª¹Z:Uïy>Ò«y{ñ¡Úû<¼©bÐÕÛ?€P@r³™ù[uj̓…ò1ð}êýT½ê_¿}E?AÔôXÓUîÜœŽ‚üC½Ž» Ë@–á=õ´â@Ðö²=¡:ɉ€ÊÄ…)ÁxйáWnÜ[0‘WzþÊMÊy½d¡6HaiGÙæiíTE¯÷Ÿó>ùí'ß±™çD1Óx°ÎF³¡ØÒµGEµ1ÀECy¸_¬e>lž6ON“9½+{dF|Fi “Ê:H]“ŒÍ|°…WEÄéÉ|ªlo´Á¼¯@O% wOU®i³Ã]ó´Ó9ÉÅÓ¼w0µ–ÆÁÁÛÀBzKÖ¦CJZ“ÌÍpƒo*{øÚh{5§zï¸þut¿%ØàÐŽ'÷p Uò'éõÜõÛ»ˆ ªƒ!(òW´ d™:ëÂËg’œöƒ˜™±Ž‘ Óˆ–a%HísyÊMÝK´#¤JEv…+&‘Èc4¼¿¯Ð·~/ú6Q8ƒ¬0/|2G®SB„b .:«%nSó%"‰Ø´@etô³TÕš2RêR.­ÃÆ ƒà=˜3¶÷H!h*Õv–a)aé¶uHÍRòþwî1C<àDMiÒh¢vÛJ€Å4КåÒ‰•+$‡œŽ±(™©5¬ÆÃÔ¹7Ew„›eÂìïŽRÞ¡Z$?ç7}ãúfh|\^o ~þôáx´0-……_†JS†ú°<~ÕÚi·vª™fÒ#•6@Ez—•"5­Ú«F% Ͷj{iPj uúò&³lgÑØ3hœY-®Ø"ÀÕ‰7lóH8°Ää¤ì¬¹P®Ë=Ú¿O9”ؽånhkïdYÅÆ-$co¼„>ÎÝÕ‰”o/®ž6NUÒè«¡ö‡ ßè\SëŠ)–Czm|rØ#&p“f‘‰9ŒÐ^d.ÓpÖ3…•èN†I4f$@3<ã® ›º L:ƒðâ·Q½àõ´¨!\+u}Kxá[k>àõmºÆñ½¹Cgÿæòÿ´‡MÔ‘†ÿ^ï4‚øïÚ.ÿgÿß:û¿Dù=¢¾7aß› &|-õQð=ÿöòr²~Û#‡Œ5V‚*|e({¬9çw½¥“K«AMH¹=÷Aèï-FSkµ5Ĩ7‘TefÚs\eT£ç3Nä«XíØ2ò›P‡êsq>A.†¦,.Ð.£ÞÐÄ¡ä¾êýsd+“ ûÂŒ±ô»ÿœ.ÿ€ç½¿|îßýl0ü+ããÍÍñ‡ÞÝÑàó§öùïn>á/Æ?ôïúÆ<`P ˜qswÑ¿3>@ ð >Ž¿TBC+§ñ>¨‘…ãÁM•.\ð/þ¯&ýPü<8Ã?~¾&;.Þ…ŒÁðîöfpð†ysôÿ—ÕXVâk½Y«w´ýˆÄ×<éêqé¬PQ³ÖhåHg-=›Dh5;ݬ٬ahýh=ŒaCô‹Ûå1Œ2+.œ‚'l~0'r⯼©óF¦ ¥ïBŸtjµG¼ûû44I_ Ó2‡%ã}žcP^2BÞ§^´9WRêf½‰÷ˆZLêfP£l•¯(ƒµeKR ³ar9ŽôÉ»^!u.ïôýoÁÄ£{eøâxaý³Ô'8‚–ærå…BY†Ÿ‰àþhHÖÕ‹Â ·¥›ŸeŸ¾¢(<ºëº€”îÊéúI¡õú£F£ 'P ûä±2°»”è ÔH® V›Â£¸ ßz·ÓÈå׉9˺&Âã‘dŠ×WnŒI%©Ü’˜rø/¼Í©òzëÝÓzóU ýi-÷Ÿ—1Ë|U®Ï6H ôì%á

6KÎÕKÿô3œÓÎàG*Øÿ‘oPêŸ$ƒ9žÙó3¡Y°Zž¶k.7²Æ7ü¥ŠÅD}Óã²YsœèLDs$üà:Îò(ï|&EúΙñspø¦Â‚†jRÚÁ/ ˜Ü gVîÞùy0`æÐ_e.æ:³Z­­"„EÙ¯EG´ÖÚÌ–/²<0ŸL>Z" Û{\"¿k®ª:,hšíY< eÆd³§¹ D ¬jJµ¨ì‘™w:už4-&ºE«‰VU–@_£§oç…·ÉI£Ö¬©KûuMsÞbÑŰÒ.\çÞŠ‘ãöîæC?] ½ˆ"@Œ˜À!'Cvñr0”"ÄS«êElœZµQë6b©Uõof>ÃN÷ÕùbEbCÀ¢z”´½òŽ L ® J☌ɉÔ)4œ»õd9|9™_a¹ncT8à¶7üAdz½%ƒÊ@r™#Ι!Nz]Í>W‘?dS>&¿ˆ»w¨ÇU³}÷%¨‹k•{-’CÅUŒÂй¶P¹ùC’KèX×?[ç~H¼éu;h¶›RÈ|²ÞýóùÈ´>‡àþ°ó;d³ÿÛs5Á¬º(Ùbÿ¯Ã¶¡Øÿëÿ€õÆÎþ¿³ÿo›ýÿòZÍÙ¬Þ~ €ØT%EÙøxŠt©ñ¶×™NñlѾ¹ºúÐ;ÿs‚ýß5õ²g«Ð!„‹ ­{Y.oõ‡››?¿¢W bÌ×t è=™7'$bÔÖñ¤ŽN®`ú—†ÀÎS¢s X'yzLé1I9êB•ÁãéÑ"<í@º·'®S¼«À»žµ7“+rrÒht»¥åŠ{VÒsz¶!¹¡Öm¶š¯ãˆê†Hƒµ}!oó”NÕDå‹GùVv‡¯Iä eÑAFè.— Tºd“éI0œ¨Fý݉‘Íü/,ÿkeHˆÉ‘Ò‘œ­ºì¼‚Z·U¯«A¤†yU9`§nŠ!CìzÔT9âd@Š& ?3¶ãtU„DAÌt!xF΂0°4ýU /Rcok¹LþAÕ#L÷×—W•ƒž…ò«ÿî°rÀv&­°¤šJãê¶Ú­ZVŽ¡":±TBÝVç¤ÝHŒ½66Î%Ômuk§Wäê¶N[­—F~ —¬†à(Ä›¤›ÂMfäs~,+­H@ôq}Êb´é¶;µV7Ñ&çYl£Sc›¹`Ò®@E-¦¡õZ‚Õ´Ð )—U,®-0¡&ÜÁwÖÔWûo"#Óæñ:¡øïN»µãßÙ·ÎþÇÊõûZ¯$-,|]*Ì×3 'LƒuMÃÁd³W J¦2¬Ã t–ì·?•h-Ž“¬ÆßÐøôÙ`‚¼(;^¿;íNiváÐg`‡Í¿Þè´^Œ€½ gŒN·›…}C¿;ÃÒ§2ñyÈ+2Þ˜³®ó?ŸÖÔ[Ý{° 1+žà8=úfÙÙùr°—†ù`Ú娛'µ@²¿ÎÞg ÄÙôN[õv£•Õ¤7ÀÇÑF%‹f/uÐÑRÌúa|GP›ƒx\iΓéÎÉ%Ë[ó£ø›Ã;Ãö`Ï«¸Ÿœµã¶=ÿƒÁ¿#¥.¾ÜËçe1Xüò9Œ–®Í‚W¿XÖMÒ£/h^6eQ`²9žx6î-k.û’92FPõ½…Ž7ør"“'Ÿ3m 8N°Æ‚ìAk·ÌÄF¤ñ1ÌåÞaI|!(r1Œƒø H{T­²ß(ä¿ùâá²±ýÆëíÆÆG+æíeÌJ¦èŸ#ã~µ„ÂE£ššâ¡¹êñ°Óp;·Æä/`”9Ž çšÙé éY“ÍÉ©í- 2¢æ5ýðe®8¤Ÿ°!-áÓdg1nÜ#ÃúUˆF’š¢Z–Oà5c…K ÚÖ«qWó¹Ð¬üuÊþxvVþã<Ó}–o!×:µx…ögŒõD¤é]ÿöJÒF‘%{ËÁ½Ì­)­)$‚K€ÈêÜ蜜œjõ©¸2¥»6:'Ýz½Q{5ÏÔßh©'Ÿ—ql¼ê²Èùž‰+\ÆÂ§fÇGǧT³†ä»Yˆž¿»³Éçòý”zä\û¬™Uì­Ñ–åx›:Ýú‰«ílJÐ?~Ù÷Dò(t/™=t¥žNË= ÁIwb¹ƒ_Œ/úܙ͜9•ÁÞ£ Ò\¦¹ÒÒ®¯,ÛÕžCÛñd)‹›ámÜpM~þ4é´$°5·ÚS–jÚP£†¢\N²ÛÖ6¤ÄéîoÀcFþ¼l ý'ÕÿÓªwAüŸVëdçÿÙù¶Íÿóãåð‡ß/úOŽtÔx·Ó58G½,ÖËý½ÏWÃmÀ Žúš>ž¨nÜt „Ñ)ÃÓ£õ¤<òjÛO‰>­6räô³F+BÂ)ÄÈodz!œ5‹‡W˜uëÈó£¼!“YàuÙÞžz#ˆ·»¦»GëÛløBãû*ôDÖãT@"¼ñe+£B§h´’ ÀG¶!Y°Óm6^%Y!4p‘örš³Øt¸1Éù®sø,ÊZrÃ9y¡–¾Zó±ãJ˜¥Xè¥ Æ?û/€d%C³7ýÁ ŽKhB5áà ]6aRô d@r–=«I¤ç ÇÞc‘wÙôaœb ó’®/¯ÄêG‹n¦*ßxzɉëof~±ÄΡ­CØ`Ž$·d`ÿáÉ5=–£Â¦ŸÀÀ‘8l–’ŸHØ2´2D/¤AD±vjCy ¨¥"gýzc¨1øø±QZí™Rp.ðYPã_Ã.¶hÿ¨E Ñ?…a"Øq=\(W³Qo6’]þ}œFèÎÍ#59ÝÐ%÷Õ†m×¶ @fœ ù”uH¾å÷`£»-,i[ö©KŠèºc²=*òØBS` >¹iÉû:š:ƒ-‚k€eS kÚÂq¦èF´~³—’©EP‹à¤/!”†½]ÏIõÁÛdýº–p¤§Œƒñ=bͬ™ã>ŸE Œ1 [}=†ªjŒ¹=EîŒù2iñ½¤Áð«H±¬´'è½ÎI­•9FÂʶ§Ð!(ÞÜóÊI¤‚¶œj3!ÉÙ¸MÉ‚MÖlÖT6™ü—ÛÑÀh²f³yZk½6 Y´Õäæúºž”p¥vG÷•ß—!lZ¥¡a(Voõ±5Ž«¾z{ssÕ¿È /¨€0…íBïo¾7€ÖlÕê±ôiέÈËúK jm¥ç+›l[°µrZÎr¹¾tãêx¼"Wâ.?ì[æWn >#ÖËøÿZÅÿ×Àü¯ZcçÿÛùÿ¶’ÿŸ‰ˆëñ¿7 Cuö¢Š9—˜Ï PNa‚—·Ôæ<±pö¼dFxY~H-?(žO|Ä$(.>ªgóz#Gt]ÆøØQ*‹<>ØŸ‡|pk*™J>X7£‘=¨Ñ-Rýž1^¡!d—Î@¿û‡ÀŸÏ+xŽß0ì#k ªØB{ðR»e4;ívW…D‰|%|ëÐ0‡ÔÛp,Oaä© mä´ ¾…¶0F\,O^LÌ÷G D9UN¢zYˆ©7CuµÄ=M#¢½ú°œ¦©/d,ÖrmgåE•›4Gس‘“ãâ’£ã$Ï ­¶ä~ÊÞæéy¾Ë}œ7¡Ù3ª¶áMPbt1‰)¬K<¡I(Y‡ÐÑ¥2OT'™`…0C>ÙP4/Zæ'R `16 ùÛåLÍÍ´=Jaýzà,&ͳðk,œÓÚOø¥‡†à8ä\ïizÇzà9hµþ(E=/Τ&ÂoÆ,÷x»#jN |ÅñªF3«B™5a9.4‚ªÔ.<ù,Îfó’ãr3½ÎÈÄy»J›€ëKCX¡Kƒæ xîøÀoÃÈù–Æ×]L›«@ÄÓ¸O¦GäÓ¯QãeÏG62ûlÅ(±¾²Ç¯5J~ý›¥9ìK®=B_±Ìia™¢ÚS‰sùQ rœW¬jÍÇÇl3¤øOñxS@Ÿ53áD?òoÚØ]žà=1G2j´3Î%p‚€kõµçB”$›œ²¾ÝüH˜3N¸û¾ü¤Ð¯Râæ²© Ñãá{ƘžºaH@9J»ÖøHÌ…ãyöýôÙpæV†i¡ iÖØ£°+°Ùé6³fñM‘þKœÆÓ¼„±èQþ7Õs¬¶ ž·p™l(±P:-½­öZf·ã­á¹ÔŒ¹%8/sÛøòñ…,4[àÂŒ±+ÿÞœ˜äÿ‹t[¿Xþ_»ÕiòÿÚõF{çÿÛùÿ¶Íÿ÷6óðöw—8¾§¯êÌü­:q-K9œ‹o/>PàXõSï§êÇ»~_ñ Þ&!CF±OË D'ãÛWô FN5}‚é}½-yƒ CV†‹0ܹò¨¬¹Dç`¸Vr ·q‰rsdVà_yªU^ e‰‘óPÇk5•ŠÂÎg ~²àÍÍÇz’•°üÁ” ÈÄ!é“•ÄXR€,ÐY±ùøÜc qÁV¶ºªƒE{T44UÜ5Ý< EG#Š"ŒÎ–yJÐ…,9 S_ÊEÓ£‹-ñãZK)ÒRåì[y\P&C‘ÍBfú™:ô J„Î{ùÆËÍmcȧsì0$€|„økÍù»xczˆJ†“%¢ZpéÀ¾ì"Ñ ¦Õðu"æô’›mø’CóyN~©C!Ù(¸5O¨úÞ"«†|MÒlÀ<Ì1õ¡-ÔvlÓœÉÈÏ(ÊÚ‚õû|b»Þ2˜ÐDóÚµf¦=—y,]sb ×ÂWKaB‡^PL7™&Žš"#ÇÂq+Y%í *¸ÉÊeÔp‰*ºNÕkÑ%üF6srv˜È£ZÂýLØÌï‹·×±¿ºh {Äõ­¢áFæŠáÄAOü]l(/KÀ†^Nt¥“snØ1¦®¨Á ®m„!œÊeX²–õYÂ3²?ÿfpQDSãWLƒ2á´hÓ¦‘›S}Òî‹i„dÎ&ØÍ{¿\Î_Ð`kœv1\·Õê¶O:y2â„Ñigâ×`ú™ÿ<æÇ¡+ î|sëÉòì|â_Ð?áœ9â@–ýÝN— ±«~úþ÷Œþ×GwøïV·Ùml·ÿ>%ÆÜžûè|Â6Z—R`î]HŸU=AŽÛ›Áðû»> ã HÔé~¼ˆ•¨PÇgö¤JJÇ3ÎàÍBuÒè:*¼JË)÷ÀßL‚’ U^°×Ë#×$,¥ò¨Õ•m5f·i‘Dt­v½vED÷áy³`¥ÿ>™xÙñ £YðZív½»-™‘꼋›þ…õ>÷1mcùyÐÝ–Êf¨8åTS|«•RÊé G§¡v?#dŒ¥5³ ù‰9²§6¡Ë?9î"(¶—r¬1òm³3®¬gbz,h‰ÎyKg ÿjM©ã,ŽÈ„toÁyÓ“7¾Td8Ã8íðmDœÂød´Ýé³,‰Sù7¼T=š_mgå ú˜0èÔS*Ü}°<×OVS.àãUÜ"'´9cØô¼'Jÿ$øè¬¦cc#àÂU~ÓEpT„`r¶G’Ï;WéP×ÅãJàê “×6µ°©â`šòâôíWsêÝWoó춤«æ4Øæò÷&þ·À÷ã=ø=&°²üOòï¹°ßsòR=ÀÉþßZ§Ölò?ÛÍNmçÿÝù·.ÿsØ»¾èÝÁáöCõæÃŸ@¥} þ_ǧz 7ÌEtãÚ”Ùa`ÂqÀé,QåÊœ?¬ÌË8¸¹¹¸¸:La,¿†(0 ÿƒ#èüaùã ï.¯¿¯^õ¯¿þðšþàÈ©R; ÒÕ9¿yG¤ pÄ•’2ê\?a4´—•™.ª—<ƒÕÂréuF—3–|Eû«m=”ä W™eŠ—ž\Úi´k+Mrné^|RiØí›è¾ÀÓén"ѯÝ=9Ѱ¨¢ˆÉC$¡Ì¿rÌ]‚ý×Ëþ¾5×ödÅÁÍqýùêÊ?Vö áF26øPº3²Í¥ŠÍ“÷ðy›ÜZä²ËdÚÚ.’ħèµV-´¼KmÆ]'×¥6ïî¹M×\ýP´ÃiÚý—ÿíƒ^âþÒ9©â¿;õÚ.þ{wÿßþøoi8ü'âtFDëÆ_î%B…â$ýŒ&¿¼¾^ö®.ÿ§â[¤îlUØ·œëÆ~GCInI¼wÚ¨m$è›ÇøÇE~WÙ]psá߬þøpº*°ð€wº­n--Æê îB:t•ˆ! %¼ÆÄ”®{IÍT^F¸øI]˳}¥pñ“FG…䊴ÄhÃg’-ÊØ_€i¹¼ñâLL«’Ý¿«ÃâD‰oGœj¨ïÓÃO¥[:†š¿6R2 9ëPQ„è£ù•t "xÎí‰S\,UÅN1Óêbå.ÐZŒjɱ©'§'Z¡ØT8ªMÂtÔÄ·1ñ¤ì[¿ˆ¸Q ¾·,/¦®[o%ÆÔ-ÞÓø:xúPI£[ï¼4Åx\gê':ÿ@§ï°±ñb6ldIK©<fì¸öI½Þ—- IÉxjÜ–0”"çÈœ±(Á»È6æî2/l#ûÏj}oU]kªÀ«"OU«×7¥äÿ7v þã¤Ußáïì?[gÿù| «µ_½ëŸßÜ] ªïn>U/¯ÑïuÞÿF"AfYâ4>™s{±ššaÏÆ§ÄX±5…æÔB£‚éûW}èDÑo¢7lDš~bê ýuz±Úذ¡\Ý _Ñ6”2[Ö6%ôu¡!‰“`ãQâp–a9JêxyÌKÚôJ´"%ÉB¦¤Ï$‡â0F6¼¯èàg^õÑðG~.k¸Uk\ëëq 'õh6êaéäÿ…ù“FZažF\:ù/ôh[»Ä¾ùo¸ë"¸=1 ÿëÍe0¨(èÞSÇó¨:¾Zé Ђ´<¿£¿ª8=«ô‚&”ÿî{ŒPµñ@%É|̾^‡Ç4j°£Z«s.æl£¼ŽÈ(²È†rÚÅb8D£8N„§ÆG²øæÎïvj)Ä©­Z»ÙEÒÜY;5T7®ç+Û[(øþ¹l iǧ• ¹„©zÕàR\ 0Nšäøhuݪ=BTÞioˆ•PG§"¿x}v'^BÞ)rl\NŒ,Öä¨U6v,fƒ÷;Ü$Åã¸(/V•cn…Ýž‹|D¶@Û=Žºœç6,×›ÍZSÍiÏbXV4ñfj±„eïÕåŸûyCbc‘ ^½Ûí&#óÅÆ™¡¢f£ÙH69j¦‘ÒÍŽ B+€Å›dv\;êkŸ6^Üij'tbÜOà”+`„#N²ßp©y‘çÓþO·wýÁ€±P'КÉ" Êéˆü>u`+`½ÙªkFîh+`©{ÎϧjDmÇ.#ñóÍ—ÓgÊzQÂ$HèIIa/Ó¹3›9sªœmrþ¿áLVÕ«§1[—0Ó£‡Ðœ?Ë Íš˜Q'[¾wÌé4ï+sÅüžñ•Õ\‡_" QOõ¯f|qfÏW^Þ—,R˜†|›ï}šU8(.a¾šN ¿ü¶ð›ÿßÂo¾+üfµð›xb(ü²†›{| ¿jÏ ¿ê­îáòX|Ný¿ÿoñwÿXøM6/þòÚ/¯'÷zo¯%üÈYÍ—…ßž™¿w)j~}XczÏ ¿+©’ —po-ŸàZR¼€1¡VÖØ5æ_§Å_öãR ô2Öük’ !L)Ó{Ÿ¬éT¤ù.ÍwqÛš× W¹|)§Ñ×û-°tûë|gÉÎiÿ%,ä $~fÌÿ„ÿ§Ø›ÿQ«7k'ýwgÿÝ6ûï§gÚŶÛî[Ð×o÷õ¯‚UÏ}±¬[ö3¥"ÒÏ ¶^g|°ß\|8Eû®Ñ5íº1]”Ó¢›6Fëuýž/`ÎÕšÔgû±–Zñ2ž9u^Aí0šZ¦{×°å£<±ÒÄΪ|Lðœª#¥jH©®ì{×tm:§KdŒPÎÍíZ§s*R7e©ŒK",Kà‹?óưî¤\qQ ÚÈŒ/Ÿ•½ÑZá–ŠR=úáÝžZ¨Ž0äëžú“=~Œ·a:ÀWöPÜ©Ãjd¢@øèçVö¾Úf !s½:uÌqua.ßJÞlÇMK^eoé1r¾[yî;¨û]œÀ oo<æ;€1™šôßcÓ±´HX†N·²‡Êˆ,𮥴/KëÄðËÖUöôæ…Ä…ìW§£ýC Иt›Óg²ðäüC\«ÖœÎ'ÍF_õ¢ãçte¶ƒ³«Fš2Mo<9cA>–ñ†þ¢©à,Œ7£)vçÝØãvC,ú Ê3ë¥ÍÙ`¤KÙ’Hë¦7*{ryÙ^ô˜0ÖC¢øÚlþŒÊœNSÅU7Li›.î‘,’®«™Äm%Š{RI„±µ€¼­Èiåé:Hö[=:žŽÖ˜|Ÿãa ¥Îñ8Z[ÑO†'v„7¥ÇÕÚËŠ¬¦â ÙÈvk§§|·K®*n\ËvÓÇ<Âi5`1ÑÁ*|·t¸]ÞæxŒ9•½=#Îy7"(݃s¶g8sÆe¥Qæ¶P'¬Ç€Ã;–Ê¢Aq£¢PÇkáßìÖ µš#ûƒ7¤ž©¥³–¤Á%•CV|• ̘¨ØÎ ‚š+äÜZò¡Ê2¢â݆xÊ©ñynÿÆê¹¼X«™Qª OSçpÅvŸèE!“ÊÊ[^¤ÕöD¬þ¶ÀöÅ„[t%ÍËgY1½C ¤ëuI@¹åèJ úÈ™ÍVs!?AËžOÛ$/tÊv.ŒåkîݧmÉà%lëù6j ¼]_Ÿvj-~„À3¨i{iÍs‰«éÕ4ò:cÁÍ.¥#ÛQ½SÛ÷xK|\Þêð‹*}&ŸÁ™!_ @±Çøo\gQ°|\ÜÝÜV/¯/ú?Åûo䫊OE«RÞ·Lùí¼ ˆVIÅ`?£ Zp"pÂ'9T^g³sj—Ýg™ñÔãÔñ7D]¤Pèx0Ù%ÔMóØØXÛCl9d4GÜo®ŠÉÊTŠÆøÙÇ0Ï«49–·»>BY{®âý©êëqs ƒ®3õà~l1'»K¹+¨×äúR0RBc/çsçâƒV·Ñ”\@•N8~…Apžæ¸éÇö>5“!úËÓчp»#Áw :ÁbŸ)ßEÄò°o쇹ã*ˆ8zcß­¦™µï§õµo½ÖiŠÐ>,pëµï­k;täãF£u\?Êz2–ØF·cceÊãþï+ &*m̺c éïyÿ*É[Ï^QVÙñšó qíióBÄE¢õmû]p>Ð-+Ù€YP+âmiÎí‘~ ]FbJmTam™ã nÃåw ËðjM¦Î Â2Fc‹û@/'ˆŒ¡b€$¼Çà`ÄKžµ4d ¢÷êqà+Ûíqöé†;‰eĦoNm Œ‚»ãÔò<õöŽ6û¥éxK8ÑÓõàòoù|3ì Xc÷ÈÕœM[n[Nf[‘ÐÝeZBÜM²·-WÄMȽº±6ñ³ݹòê¿ ÃùFò?e”Xuá8¨#JJÉÿ¬5NÚüÏvßÅÿìâ¶-ÿSÆVoon®ú¿¿ÐlÉšÑÑ?™ÃÖ_1ß3b„×Íù ÆànIšgÄh”’éìA?Û3¸Í”™ñ¬•²>)áÄ#@V£oOò}›Þàßµz§ÙÍC­›ššÀûL\pŽç(Ë…Y‰Hj®gÞDϸd>hz÷TE¾Hæ#2T ç·‘ UÔUȱe.Gó«eÜ#ùב¥’›±Ð^'ŽÝd¦s(W©3ª^{ÞÂÖàÐgâ G—Cž´•¦"¡„Ï«1Õ\_^ ;Âúÿ˜iÙwⓈŠvsê!.üÌùj×I†lÔ“œÀâ©-2‡2bhLC§U;MÉ4¼ˆ˜gŒ¢÷ÞbªcL*÷-L¨·j9fÓ¤ÎeÓ ;Qô£ø…ÿ?†ƒ›hÖ7 1ÿµÛ#‹J›;ø¾³åÌŒãðÌØð̉µ|F—€ðÐl÷%ƒ‚+{>v²ýÿgï϶G’´Q´o¥§ÀV­Ý!ÅœI)ÿŒ½#C]šZbäðçÊU "A $ÁÈPªúï~–¾=7ç!êÉŽ™ùwÌ!‰QÉè®”Dîææîææ6|6Gwéº8èÀ¦v«Vzñyò"’¯¢’¡vÊKÄ„Qwz­¬‰˜°UÇ+W8«}réD^bïRIÐ$I5¶–ŒûVõ¾ŠfMtn;cn-÷‹ÌŠŠèºð.Ì;N9¾Iú ò¤J]6ÐW"§’ÀËñ!$°þä⤠Òiöý™f ,Ãl²„4˦üÊgÌ%,°¤Ã©}Z³Ù‰MíË«J”ŸÕ'ÏE?»o3³úRUóMIä˨¬çËå“«y€êÔ àÖtø:øox½zqü·V§Q á¿Õ›[ûßÖþ·±øo˜ýü§³ý}HÀ}[Nî•áøXÓ:ËÔAƒKD>(††c™båCÃao4œ–AÃ=#2\­Óh¶K±ªìÊ ‰”f&dÍ— \è´Ž:ß4$ÜÎN>¸ÈçK‡~Ó¦+ªì% É“‰öNØ8l#³Ñ¥§ŽÑK‡‡ŸRÚh€)x“”òLO%)'®Öi6ŽZ­¦eW‹“ĪY1÷öWkN&q· äÒÃtCæ¼âÑ·pL?8ÌØCÌãɼq¼34Ω=*̃õ9dÞ–ŒŒ¤ˆ’UdÄ>³çh¾\⃙ì#Àü™…ɻзIFtJIIÒÏѧÀZ†L¦–¨Ç§Æi‹Ï3>8´Y"úí¹è,iÇrÚ¢ ÐªÜJ¹¨@ëWÛL , ^‹ Ç™çÂñgQZ„ýmhh&kîÿð“$ÉTúz41?‰A}öV0¹O{B¬p4ÛóÑt5¦¾xFõÅW5%Úê¯Rje*ñx?¶ú€|×b\Sì¨a#*_çÎ|úD½Î°“ÊÕâK¶ÇLâ$x8¥Þ.S´ ʼ£­7yÚåIP’:“ðdd50?˜Â§úö(|_[®Œ%fɱdÞ;›F®E½šSQƒ/c@ß²É^‰ºj¯ãrûr­^χ?³g7ûôG˳g’ý80Žy67ÓèÓwüÙwôˆ n™ÚXàRk[Á¶¼øa-é¿DËúéIÑ’–p<¢eÍIIDè CrφòêhŸi¼ Ÿ¸V𾽘y“*Þ>óðHy1Ôc ^?ئ†³\VýàOÁŽš£(¿Ù‡§òˆ¬u{~_èL_ß“‘Á9¬íÖT¤Ö’QRwʆHÝɺóRà¨ÀË£#m?üS{í¶¨¨TÔ5pQkvOC¡Öœ§Áãasœ•9,…?š×v˜Ë±›6‡4úÌÝP—&ùÿü¿<þgÑ>Û!üÏVmëÿÛúÿ6Íÿö¾m¦Pu³Á¥jbŽúÐ5ûðÝh墈¦$«O.›kž*ì?ÓøŸÇ_küxjâ6´æRù¾ƒE”¸äY2Øë±ìN¯+€ÞžsªêÊ5’Âv4VÞ‹øbOç‘©ôLl—í½ÿ+ oA€öÙÙCÕÈ'¼ÿþîgó;˽—B´•°ÉÄžÚQ¬ùçŽsøÂ´çKø»@–ÊÙÿuÇpóDj¯˜waº£•—ƽa ÷®-hÆZ‡u(¶]ûnµdðßï®mËu­4ÞݤðÍ:Œë‘¸Þ®@XÙh*QtœÀU«Ô¡+ƒræ·ð½eœZ_­©³@wî¡q6UËÊçùHu7®ÍÑmñ# ŒJëvjÝ›S¬x…Ç¡ÀÆÏ°ü4~¨HÅn§×«5áp„\`x±Ž†é èÝR¥­íÁ$/žè2þñÿ5µZ£Ò­3eH,UCжÃÝíqT§àñZg‹Ù¸©âò9$÷‡|xwGyºi$L~úBòðûS˜*×1NªÂ?þÌ1ëZ÷6b[Yc4­!ÒØÕä .“ Aþ}ÝžOh¥>žÃánˆsÛ[üä¸_¤ìÄlIz{‘^Ÿzí»‰!_7ΗãuÈ¿rÍÑÔJ`šÆ1öôº,»°G®ã9“¥ñ(°Î£§w7p$À5 Wd½sq9¢ëÑuƫђTq–䄦`}‰hsà:ãG¬@¥ÃªÆY¶ ·4§SSÙÝgÊG…×y¨]6ÚÞQ]Nƒ9¨¯IˆËÊjÇ#qá1%)'Ïcˆ8jtpi}XÙÓ$v ¨ãÁš.,טúÕÊ £z©‹ýñØ(s Xp¡4»­V-F+–Úw£ÑBèÚÂü‰Õ{‘H´…õfpM­²ˆnÖˆè›Õœ * oÞØùÜ {5~׆Oå‘(ʵ÷¾Q5Ò´SEr ñŠl›Ó‡¶ìù/ø[…ÎpIú@Z“µ†Wkðñ`æµq—Ï)‹7ƒ¹*÷:Ÿ›<§k ~ŸàSÆ5ÁEš#LWÞà E8Á ±D÷4oï#ÆäëX» ËñžZSk¹v{ˆË(9ˆ¿¯¼|'¦¸Ö\ÓqÃnɳª‘’ìqÙ‹Lßø©{-sdR¢ßn ©ÓRBF1z+8O*²ÚütZ²|Sb¦)n„"ØžT(DT(Ào†ÊÙÇÊàç³ÛáíÛÌ£>eÁeEž‹Ê,ŠKbBnÐLúœÑ%ÕBßQuefþQ™¸–UQr3O?Må¢ÿsåãÍ`PáÄ]]æàë'çј!Fv£ÅýzÎj:FÓ.ˆýbY‹‚ã „ Ê1 >ö?Ÿ¥Çým®]Á[ ­3ðÿr(¥MGn}–kÒL›šQ\ˆ`[Ô`R"9ˆh¹pÎ.φgýó³ÿ­„6å9–Í9F~sÑ£ô¨c-é!$½(ºš‘0uŽ)þšnú™ ÕuˆŠˆŽ‰ÉLì å°R.‚¡Ì,&/¸xC™×¡ÃŒ”¦g±­M_(€'6Ô%?w#FŽ‹†8‡é:,D&íĿެ9ŠøÐö^p& ĪP gÝ{cªäópMšTàÐH½<¦#¶!6 B#€:‘‘H f?wFLŒ…βÁ {ùÆãêÏõX묈<ßüƒ¢Rl­Êz€TE; Ñ‹…†Ô5z3È»Do¬ Ü©Í;·<¥NÙèwÖòÑ¢µ Ûñ`/áÒvúáâ¶³Õ˜Õ÷,X53Ù× °–pЂÞ;c±0æ³Z*éþ±Tì|cFë—'ɽ‚å!7Ï«z¡Ïâ)HÔéàvxsõK~ªx{Þºt-\ç.Ī뛫8…®3tKÁÛ©.Ô QHøòAEå.\tÒôd[pWXŽD–ÂÊO1%0pXrÁ„›FÛôÅÖ&p‚ìþélø)?·X£-L Gc5ÇLÏ4DÆ7|¹Â:1 5òDä>®sÖ²E_ØÀ÷ŠR]‹6”´%+£J&D ¿º¦ÉÅ#qÌœUé*YÈdMc «JPaö7ŒÔ»\bÝ¥ f¹¨;ÜTn¹öήM;JweÞï+t ß¹&bé¬Oƒ÷YT J(Cewõ ƒ B•Ó§JÊtœ_ôÏÏ©¬=-笿ç›1 ´Ù#Z–Äžo’à2´t܈±TPu±¤Îu;¼º‰Iušì¢JƸܰnDù×pP"^í¬¨$ P$K,Ò×aÚRÖãÇ3˜²µãî΀-C:2“F) NW®R@Ý2ÖµëûzÈà›‘ð„þuW¤þ’PægÂWg¿õÜôÈ4Y”¸ŠßˆOgeðó5¬¶Û³«Ëü${‚f¿åÝÁZrkP/K)Ä_]núÃri7}êEõ&R²J‚ã†Fpu“Óà«Ña.W´¤‡%ûZS‹˜ŒÇS©C€!“Ì©A.ÀSkB7\ À0ç÷+óÞ2ö±TàÁÚzE¸ ã{µ’cö9Þ”X=¦‚ª*UI¢â¦ù:…6J"‡n!ô¾v!zns/*SšHuÚ ®yz—»†* N‘Æ]S•ëìv|y‰Ã¥s‘[‡“|µaiU}±ýx6øiµF _j =´ÒrQƒ Í+‡ZhTwV]gHM)ËŒµ\ˆ2|5¸È®çZcÅyÈ—˜š¤Ê×G^c‘±&‹¯2•$¿Zsa¶9´Îè}]¢Aåˆ4ÑzAs.¼\nDÜs­·5˜i.Yºfqî‡7g>sÚ™UÅCøE4­Cv¶ÆÄëk @';ÿBv‘zÙ!s¦2Ö¯{ËF£p[ˆç~£ ‘‰ÂVøZɳ~_áÊÓ…Òíàß?.OÖQ´dÃÅES€6’N¹) ¨õèb¥EyÚ ÂJ‘S~Ånüõ °4>—¼Z·’jxl¤ø¼;,äø‡¶ ‹Åb#È`ùÔbºvÚËÁÏÃn<Ø‹¬Ü:Ì"°Êå«¿d+Я­^¥þÊE|²³\Wê[L‚gåtX«¥Ò —uª.´áo>_žrœ1Y€Ø˜tµ9dºç¡P è²/·ž¾ZÖ¿LÏäeúÇð]úœۋ‹XÕnÓeܦÍÑ¿LWxqwá‘¡ƒý“Oür]Õps6¸n’ìQK·Ü‘Á[yèÕõ`¢UÑ%ñ´ ‘Ë™/–~ <ÌÂ#Zx`y,FKãñÐ-éÇotÛsÏr—t¼»cOª”·ƒ›a½ï7§·9Ķe,W#)NV`­œkòj1ÆÝ¨ûùú·b^b?S[ž/ñˆb:WË¢‚Ží©¢ótp>(@'ÅV[‚a&,ƒ›ó%V0Ú”¡ápÑ9AE÷äêâ¢yšß3É,›¼QŽY,p”ççu1Šqc‰Ä=ÜJ¿¥Ž"aëú5_·¤ÕrÑP\¹]`@GE%øúæìrXÉG6……xLáÙŒ‰¥„ +• Áµ¬Ã›þåmÿ$—¦{µ ¸5¥Iãnꌾ wžÍl?ûââl˜C)Áw1)NA¸ž™c‹C¨¼Ì¤JkA‡µ3Þ™0F:?ÿÐ?ùkö[˜ƒÅ8¡— Öž«ó­˜çÔéÎqáí£3œÓy:ŒÅ4箯, V÷\¸‚'¼æx¬ †-—ʃ㈹蟞jãbk¨òéêê¯9µõ'›%ú;ÐsVsVC€uI#=ÀuÄ*i(bM% F,´‡ƒÝâXh5®5 ¼L›«¥£ma¼E÷?¯rnå!ê>(}1O  Ù,­¸us*( .,)®ˆL~³²qÝË²ãø®çϪ<±Ômœà~¾º*ÅÿÌ0Ýqe|Wᡈò¹<íßœVN?T®>ü[í“ éK6½¥gþh[%¿ZÞzÙX,¥2µæ÷ˇ`6ÖíTé*çƒË†Ÿòg²Fqùø!/ÞÚ~[–ÝBχ]¸,¹åä¼{›ß T²?¿üùùŒ÷SÇó¨ˆ'ˆ>0¹Zöú‹QG/hµŒüwßûóÆgµpZ#l¿;yñýȘoü´»@ <9¿ºeY tåsÁ2zˆ7ë )éèO ôy™>~oW&n}ZÉöÏY¡Zþ‰²¼!ß‚¥¤[5õ†x" Ñ™/Dã¤hŒáäh–GŸxªaØßHI¬Å³ÃüN²‹ãçq¡á¸H%/HCè/<‘dÄsôדÜØ”|hKÑ÷6¯Q·‡ K"·‹ºë‘Êr<‘2šAÂ)çV:vbÝRN3Èïb©´Ð…=[ÍŒùjvÇ2¼yç†#ã]pÚ¡Û$æ8ö¼¨yâÚò&.‚îŽ})Ä'hÏûx3¸ý”#G LIID©Pj`lõðnÖ2;*4GØ "qù c¤kaø"ÛËwO/t2q{À:ùº™ ~ÁµH«2;ërÚ˜}c-8höFycੵSgE>O­=¿æ¶Žë¤cÌ€[*Í^2Ñ·ëñ›z@!Q.ãå.£aDº$äV£¡sP(<ç±õTN=¶ªR®Ž\W‰ÎK³ÇD{yD‹#¥y€Õâ\ù·+`zîUŽ ‚“+%2'?¿þÃXëã?R3 гwWÆø¶$c#ËqÐ{dæF–Ù€ ºCöÛ"¶jÈU¯á^®çzXbtM$ÅbS`gñlôª¤úÑ,*¹cY„!/†P½³|g¤5.N;Ür-s¦ wèAÿ¢P0Øë˜ãFµ°VY¡Â Qþ,ÌG^hh³+0„ŠCìÙ™“Ù׉“÷ìƒâÊZh\\M+4G3ç«¥NJ}ùñ±859:=RM.ç•¥óóÑÉj¢å ®¶ØØVa›Î~®¬°Â‰øÊ¸}uv¶¶œGÛ±5WMwŽbHÞßø] MÖƒËÓÊOý›KHŸú?ž]ݸ.ú!3@>ïë«ùØr§OÈÓuÀàÛØdU\]žæ [FÁ¥í¦k0oVL oÜŸúâYqXoPMˆ»¹É‘Žõj#'²‹š¯'eÜ|ÅnþÈÅV(®—¬1{f9«exgƒ«ÏÃRWyãUô@1)6|*Šcl Ÿéa]—3Ó .üÉ0ƒS³]òéµzÜÏXÊ>X?|ÊРýl¿þΚ;k 'Ñ”uBJû‚Õã1øá“Uw…í yÛ¨ ^ÉòÔ½Œì€sV²ý‡zûä š«ä¶"ûâŒ#/½ÂPÙZãÁ[°õàò°„è#¿H òœ'ÑÈÉc‡9ñæµò²¸ºˆNež¯p…Þ&‚5º­/8/ŒŒÑj½Ö9jÕˆ)Îñç V\ˆn»Ûê6‚Z@^ݪø¥ôÒjµ¨Ä/\¸:ƒßxÅsq$4ŸÆ-}^´ª=ˆQtk­’¦7ªõ£z­Uâ,‡»hÕê\ŸÏ0Ù¡ÎÚµN«Ýè­?ç³'ß^<­³eý–…ÚWÅç3Ôb·Ù¨ÕÖžÃp³f§Wâ¼…:8j“Xw®œñˆ;H¨°uúá$¶ô@Æ©”1úëV·×Zg&ƒ 6›­Zoí‰ µÚm¶Z%Îc°ývýÙ=¹kwšþÉ` þ0±ÈÎ:ËÃÌ´>úe,38,+´–ì·Ø:j¬¿DÂÍöŽJ]#¡zµ^«¹ Ä–0j‰Eš°à /šm4ÖX¥[1ž&­Óâ3Ñd·ÞX_Œ‡Û…Õ Òæ6¢‡^£WÚä6óÎn³œÙm*#jÔ»£ÎúÓ«µÙ¨×{­’æWo¸M §ä Öº=±S ;T¹RTÜáE/‹žÆ~[œÈv層֤…›ì4iïœs«ålÉ•ÒrÊÜ­{Ö‡ÚíÂ"+s1„{è5{Y®Uñ«BÄ©)½h¡k{ïàÆ5Yyn~8«[Ãj|²È`^¾^Ã’ðÞj6ƒ†¿ß»4¿Ú÷,"V¾¥£oÅ£,3¯£ǵ´v1ú"1‰þZ:‹2)¶+k™JÂÞ»åô` –†q¼ßý—í¿¢ÿï2ÿï£ÿ:­þ¬wÛ5õ'þÚj6ÛÿgL§ÕìÖ;øyþ¯ö/Fí%°Âà+Ãø—/X ;á¹´ï¿Ñÿëÿùc6ʈ±jmϰæ#C.¾ßû<üXéí,—iêÌ-%ÎÞÿó~÷ý_§W'¥eàÒ0®?8?;1ö*ïÞýÔ-¬=´¸ã_ z@’@ùóû\ÏZ~ÏÇÂmáà¯Ùs¬O,û‡5g`ªJW§ÎèÆÿ|{nÜ.Ÿ¦˜Ž@8?Ö«ÝNµN=b©3õ¦0Jgfí©¦ý@É3²1cPº÷Æøae­Àû«Å^ ²»h"Ü=Ðb;ïe= Ç¢jšF¤½|ÈÝ¢‹Toêê[ ìØÐõj{/óî?gåÌêuˆï÷š¡£/Ãzyˆˆ3bb!5DÔvdØõ}xÆóÁyÅL0 4„9S@B¹#r'+ý‰ï,i˜–R“Cì£éÔ;ÆÜAÀˆûJ…}‡±Ù~òÅ3ì%R/¯{f>k0`ƒ:´©”{îиƒM:wÄ •}OÂÕÆú&ê8֘ňQuy ³–+¡gMO ]6Êw·*s˜Ñia  B˜Ì…Ðá¯W³‰ñä¬üÇ‘• GŸ$këýq…™cV 1BKñ`/Ív3¸>¯Ân#áùþÖ²bhÏPPFПXW&v ‰¨ã ôX[SÚSXOVU62(;$)i7 AÛMM™S,¢Ú þY 2zk/W ~)Øe›¬ØþyõNH|F¾§¶?õœ úAå©ÁŸb].yÁ8fâû½šr¥»¥½I{òÀ¥Ïè#q%{½˜²­£ÜK(Ãê YkßoàVÍJdé—ý÷)÷’2‰/W­^[ŸÎJöÆÈÁXó~’ ÏP@tZ­º"‚¸ó( q†²è7nøÚŽÔrîž„*©Ë¦Å{_'.9Ã-râ›f“Ô{Î>séSµÞuÜödKcÂí3Õš ×ä*¦9W0#®c¯à6+Ë0–èÃÒ;YÅÙSß^øëº˜‡n {Y.ß]¬-‡óôûOÎÌÊÆ ÷/CMÆ­_°Dÿ_¸TF©}¤ùÿjí®âÿ«ÿ |Ô®oý[ÿ߯ùÿõc6ßÙç`”]æŒ Þ¿ÈÊ?’D½P’§/¢ŽÔôµŠ8¯èà Îùš»è¢IùÜtyÊh®á¹‹*TT‚›Nc¨Täµ3¨DœÖ[J9'îLì-Á»Ö¬uºÝ£ò¼k—„î® ¯¹ÖbjŽ,œ~;{?'fð;Ü?Œ5g‹ï`ªSÞ³'•±cy•¹³dE ´F’ß¼Õ^yq_³Ö­×z½,?¥Ÿ¯¦kãX¸(*X”AÛ),¹èqLÅ *÷RÿvŠoÉÊx|’Ù5ŒÜŠ¢½Ž¨>¬øn”Ù¸éQs—N~ßßO ‘9Èøm ú7ô¸P×Þû·”R´ö–w]-m|‰ë:Ë@­UãÂ2ÑP>YM¼ºþ"‡u ×q-Þz E˜Ìè—Ȩ/îûûŠ›ë vº“"X3;®aß5Ž’׬8¬¶PñÞj<Û‚¬Bâå\“± ,çÂBWˆ6\èbX)¸FH`^U¾u%Ãê@bæYxq°ÞD±ž@ Â;‘vyv.NŽGt,¡€™«À0äÿ#œO{R|à¼Uh/}…—áÜoÖzmÊ8qîGxÖ÷C•_'ŽóÛÁ.;¯†»û§Ù·ÆqhÜŸFñbjË0ûú.t`@§Óªet¡÷ýEFPæa·È™s7Vœ¾œ8Œ §s#\X»Åμ ,Õ÷´µ¹}_ýy’6I)Y_ÇÈ $ÈŽQÉ€Ûo2#c°W¤Z'Þo+Ï pÍß,})›©™diKá² fò×A‘îÈfí¨Ùk½¸;2×<Îoh¤ˆ;/û>ÖQ§5Q€†˜ÒµrÖ‚lc) 5´1~EÚ!X˜6l`ü"³!°Öl:sºú ¶v¬OHD Ù‚",߫ج×êšpö*湨SO¹îCK”¡‹Š¥Øo\F«WQœoæ,×Ñî•ËÝÁ›àd ”ßzÔþ´þ?½dé}$ûÿ&|§ûÿšÎÖÿ·õÿmœÿO©’ú-øþf)¾¿¤’ñ Þ¿På\?:ïê:ÁÝYÁU¦ FTq}E¯Ÿ:ÓkzüÂ…†×óö%ÍÚ:þ¾è»%8ü$/¥~-œ}²—5ª?ƒ°Ý®÷ÔðèT`Ì…B²,›×•š&tm‚ÀÎá¼›ÈÑg~…«ø–¦"þÆHò+¬ ÒËåjd/–ïpl·;íNí5ŽIóáÔR,¿ÀÎQÒ±[Œ7jnO…•lï[Ô⊤OnݱEVF8W>Àœ½Kó •»GTuÌÒásÃüHZÓ6ólAŸ3nFdÕtF7Ÿòdkp”¬fóÝ€_.ü8¯T¾Š×€¢¦f°þì {KV±/ÎÖ¤ ÅÞyÞJoTì@6Wí žÒX Ä«¿±L*‰ŠLéW Öh¯1>3ÿæ4ý±`€¥Ã}[ÀÀýôjßaÖôl±|:Ð`ûÖø²ú®ð~À›³ÒÂÎüæq¬ àD«5ôüš¯,Ï¥ÉñŒH^‡Ÿþî$¯§tVƉê,÷œ 16³žâ˜IèîBrPá©VºÒÎàV­ñ9hþ5[+B5Š>÷Õ3_䎈fÞëPaxM<\¾åŒœÈzf†¦í,Ù}•¨ ¹™ÁCÉO?H9œÉ}îÍàÓ*;\CÍÛK˜Õ9uaޝ°‡G;°¿R:Cº¨´W¹Aín¯®¦òEaøE4#ÃÙ’ÿLtx)Vnä«?|®$óK_ Êc® ¯NÁ“KU1^ô°‚©`ñ™ZJYT»ç‘/e °N¨­bŸ×\‰yùÌrŒF&;ÔÝœÕ}Ô‘¢œÉ†åŠŽ—?áeÔ™);©)qZÙu»ÚÆ.:¥‡,`…ôË~-–c-7°8¸'¿‰Qx‡˜Ë¥kß­°Ø$—!´[›…>_Ôx ÿÑ]åL&ì º©:Y׆ŽáKØ´–T†•rÇK4Eï&ü’9mÕÍ$x@ªÈt{…^ZcŠfQ”ú¯092€ ŽˆÈßGè„1ö>³çЬ„ÅÔN.VÃ.«4‹Éa¸}G‘ìE*0âºæShD]÷0®÷®Éª™újSÖÕ®¿ƒkÍ!gŽl6‰I¬‰ÐἚûìÚ»~ %ô 7"æ\¬¼ï˜r‚òÐ/¤Çb\à€_¢EßLš$™¬x¡CÙ!F™ÊCØôxØ'ƒùT<”ŒA0æjéˆ)ŸY&Õ å³F(D=vìot!‚ ÅjÉ—;0¤aWƒ¼*ªtŠYgž–íîÛU«zÈá)G¦5¥ñ…jä @õ«‘[ÞÂ{ÈØesdòãÒ[‘F5öÍ(NøgüHà’Â\¿yCT—ö4} _ãp\›Õ]g7‚2‚ÛGN#_ð£ØÕ¸´ÏÎ cì¬0;w2uÌ¥Ö}ˆƒ»å±.Óö§ ¬ïï¿%®‰;=Ñ[] {÷­ñFE4ç÷GŽå‚ÂËý¤VŠNŘŒ¿ˆÙ‹ù×v÷I_±ÿVNÚíÙÅõù Ò¿¹éÿbœ^}Æ´áçWý¡±ß8À9$nàG÷¹-N™YP¡3¯þÒvhg±òÓ x‰GñK¬‰ ›¤8Ë•&y2LY0yïâšpWhóߪ{FUlcï´k¸±»~Áçî °‡øúË{ŒuÑ–Oêh~åôÿŠñn$ÿ7ã˜ð+(,SçÉ¢¦æŽ¥(6Sle¤­ÒÄoþ‚ÚëÏ18Ëùºgì}p­¿?Ìѳ¹w|™[ó/üþƒãÞÁ!FŸÿÕ]yü×sknÏáç5^y÷Xß{·KsJŸ]gé}y‚ß~±à¸†ÏÃæ6qÐÛ•£Nä@þ‘Ãìý²rm O2§ìÜræöXå~úW®ŒÐÈ|Ö°Eóly0í©Æ*|íÒþb/M•køéSP,g¶+Y(šQ¾`<ŧÿÍñ¬Éžd¬ Qá0ß–û{àõT†Gs\2Còù`¤Ê3üÌ+ “1ÇʲP‘²´|¦±ÚšôÊa—ÿß©Õêiz?ng¡CÔbŸ3Z—PŒ5`|„['U*¤…‘˜îæü©ºnø§Vo·_Á ºlôŽ2#Xñ+©Æ¯Ã¦VùÃ*¡ó'­â²rÃÐ#ðõ‹>Àn)ár´QÑ÷Bφ÷Ç6Kç§ÖÜlå i z¶¸óˆ[ðú68ÊT jî÷sûï æVÞÍS- jžCŽ6÷zôÁúy]™¼œëðT@‚>8«é8ÀÕÝ5m›âÆÌöî|5»³„WM|ìv̼Ît±ÿ.mߊ)—¬’ªºTSñèòÇ­®• ÑA´ÕÏ…XÛÇ’aÍ©DôuzUIîN¼V Ç(ƒË¨N¯oÎ.‡)ý*/BjKŠúЇ]sŠ¥Mà9Ì8œ$å)LÉZz@§ÞÕ²aµ<€avë¤nþùb==ÂÊ—V ?UòùRÂPf ”­ÌŠ•¡È ó<Íò6ñ#ÕPò0KGEZ:¨öL^›òè5o£¡Ä2ðO\˜•—¸9€/Wænï HWˆŠÝ&-”ÿ?‹I…8H[ô a1*## 9þ¿ÖmÔ;øøÙØÆÿoãÿ7-þÿíIÿäÓ 2$TBT¶Î·•ÓÁÇþçóáÛ?uN@髉ò)À…ð´¼bî@Ú*Y3Ÿ  7lf2A씕‘PÈ`©¼'œj%¦$ÒB©·Ú]]xfï¬X\ÎÊe%E€V4§Ig¢Œ7a¾W‰Mö#Ï›š@±çI<årÓé5ëTzUÜmüÇ"ÀBP#ó/, št‡0Cñ4²9ù,ÙnbðÂ3ÈÛ:ôcªVÕ€“)ÞÉ­Ú ¢îCÑjºGþ0ƃ>™®¼ýâ•Ó§Ëkµ²,ߺ‹€¨ŠMT{TLTŠ=kÝbFÝz› ±'„#ú÷Êø%o /y±kab^,ÄÖÚ³¨Gà¥N(FYŒi¼w9CzÂ@Ý?iA€ñë¿”JHz«ÑK¨„”ÇÎ.Íôž‚´©–yÈžÿ¡=?ºÜ ¨8ó c®QKÞçžë2‘òõ# œF³eças,0i*ÏF˜_r©<¹L0y”¶ 0ÕD,û­¥f“í?ÞïÓçA~È„ÿŽx“zýçz£Ýèní?[ûϦÙÈÃòg)ñ\Z™ xÃŽžUp÷A;ƒŸ¯o··ˆözæ6ékm20óõk5GMGö Nª¡ÐG‰Ö7ÚXNð’ç®FKžÑây䣿öÇæ=Ø{½Ö©w[­ÒÀÞU <K€eƒ}€Ëe>$}ÊKGD–´zšë‹!"Yƒ‚ÀrâÔ…Q8C6†—QݲÕ)³à)Ye„k-9£´^ëÖêå/„só õ]ÄÏ7 ÌÂß$Ç2Ä2ç¢JiqJdסÓ~j²üAiñéñLX)u>‚çô°ŽÄìFoX<3{é§þQVŠÂÜ (ÀÐF«Wˇ6 {znOEŒéÞåçóó½]öù¸&Ë/>^]‰Ï÷îLcDù7oàÏ7{»û²^“¯Ôk²¥} g‡æØ»ø|j»<„æ©¡CøN¼ö—„×BoíùÕ¢ée?†ñ±…§dØòù÷ß~3Þ ÁVÓ¯ßÓ3ÀFöþ"šßà Ó·°§à•BßmI 2ŒýããÍÕ…ñ¡ÿ¿Oý±®õ>|Q=;5¾‡oà—£yŠOW쟬­½Òbmaú[­VJ¬m!Z &:jkED’ ±©ÃÒ‘®„n½™9F64åså‰òÅaõïó-(‘ƒ››«›ø¨/­ ÅbæÇSiÛæüÉÏžçZz0«(Óº…ã8 åÈí›~ûPÂq³@J„ƒÕ'ÉæK¤ƒ€aZŒkð$ ¼O˜6dvæSÊ “¾K©¦[¯õj­£7¥æ¸$­„ˆìÁ1‡Ð€³Àƒ.’„«ëÁM˜Fl`-¢6ë?e+ˆ×Ë7ÃÂhk@f߈é¸ÐÅkCjf½å3&'ÝÕ7Àz¬o÷­áøì¿ps&uZ¦š”k N³ÿvkµ@ü_»Yooí¿[ûï¦Ù‡7Ÿ/OÇý´?ìèßþ™k€®ë \Bá똉£ÖÆšFãodÅЀK½Ëqˆ©R' Y%Z•C½*uC™ Çà_mëÑCØ¡3Nɲ Kž§Ï,Ü8ªii«kZ›C çuð{_¾ægã¨ÙRAP^Îà¼E A -±qÔm©ÑjIxˆy·j¦X¾\E(‹Ö7] ¨qtÔmôrÙ£©Ø ã’{€æ¤¿Ñ‡ ªÑwö½=‡szO'À¯údÎ ÁÃÁ2ÿöÁÀã{¼qÎs¿uÑÄâ‹ßýŽÍÀ/âEš3ÿµ)‚1x»wPoÄ3rýç&Bx0“ù~H¨ùÕ#FŽP'‘Dû_hDù‡èÀ¯JuhÖê­n#cQÇ ÐÝ'ÅÍ{ êk"ÓÍ«6"¨3‘RmÁÅ•‰1ø#…dg„°†#Öj&‚ø{eÑ‘£ÿä Éeï¿E®^-"BN;=½˜¢údh¿ØKkfÿÝóý²šF~A6=84lo´‡ê‡o<ñ–øàž?Ð$vï*_@7Ó¤K%ʉ (µ&-zâ¤Åí`¹#»Ä°ùBC„öªï[H&*Æ7d ÑÃòXs²°õäp ZÃqAçGPp^”¸JO{›,wX“-/{d%Štî‚Z¡ÛEÅñ‚GT6lGÖmƒk5gzNFQc¬ $µF\íø"¸!ç‹Ap[ºý;Œ È•¢*0ÛÄ®Cߥ–L:O4¬jL½¸Z>ÑÀ×8µsªeÂYœÏ±¨)Q‘>E¿º…t!²žxí ©ì©U0˜ýÚ;”@´Ì±˜¾¾ÚîreNc–Éo¤î˜t1¾ä$cÇb¦t˜HÆ6‹^Ò¢Æß™ ›ÚkÊ{>q²CÏ墕õn8ÿP…Ì»¡2P\O‡þ¾gGGÁÑÈ™6…‹ÇË'r¨«!Pl‚š%÷ ÒÅ2€¢ÐÌÂy.Ÿø3oºÖ±œ–¢Â~dƒ>a%‰ûT.VB$¾oAf:(S¿”jJÎŒ™¬Y´³ÃŽrX¢|WÅ9›a-&ކ„J@–&“K#Õ´„ %Qi’ % ŽS®Ê´iÁÝóùG‘A2‡×À³ yiº÷h¿â²Y{)0h˜ ››÷ƒBS²Û*–¯’âH©ƒH«‘‰ ±R™ê º ›oŠá¢@)w$# ^c–éWðT¤W Y – »ƒSÕ³&+$òQÐRdjhÈЈv¼âÃÁÁ ÇȬdvÎÌùSeéTð§ÆO×bÆzïÁ^ˆ3 šRK(bÇ#<»¦Ou7VV‘=[dòË“ pßumë«~²¦¬-;´“†¡ c¶—Öókp¹Ö8XÏ‘‡Ï€ü7&°¢h+íøšÎj¾´§ŠEìEÛ“5fG+ K ¼(J¤ÅžñV—qs0Ü uËQ¬uY­»Á¥K˜,w@ÙÙœ‹F*‘aæ=kZ¿Z‰5ÌT^:ØL¸Yi‹%HS’̵‚Úf›„ëL±:ÉtŸ%Èt±|1Ã*e2)£­«4´·ªñNLÚØZMn•6w ôb„ ÝŽi!«¢T™~aø€ðD.¨Âñ'V×+¬;°Ì'I xÑG] Óv©¾]b¯û¼[6a$ŽÅ€T2@ˆí䟪,ˆŒ“ñàЇÃóÂ%—#¤é»•o±XOû•!­–@§l·ß¨Ës¾ë¬ãæ¿d¦Ÿ´¡¡1v“Ò¾`>“îfü.N§ÜSyUPo’ž.ðç¶·à7/Ì[=d_ÉJ–‡ôæ=HuÜ„TUŽJOîDÕœµ\€á>âÒY‚›¥äN?–¬/7ðqvøh¶®Šøà¬3ó‰½ š‰}¹öx kx剢×is™Ê5õ&äƒ\+Fµõc±R$=ã{`Ùš†°ASk~¿Ä£ý¢ ÝÀÔP}Ocµ «TtteWXºï-ÇÉ­ÜoÎ.¨œ.~z«„Éj/¿e&Ÿ u+#£R†¼Ï¡-æ¡aOì?`AÅŽ9Ñà®ß“%ÐÌÔ™ß'¦[ûsMtÔewÖÉÒhFí„3£0õ‘ÓÅ¢­ñ}$uÀ…dÐ ×e&ñKÑ2HÐ)¨K£Ù¨ÜÙK¼¼­|Ýí ¡¬ÏF¾FH˜}ŸëP€Û°²& ÐaapDˆuÆ!Û0)­¤¬Ó¥=‚© ,£þ\ÂüÄìÑÂ!íjlU_ѼêPÜ=Qº…4|ßaÐùØû­ðþñf&ÞÓ «w^˜2– ‘F4Òiù›íèZÍmŒã2§ve×eÏÜ— ;LBz«ÉÄa`hRH# Lºž‘}Do®j\Í™"DPŒV}ÅBD·* ™ê˜2¥Æ/ Ä8ûáìr6pàÃ#ð5’ª‹€Æ‰$S´½ÅŒ9ðËÛ#ºá/¸1Ì|B«å£¡Áu¾ÛQg1F„V$K„kxìþÏ—ð­Dg*°’„ 'Ĭ OÇAcI$;…¡º^ gµ$Ä:6Ÿ°þ ðsIˆ7dŠ –±}v±Ì‚ãØ—†¨baéSSÑ×àä*€ÃÏmÆÀa’M¤ÿ Ã:\¹°-Ÿ‰M@‡ë`qZ†‘au1—uò¡4áÙ‰q¢vÐgâx˜f2’d#C¥šïjîifq StFUb¨µgöÔDqL~æ¼Ã%¬OË&¨™Á¦…Ó˜m¼aC,¶³yÊØ'çKÒöÆ =—GŠ/ßæF0å  ?EH@ª|zÌëÝÇþ9¦ÝóWæš«—(Ew±Ké?[ÓÛÏY{¡èÞç5ã–-ÿºØ–`¹iqM‹osÌŠðF7IVBÐb]³¸³cSþ°ÉÍ8Ì®¶3O̽‚•†q…ÐõN´;,JkŽY\.´¶´æå‚(øM1ûV´Ì÷bª%߃LÈG’éºæSEôe™)YY%…3°Ó81Ò‰;U}#ªOZÜŒo„Æ7fÍ.d ei’Å‚HX$ŠR%ƒvˆ> ~4Î|1šõ=¿ô‹2@ö.>ÄDáxs¹àý0WZ+9§–ëPåXLʘº¯Ž=ffùÄéSbrä€ÓObRú»l¿0¼ «һ̘Å® —/Z’LÚEÂëòeé·¦ 0J½Àweš5ç16q¦Sç‘ÜàÁ¦x Nµ¼çÇ”šcŒÂj*ª3r&D>»pm4÷²(^Ë<úI‘–¥ÍÕœ]Ò„J¶¯F^<‘®È5O¶tF‰­ÿÝrôænÝ_RÑ  bÏG.!yî¦ÌáùG!í+êóÉW¦ü«Ýß‘¶pˆǃåžÞ„RXi ͹Ü9Šd:o‰¼a ‹îœM$ƒ¸_]ì¬A|GÎ"rD¾6G╱‡ü},r„/š A©¢4dÑ…Ùák¤Ê$Ø%ü8Š õƜӫå/DtLÚ£8.lœâVÉjsŸëÒü‚äßO PF#FŽ'Ë[ð/ö0]<¸uOÇH¬æ$U9Ï9@íR²› O+’P%Åd©:Ôªre/i ÚWÊ!Î˼ˆÕ"B.•™ËºZ„#P[2j4YÊ:aïóÅ¢z#ùi:.:måÈ™ /ŸÈ•£Ðuè‹SádX3>)gq2ª‹'ûºñ‡½xT|jÊ‹-ŽÊhöZG5$H{TB ì¬Pš%{ÀHwÙ ,âkÑžã+_zxy52Ë †š×ÝE-õ «ÿ¨t©Šk²ÎšY¤pgŽ;‘L'‹Xö€$ Pw1)¡¨+â¿E+08xÔfJ,I èÀyž‘º$O vnÃ:§ú¢sg^QÚóFÖÌôxèÑÒ]Y‡Já)â¦DŒF§% EQÎhQÞÙOÈy kÙ¹a»WYδuo±dŽ ¨’J¼¬…¤B„¿Ë“pâN`æ…õˆ…íêµ[FrÝÐÝŠ›#ÓÝsd-@ZÚ‚1bxðyrç`Å9˜0À"yre—‘ML¦"àtÉ‚§ 3`ýS¶L˜$t‹¤Øe ›R"ÁüvÒRgÂq¶R¾'Ç—°l œô„N½““MîÑö¬âãU¯lþS»;d»Î7"²X• .ÓÕx­Á1P,kÜœ/ÉN¢nAe—…÷WC͉”f\¶\§ÑmË„Óæûäwa6å~g…{Ÿ˜†"+îòªh?R/êÙ¡pw‘ˆ¶¦S¯d‡ÊiAަ´ðñ‘ÌS†Í8þ“L$›Yæœ"äAzœ‹sÐâÈy°´á¶¯ÍçÔO”´“•=Öï+sJv½¨7hWúlÚWŠ&(Dz:y¤°1MS-MǽQ°zâ7p„Åþ¼¶¿O Î8fQÖx^°¿1ëÔLã˜ÿM·N¢ÓhÕàßî.yNI˜]^Žwÿ?öOüÔÿüÿ¾“Oïþã#9©ÿ#—Ûÿ1.ᤃµžà¿ü´†ß,]Óø?kô7<ž %>¤}üùËà»å£µËkôš,bbìãD°i ¢&öX™ù‰œ þ‰æAe#b„ÕÀxO#`G3ö¥ê;…îíÑ¥Gö§ìŽý©O|§œw,ÚâÏ{ñ™7 Ï}‘>‘ê¿BkÀ™ýzý@öyE?®oÎ䬫óœü•}&VðÄH_9bÅ…×\þqjˆ”\}¦PÖÌ’,QÊwp–S³þÒF]Ü¢pE{•o ¸f ­%²ðw}¯ÈOüÅË>ɺWôçÒöÍóÈÌoeï ÕÅöÎËï€*¹‹«{ÔXæÅ…WSáÅTXÃ…WR!QŠÿDæ¨ïÌ?KÃH?‘Âloþ|ƒkO¾Ž—~sê9†ùÕ´§âV¨>Ž‹ý„I)š ¡€©‡Ö Š·økŠk´ŠaÓ¼s¾ZŠ™D¶¡‰n"ºSz¦%æš#º'¬\f¢Há¤Ã3”fÏZþ×oYaûof~±dÚëIŠl£Î·Àž|a/4–ô‹ß½¡È…¥ži_ïÁ†ù Äugüg½Vk~h5õÿB:wU’W Œÿª¸0¯îØcW’b(Çòþ1¾ƒÍøÝwFµÊ‘‡Î.¡“!ü^‘Ì4ö¹ä<$9x`üØ?ÿ Ëu¿~ø&‚Ö7¼5¤÷{cÛ6eŸï¤CÜZÓ’ÖPƒõ]mÄ‚ÿò…|By€ñUù:’Åz›8‘ê¡9 o)ƒe†;®<“*ãÉìs ²º+b¶‡½ž?a0êj¶PâùHå6\ãév¨XöĪÇì Çýâ7û–U,Å"¢jÚ§å Ûùƒù£]`ûÁ-’Çù£ìç&þ}2óŒíÉÄ"Ó#š—4ë¥ÌÃË(Z 0ÕIú’?3͇¥Zñ:DƒßRÂÊ(ÍÚâ)ýÚĦx ?P¬Àº®Bw¿8+”2¹¼ÒŠ Èv˜¡ZUìœ9)Âò¹œqyDál3ëí¾w .•ÇY®;ÈbÕØŒp?¡õ¦¸_PK€YwY±j¸í£WÇTM»8s«ù’e•ƒ:ð„5sãÔvtü}`ë‘¶ ²|àûà?pª‰O ó‰BWL ¼b>J'bO(4X÷ÇX`×RÅ¡ãJi¸›9[EƒZ·×Õï Þïîè1Ònƒ÷ýàåZœP²y+{©×YÍriõ€¿û°¸ç÷Lß|°VQQéìðuAñ=©”¸¢ž}¾’Èžcê$ìEëÇ6* Vyx©®Îʆù³¬å;Û]>`7{s4õ~ŸË@`å-ñ m\Y±”×ôõ]þ4{÷Á¹»{R†Â£ºÔ¡³'ðotâR}eT„ƒÜ…'Œ}6lðS®Ë‡o€AÍ]*î»!Wgk– jV©½7<íë¬ÃoÇçßkQcÃâ/–Ê×¶Jõ´2F"ÑÛßíE+”nkÁ­ã·–XÈöf³ »³\šdibËß 8¼-qìÅêY•à‚a›$h*T™L¹b¬Ð%)tVWj•çÅÚyÜq;ñ[NûÚ–óI_iÇHðK Áeø8TLJ¬¦µ˜VeËꌬ_IÈø²*¸ÕºGÍ#µ4ZT7?jŽªd¾ºf]6è¼Ýè¤ÔeÛ¹tèRZ-½$tßéÔz™K²íPi¸*žAÇ8ò„Šg;ÏZêlâqu¹¢›,P!,´¨Ü<ì_žöoN+§*Wþmp2LATO ‚*T¨-_õÔòm©ü*¯ Y­WkvUär½ ™¬F¤ÀbÐùÙ>¶A6jD>¹»c«Yu¾³Oæ±V>+d(<>Âá´+Àf . òªì:x• À5ww”|ªÔ&ìßœ|êßì‡Z´çF¶¬Ýf´ÎÙc#ªËÝø>¯\s4µÔx,?ðKº)æÆ)sÇóŸÐŒëÛùÉ LQ–L!“>h@ι&G«»;šWÏå  -´“—o/µqc_dE4u&íù(¦Ö*©Ë ä9GÉ‘‘ûè[AO1ëCkŸ­Ù }Í·¸¢²¦§3†³ä ïí8¶l³¦¥3ÇÁÉN‰›\¾/_ùŸ¢õû”ÂP%ðËWû'W1¿è#rªùEC/Tµ¯¼Tÿ¯^±ô>’ëÿÕ[õZ#Pÿ¯Ù©7¶õÿ¶õÿ6­þ_d9µ˜*žWW¼ŒçF×,ò¶ZªŸ‹<*­™ó³Û!ŠƒÄjwJæöžæ£ ôä‡JÿóðªrûËåÉÛW¬ïWhÖ׬ækÎÊôTñZ~¡Y)XÃÏÅ"ÄÉ¥'9¹[ÍOôÝ×µïå]Lkì&Vdêº~3RP}—6¯=ÒPþ]þ†¨3ÞÆ‰3›áƒ¨¹óönŸ¼%¨îûhf:`PÍsdñ †ü= õWeE}ÔÌDQL†F_ç˪Aúž~RòžO,^ Ò„®•]?L†c ù$˜î¯¦ò°8¤]É,f¼Ó‰sdC ža3hÏš†-*ƒsfE‰¶S°W˧L<Á²|³¼L1_AJ‰æ¼îk K+Ð]TÑ k“÷öW ÓÉÌ+>Ä”t–ZîÅÛUVPÔø+LyO„¸Rì%Esƒ‘2ŠX‚cz~oáó»"ŠN±–Èóý¢§‹GvRݺ¾° &}þ>_Ÿâ5äöüjÈôý›ÁÉÕÍiì„Æ4žaª4D—à†ÚŒIÜÙ%ÚíN*·iF6¯©ÍÕÐás0Lùó"ædf2@ÑØ5pˆ 4ÏüDFÞFòœ±A0%‘Í+|)Þhdm¡!žH9ßGÌer[¹èÿŒˆùÙ¢By@öl5Sàj…®Caè¬*¬F^¯ˆW‚,4He_L\¼zòÃï½²Á>Þ n? N3/ÆÞi±þ"fÀ 8 [=¼›¢3’ ÞÇH†ÌdŸRë´üÅþWÀ¶ûeJkrØæœ+Ĩôsó}Ò™}¦™F µŠ»öúòÆß'iyãóœgúH”u¨VéßÇèòyiâ˜aŽ•F´8bPšX-Ε»¦ç^åLH®Þ‘Nl¨x÷æ8ƲØÄÝAá§Z¥ÛÄrù¶Téx´‚*ã7æËÚþ[ÃÿǤPÆ_ÐÿWë¶»­€ÿ¯Õê6·þ¿­ÿoÓüx+8{we܈ÍòÏîÞ‹WI–#M3Ip÷án[V¼ß§£FÞ +@"WÊÎ.xE×_Ô„¯éÙKÐò^ÒÃ;¥8úB|[×ç* móRØUCk ó¹êMÌ‘=µ—OÜéÄ©àpõ°|1Ô£`BÇ÷¼£g=Â*ežù›@Z§„ãwsúáâ–€[=‰—êÁçaˆ˜×bÎ:‰¶UÞà6Ø:–G¯|F+Y.½2—±,ꦱF³È#ô›±œ‘ýô¤;«"×e€Râ¿ëµNS±ÿÔÐþÓ©Õ¶öŸ­ýgÓì?×7WCý}¬4¹ÙƼ7óP,â ûO¼£œaÐ%5Ýèâ­Ap]…È“.)”˜8²¯~‘ìI°ÑÙïG—†ãÆE·¯hû Möš†Ÿhîå4ú$NÝ:ö ¨))h BmON§ÎEiÓÑž*c!Šêw|²Çòk©VK¯Õû#ÍpI·)²ü£´dØ–è^\¹?rË~ÓÎ~þ4_šh9ÀF«[S³ÞÙ3œJ*îiî,˜Á$:rMg”ÈUÂH\k15GΊ,j!IóMµ Ò5g‹ï-!¹ Ña¸¬Ã èâxù#ïýÞ{oE«KªÍ±ú¼„3›üH‘AŽ5”¬ê¨7•~¾š®ãâ ûQV‚“X$$žŸúÕgŒ+°oøÏËRƒ|Òr¡!vB")ÐRÆeÒ±ËËÉr™Õݲ¤*¢ÊbÁzÞðý­‹ÓÈzëOzáqÊå“2B:2™š÷T×.¥úõ¡±L’Àå¨¥× ²#”"Äb<¡û_‘šHF» nbM$š¿h ”`¬8I¤£¼öˆah9çÉÛ±‹¬Ê±2 âxˆZ½^,Žgt¦.øŒ7û{SgdNãmâþ‹p\âǽLä3°£{¸Æÿ>=ØeRkHÃXÌ¥ÑèÔŽºd01)CºlÔ™1TúsU! î0ÎÞ¥ò6“¨…nŒ¬•„0¿pi·l4göÜFì.Ðe+Së«55Ìì.¹0CÝ‘¥”'D칋©3 dÜo›•;:!»;|Ë­ø\jj«,ø¢|fÜ—h%™g³+úP"ÒKàÜϤ’OYœ×›)@Im?Ž ½‰çp…ÔÓŠÖé.JË<:aq—ëDõÜšãͽª/íM³Mf½ú³Ðn¹%ÀYd½ å²_·ÜØ.õÝ· øû“ÆÿñÃÆ_S/ŠÿÑlvÚŠý·Žößf­»µÿní¿›fÿåÚÛÙåéàçoÁú; %Þ Üâsî?RÊ}¼˜šØ Z„:ˆö ið3œ+·•ë$ØŒŠ *_Ñò˜æ5í¾ÜÊiôÍ>ika~¦¤ ë¯ÊI©b«ÇM‰–_µ/–JýèÝs˜{»£n«•ÃÜ»›xƒPY”ÍæªWÑЋÃWÞJ~x5·_Y9^ð ]çx)tÕÌbv.ßÞÜí6{ªÿåìÍÁ¹Œ0€  aÞ0¾%ì*´p *ùÄ` fºÅÈ1þ¼äœÚÏ|ËÕÌ#Ïw¥£…•„Xd45ã].¦™®%#Ù3ò*z͸qð™ü8@»^:n-P'Ø DnL7ITæ›W²ÂßR;É:,­ì³Køñæ©ð£œ§VçFwòåtêMÕý‘Á—£ª3Ưw¦û›q ÿWQ¾à7# Ž•½ÙÿÕ/Iõ›ñ«,$õ6`ÚÓßB¯óQ/…ãgwwŸ:—z8£Â÷ •…ôÜiµRþ%µ}!9°Ž%ñˆ»òî_)ê׬Ä·ºš‹=¢R@1a]zY µÓhw2—PXn¹.h˜?÷"&²a'æ@6VŸ\*U%Ó5Ù1ªhäžÈH  •îLü¥B/ ÃxŸ¸i³ûn‘ÃÈœ¢ãî‰{ÇË(ÂÓâ¢ç“{.\óBbÅõâ•ÛÕŤr”£‹zNssñ× ô®‹8½êÚ·ÌÄQ 7‘ìh+äZëÕš=ÕGíZ£ Æ&£´g²êõgMJÇfO±ëärdi6¾Mbƺ­+¿ÿ' déü?f;€ÿÐiÕ;[ÿÏÖÿ³iþŸX¼±ÍwùõÖÁ¨NEŠX¤5Þc´&éëy“âM9HIø~ùüLEî‹ù›R`òJð>Åãí2…4†‚}R1d,ßOÕªuÛGÚul=?U2Bqšë)T(.å ü¸@2Ãë:”€÷GZÈ—s(E•ä ›ïw£”Šnüp§<Ö~­ÌÀêH¢îx¢-—bv s°Š‹úUrNˆ´#±AÄÍŠŒÅÖ»#Å WíéTqèI#ëyuvžÁÓªÁÎkõÝ9BûCÑ Çñƒ4`ßyƒËè0\à ¹Ò“õ§“} Áu|ˆ«ô%ö ÜöˆŒØ¹ÍÖާ§&he.yÑ›×pæÓ'Þ¢SÚn=ÏÙdr§Jf èIÕ8ÃyGË<ü…Ù)§Ûê‹zÜPâS~„tÚêëªÀ:AÂl‘ª‚A‰}©®Õ†žK0Xb€C`3ŠãaÓ±ü Û©üMîH2>®\|~;ä0ï ÜaùyKà''"·÷£§ȇ^KMÉÊàÔb%R„Ê8&~+.­ãGàeüú=ûÐÿfÔñ1,Oþ++Pà[/|WÕ>(ýs{þÿzlâ%^j÷¨8hÆ[«þÖØÁo¢û7¢Cµ?Â=fÓîÿF£‚wz º};€–aPþ›Ô×x(L²a91âÞ3ö¾V#†Ã[‹ønw?F¥Œ"çç ’ì²œ„-¸W¶ŽR2Èvw.œ1“‹R$tó}x v_ï©®3åÁ(Ý7ú^K.~*“6ÑVŠ[ hhµÕÍ/ã–z½b,Y]H›Qk§$gÌr¯«Þv¿UgSKÏ…gå9ŸòyŠ`BE. ðLÅ—zØ?ùÈCHtIöÛ[aî¸ç ‹5ӛŒŽÓþÍiVü­@VÁš&¢h>ç4ÑS…íAq3TÐ äbýÂd$¢ŽîÅZD_Ðy]û^*³ò°cºlþÉ|¨ëjnÌ(á ¸´çK×Ys”¢i©Âã…8oSÆÂu¾Â^–9×4ìRƒöÁØøÌU ×jÌü>qf3lÌö¢Ç[*ÓÇ[ÙGlƒêáU×oã&g&…&A/‚ÀŸcYÞ¾] _bØ žqga¿þ{,=ßc•F˜„n_ðMláÎZ>ZÖ\#h>ÖÉ`eOí9Ï;WnÐ3sä:F\Y½‰‚®,ª÷±Bàˆ'çýÛÛ„’zjªéU¡ÀÚËŽO '¡V)É.‚:î8&)-™Êè&j•PJ…Í#sÜÎN­š)œ!‘bŠìÏJoTs*oý£p»Ô.½¨ì<áp@ÜÛó Šåc£VmÛóï þ‰Jñ!ªÍ€¤Á†@N4…ùʼs¾ú•2=ƒ 0”âîŠ2Xêñ805\Cì ÉyŽËB{@Îj:¦À³;„0™OÈbFÓ‚ïÆ0™®‡¤‚ü‡Ò&ÆÎ²tF{ÌdÈìÎC:vJ®myºE:*þ^x|yrô„µv1Ëd éÅÊ]8Xjœ ý·«…åÒ—d3§Ó’ãh||Ë«ê!è‡-Â"Y˜ ¬Äùýòü-ˆšþçóaåvxsvùCå|pùÃðÓÛÌÃ~Ö(N.ÖSAr“DÐûhÙ“™\YÉG.w†nòBØTE§/tP¼×Oˆ<Óç”Çί[Tl‹„ òFš»Š‘+‘ßG‰âäãa NÜú´R`g§‘B‘ˆ²AvÚÎ1ŽU°”Œãì³ç D†226Çà™õªhü ?Õz¦«B. fðB¹–̨#è[²^’ý/¢Üí Úÿê- ÿã¿ZfckÿÛÚÿ6Íþª—üç ýÒëšëm^ß\}PêÚÇ›ú耊nƒä»ÖÄëøBÓ¼¦ù.Šo›ç1evé,”Æ7ý¤)1 KïÏ×ìd_ )/G¢æ˜Ä?ôݬ„C©Ø4|ÏR3´ÑmÕ»åa1ë¼E°øƒ¯ààSÑb +KŠË àZÜ?Ë/ÚÙèv;G¯‚ À̈ ô~påÙnn(#Ï?4‘h+\°º‡†]µªp·æ)JÕݲ-)‰Ù:ÞïÎN¶ÄN"ë­9Vhœbõ¤ PTÆ”[ß×q ]vÝÈF¯uTO®©dWÅ–Iߦ¤Û^h†#°Õr‘>X­á‘]^CΔ™»bJ)Øèuzõ|¥u)f¼Ùß›:#súà`D(ðß1lhñãÀ8ÖÆ`Ãå~y+ä÷©çiŽÇ˜T[¹= ÞÄLÙ¥E-.Ô\Zuå÷ýîáðD_ôty À=ü21Ý; °P¿Fï¨Ý̘¯]¤ã,µûGµNÁø©Ââcêkh"Q‰ »ëI­½tYú装oàζrýÁ¹v;4à鱃ÏÞ[KünÏãõòQþàcq5|tÜ/2Ðqöÿ%«Á"œôë‰D2l\9.®#Û¥¿X9è"‚ b.#¯ˆ†f$¸‹S4™K;ˆEî2Û¸"Êg«²ØKñ’Gfl ©r1’I±fwˆQ— VSiŠûHhÞ!uü”жe$΄E%Tü Ñ+¼à‹iGÛè°çc¨tzÌðmW0÷®9›2 Ú°FSXÇd·š>U¬9áUáe¬¬°Öv¹‰ˆùÉ¢ÐIÔF– \Á×¼gækL†ÎÆ>`7®á©?wUl)mÃ…{g޾øá¸´dù)oÓlŠÉ‚áGñBch-sYdála°Ü<ãÊÓ&’v éRû‹¥=³ÿެXú½oNA²1xÑba±ìDû­Ê©3 †]CßѦZTll-¬9õ²ɦ šÿ„u„°[\ûЃÅM™ÖÃwß!<§_éK±‚p “’*ÿò¯Óåw´é+·¿Üã/g§ƒËa¥?Þœ}ø<¯®ðÙ]jViÕÆA‘Ÿ/[êâ÷|üúº9ûª~èßëï{cïk(í¿Nl×[þ ‡ûïoïQÜ ÎûÚÓ?¯ ~¾6ößPoŒïg7·Ã¿]ö/Œž_ñu¿®S3g˃‹ëó³SƒiŠ&QÊÚmüF壔!ˆqå‹ÖeãÀè_ž`ƒcþíûcFp–pšq^Î&¸ØM¿ ó+”Ú–°†34+Ê}Ç— ,IRù±þy`€òM,»™J‰åfúÕ/ƒA•³â{£.XŸÖv¡="Çœ?oPŒ°Õ8þmmzN®.®û—¿T¯o·´ÎN…ª°&è¿hK˜ÏLasìB@õùf ÇE_¬g®P"¡ö*ð:*_Y~˜0«OßÂp;¸¯âãÀá–2¿·<ß'ÄÞ« ¹l7òèÐCç_dK‚#çï„‘!¾Àd‡i5OΊц‡'ïå¾·rI×À¡0"2ó%ã!!í}þÁ}kó“òT28)fX¢ÚÊÖ¨’óâBB¢üè„âäMÏ—hg#ô»XÁi5Á£@"¢œŸ?}Ü | [÷˜QcñÃí¡×GU5ðgÁ×SÑúìúeô0oçóÈ^óYÈœ™Œ¤P°Xز4¥<˜¥ŠSI Ügü!.K–VâÁî±ÆLD¯½{†Õ­ÌÄU¶I¡Q–îfïˆM†á’}›%àî=C»Ùœzµõ,räÁ>…ÒÅÔ˜¯–_e^;#zˆ…6?ÂÅEŽu.`ÒÈrç¸ì)úÑhÀî7KoT(i …3P¾ô¢Sf†Z½Ë…0o ¢Êó;aj<–Äýÿ«EN:!K`Ûaì.c¤a{˜OÿaY+»†Ò‰ƒ¢À5GÔ•\?4|µZ=Ÿ>qÕl:ðZœBžPêƒU7Ä“ì4²ÃOòcê€jÙ-˜±AGy\Ûé=ø%•±ümwþ ½úŠ&"®Ey”ʶ¸æ±÷“=¾GSÕÙ|T¥†a9XAì7쉸‘°` Ñ9)Y±câ´à‰Ï舦ÔŒžË4¢Àhøpnñ<¤Z—‡Ü½,¯¸TY*$]Åhà%q„øÅ¡Y˜=ÁE,Ù1 ”ùÇžÓmfåâË+¬ËT0f*N>º6Û«eøX‰‘hÿpœõ\ñ—ÿ¤Î†w-´#¶ÄdIÅ)ðÊ…97ï׿9ž51n— ŠaŠ>*3þ„ø !/³„œj}+â€ómª%xÞÒ­l¹œn[ìxÝ‚ÖÝ­ãmý6Vºzï_:þKSÅÿmuÑÿ×jmñ·þ¿óÿ}beóa]–®3^E@²H—R½úÿ9SKðü­ßšê„–]œ˜Ö`ñ‰kõ«Wôú³¼¦ÿ/̹¢À ƒ×qíEÌÀÚþ=β²ýz²Y MNK‚7OÖå(ÛÂL§p§'+ EËÅ#Á¸¨7 $Ïá–JáÙ 8Ò| RL4;3åsÐ &…›®á–* [Ê‹?Ç`QPI éóÇgQCšÚw.æÆ·lŽýJ–;$šdÆ@û³ÑdsZ®mË…{ÑMî öîLÓi²G%Bh$Žíæè ¬ž*ÜVÈÑ„¬mªˆÌ±ý}†#,àç#¦ñ9.P0g³hcnÈjùà¸| ?-ã‚NÆ!ï oLHHáÚS¤¤uãwGp‰»†…;²ŒÙ¦R¦*°èrwë.ÞjÚ†H H±f?¨Ð]riƒðàãé_ŸÑí·Üq©@ úa€¹Iœ D%/Gª˜‡¦k«QªŠhÑK>N[½šF~A‰9ßïm±U¦¶hì-ñA\¹Fñ" b ótñùD’R!9B €Ha&M¾fÐâ#‚=µ—¾}&ê?`1(’Ÿ ?23µc‡}%ÝÄSǤhgBáh–À©šÀçxõ¬,øØ˜ØÖtœ¡ÝþxÌ΀ßy>öŽvuúá$Ì[{¬Ÿñ9XF@’P̆ð$ì)ë0ðbSl—ôækj>'“÷­¶¦D#éý]¬`µÀ´ÃzIdž­¹åyÒíßíÅ“²Ëpr*0;ĸ£Ü³•&Ђ$M 5~"§x&hoŠ…†`c-Î)·êûì óŽå&ò*€ÖÙ¨»vœ©–¿šamŸáöp KLA‘:Š`<½j¡%‹P „ù_X4‘Jò»Õ4 ÉE§2¼š91‹2_Ä Ñîú†ÅŒ:~¾Âcq—‘ °3jWÇ­‘1§ýîU Ÿ6r\”q¥šSìMÿñŸÛ­îÿekÿÛ8ûßíðêºÂâˆN®nNÏ.ø0`ô]íç“Bgﮌñu‚ ¬"Bh¾ê¬I‚{V VÕ©\¿¢!0rº×´ Ær2§i04{k;GÍG00aJÛ^øÐ)&Ü/Cý„> ÙG†%w;Œ€a!(Þ3€½5­òøšX/a扨º(Ü×ZLÍ‘…S'pB€-ÉGUOÅx)ݘxÔÑ*½¸K<•@(ïÕ\¦ÿOL…À'âÀØ]Ï;¼]nK¬Ð”Ra|ñÊP77Sãhn— s¼†'Z„¶ªöRH6©/zùÐ`%p ƒ‹ƒ„ Á7à?öŠËò(@³1ÈÃl9ouƒMiÀ4-ÄTT""€iP< $Žnj.Æ’ÂfщV©u+µ†Qï·Çõ†ÑˆïléÅ%²‘°à]‡A8bPËØCƒBí}F&¥”dlD¾7ö)jÖÇŠbA´Èç ’%ØÌ×Û·ÊéÖq½^§ƒ\+ ! 6F³¦iÌIYC‚‹AÊQvç:æxÃB{ËœÜð DI¨ø‘ªÆ{…t‘¡w s)Á¤ Ÿ@H¸ÎðÛ×® žú5½AQÌéÊ>“ëxˆ"g©´B¾êåSÙE}“Ÿè†ç0Û”ŽÎÖŠy'3} "ˆA&±"|ÏQ&à¨Óë6jå– ð4¢X@”ÏÿH-ñ¢óâð¹½MÏUQaq[­Wq:ùîuB;Ùmü5i0 *íw(¢ —¬º>úEÕ(Íušít²û’¾T{‰ H•–Ys:•^€—öC…ÆãC€sÔ÷FAçPiãËTI!4:\Ö±L.§ŽÂQ¯Ñh%»«nt8 Ô´L8ú¨JB”ܦâ‘(î8á°G,sô Ü´þé&’úÙþ‰¨©k׿KAÇ­%çÔÊé˵syè KÝ—wO’DF¶â #…¿Ø‘ÂÎê±dGʼnÌàÕ (¶/äx£ckî+Û¤öI,¦Q’¯SâBMĺ}iÆœpð·(NäS¯€¢ßb9²b¶ôÖÑaøzøoJPÌï°”è7üm¤i©œ#ÚÞPÓ¯`';p*¯a.•Øe‡l =؈zÄZ$ç œ8#œC%·mâ¬\PsùsÞÈœ†»¦ó–Q;aÏÖ {¢4¢<9BógÌWÓ)Û0ì´&¨ GÄr­”ú&G½ÞÑQ#}“€ú¥x‰¤CeyYöŒã³ËaËh°×ŒÚ±¿wï:«EøÐþžTüØ¿9ùÔ¿1š5z¨Ž¯KçNÔ÷¼kfÚSå{¸Bù X{E'A¾ÍÑAÂßÃw3Ð<¿ê{F/øªë‚¨…ï?\]Áçþ‹w6¬± 7‡ãáÙÅàvØ¿¸¾}7þÛjiÓÈ _¿ñqJ•WÀåè¨Ö}.GGõ£¬\òåz9:j¶º×ó­N£õÒ¡†‘8ç‹ÞDP¬Q7íêûÚX¢Gæ«×hw¾}P6ÃNQgoÏ+Á”Ù´“ˤ¯« pL‰[’ÿcÁX-Œ °—/]ÿ¹ÑjwþŸV·¾ÅÿÙú6/ÿg"äóðêäêââlø-x~”<_½¡’ü ¦wšœdŽÇj[×™N)óúFPpNO+Ûþåmÿ¡–+7Wççú'­|ººúkZaèXz©~“Òìk¦WÁºN tÞæô EMîÚE¢CSSJ‚ÆK?9H;‘ÊL Òú#gÏp…`ºs4,;“‰áwKÁÆ~ñ€çpî4»ZM ÿ]7/Hã[6·ÙGЏu6ÉMŒl¶Û×pÓ„ø™§òñLQëùI`ÊŽ-ÏFôgÒ4«úõ" ¡¾ ˆ#§y›Ž£§ãøU«õw'ÅssžÉã‚Æ\<~ à\‘HÌø? $w•µ.JñÜ4»Ý¨õ‰ž›!óÛøãBÁ[d… E²» ,á²x4&c 6(úL… ו3KߌvˆLÍ{ÍØ¼xïïÄv¿9ýpqkì{ˆ‡czÆ•kަÖð:ÄŽÍ¡;‹ 9!K9 -äðPø:'ï¡W“™œ^ Ž Ì¢_ј=Nî¡53 îôY¸U߯IÀ1Ü­ÑŠ\q£ëû„ e_VXò]Eù£Ð#Ìð°âô°ït3|éöàf·WkÔ²¦+äÎ1°Õ|JËwMʦ•ÉŸ!SIVgŸî}…ü ¡©å8¼´5hi /™_{3b×êÕ(9·@i¨€YY±ùwR¡¼ÇÔõV•Ñ<}/F¬¡ WNF»pÆØã/@jÎËkQÁfÊ·°7»Gõv§W°ÎwôýâYë|o¶™¿ÈÕ½¨Õ?|/©öw¦›}>ë’ hSª+þi½ÿ+:}é…ê·:Ý þ–ßÚÿ·öÿÃÿ %·ýIÀÖhFþŠFL‹zMø¯¨Ù^ÓØ•ËùšÈ_1RøWTÚ³@ÿ 9¥Â…zæø_XBñ5Àêµ£z·¥E"­‹—'þÏ Öè5j½£Îl ¶…Ë Öhô:­40+ÿ `H4̆³Zb±^tïân;b†U>B˜0‡¢ÊôÉø¸$vÏ”bw\a]¼•[H†©sYí% r4! g4$¿6ÆÊzVÄ›0kÅ€h hÞ6{I"åÈùS曳âŸHAõ|ËÐiú>‘Ðä>d]òµ ^(ŠŒÆ[•Þ­—AFk4Íö¦!£åëÊ„Ôõ-¢•ä+ëÔ:£nç›DöÂvd£”K–ëp0˜/Öv©Ö œHsß+o)þ:àñQëuÝuZWÏyaoôߨ¿†³.·…ã}^çÍDK%ƒ­ð0·Ã›Aÿ"±sMÅÉëBŒëúTÐòÐRÕt2NA˜Y(‰Óùr§ù-D¥ù”¤¤)Í”î¨Üë5j Õè?&•âžd’ïò|Æ«ÿÈ]vj—z¨ ö¤è55Ž>#1^ ¢YKqZìîü„ÆÖ%º_„¯/!ÄèÙY×ùˆÇɵÆü ¦{wGÂx=²,íšr´sOš™_¬ŠxG@¾íÆrÑ ÁuvÌÅÂu.Z­|ì0¦‚³hûÕbÌb¿ED>ÅOû÷ó:¾¾ÚÖc…^ˆóyýO'ø±tqíîÈá#M3P0ú<6½!×´¨™ÌÄá€4/Äa4¶ÉÚ§”i»|j±rT;?– ‚@—«ì=‰2Ƽ|m9®œH™)`qhQ¤¥}ygïò«™WA‹µ\\ú±øùú´?ð{ÍmíÕ³ËÛaÿò$sDk^o]¹ß+3N$k×i}Œ¼Ûó«aÒ°Q…,ß,ëæ#ÌËDÙm^Ò¼(Úp)`O`Ïs‘têš–i•î!ÙÙŸZKc_nã}M@o&Žspp€¥Ÿ÷“›\õðìîÎwßáV%íÚœ2Ý®ìê­zR¿5–¼õ¨~‰üÚF³ÿ®ü`åý\u¹ìƒª>ÿÓ+ÌGå·{gºÆÞù÷=µõý˜9 ¼x°«’¢JSìPsS™ÛÍ"-ûž‹£¡e+ωs“Œgë$ÄÔm¸½w^ÚÆþ’bЋ•ƒY-®¯$×$ï¤bI-°»š†¨YŠ)&‡TØÍY&–ˆ|`y¢ýë³êÆšïEÍÇj£ë›Ž3_sÙó_c7À°²Jlª]™ì¿Îøî9ì¾Yó?Úÿ©ù/µz£Ónmí¿[ûï¦Ù¯N?œlºÕ®«Ö|lèóOÿñ?ýê?þçT\8?`®"|á%˜xgOÞïóîÅ“`±5¥Dñ @Þ½¢m6þJÏ&•Ö5Ù*ÌÊi®M›¡uŒ³Ê|0Éê Íc¬±U¼‹Š˜ö=J‘'|4µL÷˜Š¸J5Éãú[¶iBÝNÕÒ"inøa ök‚áe"¼©®êšíz£%ƒšd«@O3Š´L²¶LÃ2îø\ÆIå"h5M&‹·ÎØÈصAœcdžƒÎ­éæiÂ#DT‘W Ü)ba³ÒZÒ«–lˆC¼’; 톖'À.°Ûø^Vsû•|üÝ8¥1 ¢Èy€m6\Ø#×ñœÉòǞ欪ÒlÁÐÄÇô.šC„{ü{ÕJ½XñɶÞÂñ–÷0¡ à”‚uiº÷p¾ìýôEžoƒÙK‹/½¼Á†Æ-°‚2„JdÊ5ëÑ·Tʸôdrñ,eBläÌÞ-\g¼-=¸´Íç°¥—Æó.û.žâèO žÎK¼m¢Ð·8÷MØKoÍ}Þl¶œ‹Þtòf‡#Ú f)<*FÙôÆ“cgú‚e¼¡¿¦Ž9®8 ãÍhŠ‘7ÈáÞÚ€XËK¬—mò)Ì%Nتö÷-D‹½©)ì_ §Ø€~¤;ߤ°U…Gù-ƒ²•5}ݦ(Ú×IÜD¨m²úÐÌ?’MV‚'¹­Dr{5‘ÕÛ ÐÛŠ\xQɃû)É|ÞSD¦²ÉS¬ÅÂ1úÉzî®"  ê›û?”D#«<Ü^Ñ/®ÕcËjjÃVù–?é ÅYºî kw„-Øx¬¡ôaú|²ÂL0ÓØ›y æíÑžÂ(g>±ïW.ÃFDO1¬èøC.6pïÂ6‰Çòs’Ý»,i‹4Éc. Œ7û¢Ï=™ðŒÒVý[ˆ³½ƒP:Û±|ˆåÒ1•¥‡ýsÆè2WAarŒÿ©œö‡ýýÛA½¾Óú4®®—ÆÖkµn»sZo4ÿ Û!ÍEÎDpA•mj‰·¯¶i‡de'&èIOŸ*ŒV Éÿ‰äŸí(ÙÃM{§7g?n¾ÿÏ0ÃÃÓÛÿúîvpƒЀyËß 6|/€í~÷ùìô{%ß]ÿ¤|"&â»ë«›á÷õV³ùôð·¹¶W­}׿¾þžÆUêdE1æ]ˆ-Ñóç_U2È™¨ŽôD+k;ùuA’¼áº<„†’Ÿ1ŽFin'Ïqe!ñð=4±ð<Â`#½‰&Æ"ž@Ýb\‚#0ÅܘËýG¦€ ðèÅß“ûºùÛJ!ÿ^íaTM®pÔq·$Ÿ`²ÿ¾Òê¿`þG§Ýmlý[ÿ߯å †åàò´òSÿæSf? >õ<»ºù&rA°Z'1Ó‹jæD|kÜ>yt¯HLúX«1 ô%ÙX89øäêòôì• ¾$N{ 9A^æôF³|-T¸ðœ”’ÊËGyíŠ;ŠÊLñˆ¥‚Ò=P:¸°”ÚÀSNÇ| C列,‚œñ!Õ ËDò&+¿Ü­wÉÇ¡°¢äB¡Ç–ë:n è»Â«N¦ÔøþjI *Ýf«Qk¥&¨¤qa½•z­Þ;ê¶Z)*}vÛ€kÆÂrñꪬ*c;V²·»CË‹o‚ªqÊ3lr§¤j\˜O°Ç=ïîœ`ñ¯©S‹Oy0À9x’¾Ą,Ž~¼ÔÚàÔ>†MÃÝŒ½Î,‰|üeÀÕš^SMVÊ^Â()äºÛëj•rÝk×Û½^,ªI¾B±´£ÖQ«º u#±W®½)žO˜¿±a»éG{ÑØÝPË%`?d;ösÝߣ•“MÀ~P•Ë?7þ;.'ÜÎÏœ†ÿÐè´•û ñjÍ-þÃöþ¿q÷¥ƒÏQæ¦qÞìË‘·Õû> ­FT¸I£pë·(©ž áE\@¾¦wÙÿp>à=ýÓÁ ¦åû?¿¢- ~ ¬iH`rN{=UøîŸ<3Í.È˯=ÍÃLîÚz´»Ö?˜ò;Mu]QŒ!zaºK ÙˆöƒÝçÈN_¸ÎWØ£¨H{‚6\˜VŽ,ÎýZÞÒ]qÏ–ÀëeyoÊâ‘ËÞôÈIï!°=³„áý¾2 ú%Cæ ð®”"~“‰VŲì<îQÓý÷NfÀ¯–ö„¸ÅŠi}‰ø€±íñ¿Î@£À`ËO'_ÂVü"f±:-Ê@Ù½’îÚÂZø“j/Ž ê®âs¸g#R´ ¨1qoÏ+¸kZµmÏ¿3øg´‰Ä‡{QQ ³ˆ4DgbNàŠ\É&?žXŒ•Žq9™‰(‰™†¹¤ùM™êEš£ߥhX­–·L¾²/Ñ»12+ØÄ04Å^O·EE½ ã¡¿Í3‰§8ž0‘ÅöT ›ÅÊ]8ôA濦΀³Ž¢×$_U=+ãØšÂéÙmYcà]=à ¦Õ"MY®ïϯNúçç¿TÖž–sÖßóÍŠPÚ숭?KbHÏ7I v$<– •rå#ºÜ¯n"FR¹ö‡ƒÌã‘ö´Ömâ€Ð$hà $‹3ФT)0Ú âó}¢ÜÌ>Ò† h‰QŠ(ûñÊ5E0ÕZ׬BCFÂOÄ©‰v^†gEáLduöV¨¥Àᮞ E‰«øøtV?_Ãj»%ƒK^’=A³ßr€î`ÀâÔ³ü ø«ëÁMX.í¦O=ëã‡ç%q¨#¸ºÉ<µ¾5S²äŠ–tã°d_µéQÁ¯fšÍuÙJ´Q†Ÿj=ëe+—ñ5òV¾¶×x ü'5þrýOkYñ¬ßWxI¯Àö÷íÿ/aÿm6´úŸuŒÿjÔ¶öß­ýwóꆕÛÁ¿\ž *×W·Âw´ñ¡_“ñ8á JšS†¨sjM¨Ð‰†§ƒ©Iè¿Rh i7»%Øt9øy˜`ýh>B¤¨h»òðæóå "Oi6åWª3ûk~#˜˜Óà›}.×1 ÇÌT)•B£8ë× :žÊ¬Õ;«Šûµ]Ñ+ÞßL5‡QõC›v£«´¬[04Š‹"@'9)—åXdÏÿÕÏ•ÿ[¨Ê(« Uv­QœNý¨ñÅFƒO/6Šî JÏá1Õhì7ù=ÿP\âà§ßF«Fie;£f?ü>ft--Âàxé ¢AR‚™Š±u) –õ,m|bÝ—ÌèRŠ‚Vßn7;‰Q‘ƒ?Ð-fcT Å*­¶Œjn†²‰!aeÏsW~q±¡‰Ï9Õ‡J Óœ[ƇÀu#ˈ’„Y9ª5ZùŠ*ŠCË ¿Nç7‘OØÂo#Žö”Ñ®‰Û5¥ÔsôvÚõ²Š »µ¶Vö-©ºàC0g‡¼¬o©-¼ª÷D¾ý‹?‹M¹°ÊGM l°°ÊQ¼ŠÇ †M¶0—$ C¸Á¢)ªÕZPËMMRøÕÁwz 1]ÅÀwýíYÂÚéõ:!¸÷â½æ8Ëy¡aJ_•îÂ>~gÖÌqŸŽ…ðÝ'̬®³Øs­±ÅÓkrj°·©Z%hÕ¸W…¦ÃþlïK5Á· .Ý:¸oD@¾ÇÈ¿³°8Ǭ%ÄÔ˜X³Ý7b4Z äðvíå\ì¬Ñ$N3žwÃr­¥Ü«XùûÓÍÕåÕç[ÛxjÞã1}õñ#ó´DùÞ³áiY™,8~ WA{êT³A?/6u£Öìµ¶ØÔÏ€Mý¼ƒ…ûêj6¯`K CÖ7’ ëRGºß~<ü”æz×£ŠÓÖb^NÌq\žHœûhË ÿ  K&OÞ:GG©šEe’oöN* `Ÿ5ŸMviˆ^æt*е'A¾GÊ‘'Øal“ó'qBÁöÌÒ*ó@Š—¼ÕÝï+ N*ÿ¬È‡+¿9ŽªDÑF@<§‹r¹¥²+o4 tТùB“ÿgDa1Öô™<@)øÏíz£Àj¶š[üç­ÿgãü?§ÖÔ"‘¥ö6Ýÿ3 Un=y0 &ÿñ?ê?þÇ/}>\Á¶9Mpý˜=<"øDáH‚#hÄáGA’𣮿WôEÌìšNž¿òb:«óêÈ:œ˜ÈuAÁ‰ZÛdnÙ¾ q~ ãap*£=¤/_: æšKãÑ2¾ÌáüÀæyœ-®‰‡xágèÑÒzòŒ®”Lÿ¤?÷m\Õ´5˜¹߇ý4ÆÜ, =3SnÏ {œ‡ÕEW,yé:+Zß®Í.«SÐÉI²FÏÀÄ{pVÓ±œšóAȹ¹±Zæ%@gM'UÃ8Ã2¨ a¼,¶A,¦Ó'B€’·éÝX5ütp>€«äÙåí°±E7ƒ“«›Ó[ÍÜäZ3FhŠz+Ð ,oòÉy´à0:¤â-8”à{ø™é"Ó]Ë[ûlä^ág&v¼ s#߸å¸[q"ážì¸.££Ž0‡®‡ˆPÅbâÑž¤¯Íhs‚wá"~ˆßÍ-VXͲ¡7—? ÍûpÆlä¬9OÜ­ måj•Ö •÷u¨ÞÎí/Ö£´OtNˆ•¹†Ñ[|ìÌñ˜l{ó'h†µëñøàÌÑ4cÉA¢øín´çæÕnA©´ÈMÈ?K¸e‘”¹.BÓtn<þé¼ Íû'Žÿ à>¿äý¯S«×õZíú6þo{ÿÛÄø? 3üÏSò'±DX–/É€( +\ügpssuóšˆù^óJ˜ÌĨú£LD)ÀZ'%vÏ_™e9¨½€G*³\V ѦÓç@è­x<ˆ7îo< áÏ«à“ â?7`…Œà‰É‰çÌ©$VG­£f·«ä[G¾‘’ªföEçMe-Öà!®ª%U7ÒZ<4ƒå…”7‚OÇ?¹Œ¬²^yàk÷H…áˆÈc÷½L„ƒl{Ñëî™Vœ²Ö$ÂÊè-Ðé¡A…Oòr+“iëŸ]¸ÉÓíÒÅkü âl-ôÒÇ<„gÜ]¿ ìVŽëåÌ… ×·éÖzGj©¦øú6)KöO[Ô&ï¶aåmRη\—õxmgCÊÛú´½¶oÿeñÿ’Åû5êÿ4µVÐÿÛílñ·÷ÿ»ÿ3³¬q‚[…YDÿ\î_× ¶G—ŒáËJóþfs¿Î]?<·e8€%Ǿ5ÿ¯âwY×ýàì³xéôbz}h"cÝ¿ªó÷°è£9ckjLM{ .U÷ {NTwÏ­%ºmT¸»è)¡õ<…PÎÐ;E°ï'¸ýdíNl×[J§ ð;!Äbr=«žÌcé¬Ä»Ë±Ì.‰ þçÎLïK?[òõQ…[¾@n!AeÚp}ÄH_Ö»¤Ù<âž Èžœ•1‚uHijp»sðRÍ ÆÀ•háÀ»è-G,!ªv;¥’´ú±—Ê6ánõ³—®sïš3œytDì±\Aoq…‘öF83ÒäÞÔƒ]?ÕnÈËjÕxfˆæD|N.R*â3µ¿XÄ€G\ »t&¿êÉùÕ-÷8ø€«_Méå­ûè·­ØT2wdI‚wwvvØm𘫱®|ŠéE ùçËÀç”c´÷“=¾Çóål>ªîøßKÈoü—ŒcüLïÈ8¦e[aýý85ÇöÌv÷Ô™‡nÁUqOoÑ´§ÈOøâÿõ˜¸%ßÚ3ÊÈa !ÒyHoÄ‘þoŽgMâè¾]‚ÄŒ$Ü£o2P®~Ìýì|@þ’ê&˃^úàŒ™¬Ãh"%4…ªÅqIžÌ@[©4<Þ&´üÔh™[›Ke™X÷h,$Ù;wÜ™9U%­G§2žEÁ0,Û5¼©oûRÛ—ÕüÌfA>b=S ™žIKpW’9x¬±]gLÜxÀŒGØ4÷"gÌqŒÙ H ¦Æ5ý`ásãÖ¡•ÓƒÃ%}}÷qíÏ@×h庘íÃH0ÇcDì=äÔa]9Œ;£è1[dAa#Ê*ú”¸ÀÉΧTËNeƒ ÅbaØò‚ˆÁoˆ€]üœŒÜS<`VžDRœ˜eo!iG6°h‹ñëo¼¶’i•Èðè˜à‚aTÅQc%î…ÿîãÿàþ»r|_9Q¶³ïŸ ÚÇâ k×ÿ{obÄ?ÂÀÊÜÁÅÃÏ”âõg_zÈ©É)ƒw÷a®Œý}XêÍØÁ9Ê[ñ¬)® åð4ÿŽÉxÿë÷Ư¸·*,õT¾À~³Ç¿õßà7c+<ÿ„Ib°üØà›[$ºp|µÜ'Ð/a¹Z„*! ’6F@ž†Bú@×»”²ÆpcbÎì©mÒÉ kùî „Í# ^ønÞ.>˜¨D±Ia”1½Ñú=¾œNd·J°ßØöF+Ce˜e³(g‚¿r¼°œVvË¥T^‰ØÊ+ׯ‹äXy31€´ÀÆÜÌpÁ„ûöfD &ß«sùÆ— p:¬9[×÷dÿ—a¬/œÿÕjvCù_Ýî6ÿkkÿß8û¿ ýç2ýƒ¦ÿPRO¼íŸûóÑJýM¨Ø,.i%¯ç Ðæ¹ 7Àøt„fmmG€’é÷,>l^‚É LÈþòÃ’Lf;•Õöà™ÛV¸äÇúTÌ}0áFu–Ë4r@“¶NjüÏ&È»'Ï;#Eù?z³Lwjc–µÅš˜;KþvgÁH¼ÊC«¸yÑrðþã-Ñ"DAjÎÊ%£ÚÁkUÉ·÷%&™âeÏABXê°W¬ ]Î ƒØ$‚Ëf^2Æ|ÉÈ´ks]3‚‚~3’’âÏí­#¯þ‡=šž X ðþærɼ«®…0‘û ‡¬'OM»|:Ѐ¶±þh‰V ™¤"}ˆ«è1§²¹\ºöEø‘>½Ie_ølkÒpi~ÁV„üYk£¤fòVˆ©6‘in%L A›ÜÈê-ì9»U&A(§AT¡ã†AŠLÖßDØxËß”„½&À„ºJÐcàôhÔ;GDøÛÈd|›sí±k£†âïät™pÈÖÿ\#Í=417ĉ$â³åâV¥Ó`%\c`€«¥™2L!ÚW#Øà; ö ¬vJq µI¬x6!ÞNþž‘-àVc85ÖÔŸ(Â×\"h7(°0%Ýäܼ!žd«~ºKú¶ k03ó ‹ù¶LòìÛU«z¨Ã,_GÂ!3/Îɘ™I¿ÀÏCd(›‘É3Ád++4 KÅ|ã’ºsVó±˜Z_¿õUP{X§Í’äˆÈrvÈÈ3àFçàétU­W<Ö{eEž øvöTß½5öE‚í›ý=ÌŠÜ3àòùhÁ ¿ñèÇÁÁîÞÅ“L¥ØÛýþ_ï—ßo/~©œ~x»»O:>³kÛ3«óâÁøžg‚T¨°ûç12þòÆú:˜Qý+Úr¼… Ð>EåЫ\ÃÖ§içhàs‡ôË×™:÷{ÔþÁYya „ žû÷Öi`Á?ʰj"W#ðëA tž)Gù,«Ä{pùcû_Œ¯jâÇ·j}ƒqø¿Û§ÿ ÷T|B¦ˆhþ+ÌùwC¤îlìø¿ÿïïýðªÿ\b‰Î¿¼QúöÇßúÿßTDzP"ÇU…}&çTæjOì"ˆÊý:üOŒÿƒÛÍZ­æ¿ýs¾·ñ_Ó×iVKÖ·õ¾ýßT~GW/å÷}°æ£P…¿de¨&ôy¤õyjÍchý±¬V«ùÇ;vìeí…Æ{‚ßd§¼ÞÐߎwBßMz›ýþ—.¿üûçþ¹Áv8J™C£I`ôâ¶zp}í×Oÿ ŸO~«xëã ‹KEUðVÇÒƒu?ÅžabKÑ€•b‚¿rñõ«ŸW÷›ñ«L¦ûÍ8&ö«ÈûM/ÛF)h”]“Hyï7 µ8¥öñ™K kïz¬*§$NIôçÄþÞ/p©4úó±ë,œ¯{˜©îÌí±ñÁµþþ0G³çÞ_:A11N@ÍŸ[ó/||ayÀœµ÷F 5{—ö{iuW}ê'dzLKõƒkTwöxº!’Í©¤ÃºÎÒûòO|€S×3~±¦K9ЦÄR aƒjw5æûéz"Wc:æîµ~S™Ì?ýmWá®’ûì•Ó 0S ÄØ8ðµ„lF™[ L&¼X„ª+4kõ#ÕB¦<)ôéŸ@ýÅ*†Å>gé«L½de…†Ét±y/ã*#åþMŸ©~Å£XŸª5>uMÚSpõN]¹( ú/¹UͬQa>$3UÜÚËÇá tÙ8êÔTý*êÑûÙ$̯æ–9æyõOBïF\=ïÊà¯Äå§……µ€V”wCú\ÁWôì{T8|ü m,XáP`P2Jýáxr8~mÔô“AŽtËËÊô[ØFý©çÙÜ>ÒŒ·ü©0æ*öÂ4Â;ÚsßïÕ/Æ-³±â€QȬÌCƒÐáda–¸"ú•%"2!¦£TN\‡òŦøŸâº¯è‘à£:½¾9»¦ô«¼\ k&º(»”`Û!{%º/áÙY¼_E–z«Õhwb`T‡.Ý̹"Jœ¢ä9@šƒØª:r¯Å¾ƒ,Î 2¸’Ê£ sä:ÊE:€‰€®vƒ®È42ÂG°Á^dýæ.¿(ÀÛÍ «Jsy…~õ½×%äCdpyæË†à²fÂ¥¤¨]#<ŠâÐvÁb-ÌÑ3”IÁÿl¶àw=þ§ÝhÖ¶ñ?ÛøŸM‹ÿùélø©2¼é_ÞöO¾• Á}-Ûú_Ÿ`‚§ˆ@úü¨˜«¥ƒÇÒJ†•þçáÕÉÕÅÅÙ0%ØqÆã@t‡l”¨%s*cŠ•˜««ÓS¡ô:ÑBK`ÍÈ¡(ÆæŒŠšÊuS•i*#N(È7©PŸ‡‚}ò "¼Ø"<'®ß>fàRTPÝ/"Ìç•»2|ºGÝ^¯—#À'ùäPNÉÜ SZ r†½ë¢£"ùeäžö"3ij9³“Ñhï=óþI¼´øœ^­Þª½J|NVºñgsçgep5E°1`îËý‹ñ,´‰«F¯AX¬‰ }Ÿ6á;°ó ´ô€ƒ^½^ïµnAåÅí¡Êº ΰï7î„‘/ï^8”6Q·ùÔ…žgþÝ!íeÆaËË@NH:qùÎ*Ã*"Þ8›iμs…¿æ:ÞaA¡ÁE;°Ù}avaæTƒRÕ™b6{ ªR)ø^½ÝkÕr9àí¹zîT pyvŽ ‡ÌáC°~þQÐÇ„Ǧæra, ×šŽÉ»às{ê{BxÁ»ûÁ3ÐØ? 1°¯ã#&ú—ÐÅd~­,LÛõŒ7ûû*<±ŽÍÈz=ˆl!jT/Ș(J“gª4·L¯Ðk"Ü2’g'YÕ—0°1sí>Tƒpµ¾Á͉óÝ ë&Oó²IŒ!ŸZ¹ç­HKž¬°,v¾-ë ê5jn#Ñ$)!—‘w¯§»†zFMõF%»†$9·ä™ñBÞžhëäñ£Ž&…çÜYª(û“?pþóæô­¶ê4Ó½9Ïå½AcÔ2þÊ~;ìß ·¨G@°¡þ‡¨›>¿áÇuË^)Оxê½Ý\Ÿc‘­ØþÄkz4ÇcM02Ò+Ž ¢zª²¼ÂXPùtuOWBã%*FXÁÁ|äj${“ ùzÍF«W‹ñ¥ ½Íñ€d3Ýõƒ„Ä@IðP)–\îÝò·N‘¼¦Ä?yj9Ãr¼å=\d ü×z³^¯ë¿×Ý­ÿgëÿÙ8ü'¶Q(º`³=?æbaÍÇv >ÿôÿÓ¯þãN…âüzøÂKpÿ”Ò ê ò…NÅsF_¬€¢é³ hÀׯ‰¥NûšÞ9ýÈ]¢­ý½Êtä>-0 ~Û;xN—è™V-}ÍuZ¯uŽZGun}Ò›Ž_­pò°¥¨bä›…Mo<9v [á ýEkÂYoXBŸ»;~‘6›TZp½'8ð™´ö½‰'ãëQÛräDûTä™vöV”+i2º-a Œë$nZÔ6þgæàMRÎz&r[‰äöê]n5ŒíèmE.£H77UÚOö8?À¤i&Àïö]އ//Çã øCUÞs8 ¹ÇÍ3Öª—ãåR³ið}iè××â0|†ÅR§ÞîpWArW±+ˆ/,ã†yO†´ /f ¥CöB¤,˜ÛS¿ÌÒ7»æ2(ˆ¸xgMYó¯¶ëÌ oQÄxƾg鯨8çäxg¯ßQ Çñ!:m<}áЯæ„(ÀÆ0[ÀÑ8®À˜ÔóÓ‰'A-€ðÐ)(„tÙÁ-á¿e‰WZ‘9¤_¥L,òÙµ(¿¶‹å1Œ†­ˆÙ;¬Ä©g “/=¼ ÝbùD/ñ/ª™É¦Í0•ygÇÉÈœb¿x¼ÓKŸçö•SgfO™–ëQÊ3ܫÓëwg×ëá*ÜäãÍDwÂ;sÉ Î¬Ì“—ÎZ”E^Z ]”¦Âit¡æ ¾†çØ‘µyQ"6‰skNº(w¢),à†TrŠK¥6 ÏsPНùˆåÕœæ×w m’µhŽ8T2’=Y¹TQÓ]Í)«œ·$É/ŸÖÀq–ƒ½ð&Šª‘àòغ[Ýßãƒ3E˜oáÂL"?¨“¢7 ÈZJb«yÔꈤá0‰QÔƒ„›ã1I3ñ•Ú\ßI’Ã’ËY’f¾Ù÷IÈì¶…ÞýçÇÿx¡”úV·ðÿt;Í­ÿgëÿÙ8ÿÏÛÓÁÇþçóa…_¿úðoƒ“ámå¢ÿså|pùö[Èrœ8p¤Ï<ƒöê* "˜ “‘9ŠÍzO’'ý“Og—?¼M¬" ¨*ð—‹ëm‰b÷•›ÁÇ›Áí§Áé+ºˆ2¬Œu†£øšÓ”¢×«K=e¤¥ñ[ªÎÉg[‰ÉFiQòY°yæ`ÏV3c¾šÝYBɉc8: jn, ËE$+Ã4þñç"%éGnÎÉ›•Dù0‰>-$ë¨Ûhu”´ÿ9—µ³÷¨ùj:eÅÇ-÷ _@*w3°”œ`ïpé÷®=*à;3\XMgçòj¸X+uâ¨Ûn¤`5îîP 9Ž€> ²'+Ä,•fh9ÒG‘t¿åëQÏ1à‰LÂ*$âõŒè(ÁÀ ÇÅâé3°2ÿí DhlL ÖkM‰,%ïà¨ÛÓÖ\zÞÁÎ>Ë¿o“wõ[dznÐ!ý!¨}Ô«ÕZ½ˆ@í… {¢ãzð¿ÆKÇ¿èš)+zô¨—€>²¹¦ŒxÑhQE¯+Á’çìÎe i€`ôk’«ÝÿMg|7z®êŸ©ñŸµzK©ÿÙnbýÏZm[ÿg{ÿ߸ûÿêôÃÉŸ.ôSJß`lH¸¹{¿c¡„@êÒ¿ŸÛˆÎVšÑxÅ»z|ÌŸ_î[Z÷ÆîómƒÂ<Õ¹Y;¶“øUvX'F\»Ë8S¯íYo×;5¸ä ÷Ì6¦p(èî›N‘èßŽÚ ÞÔ],¼š\,µ?Z÷®sr.c&ÑÌaœ~8c˜»;~C"ñò«iOÀ<‹¹Yºt#æÜ™À…7s/ S×:e}²@b\Mz$Ÿ1ã ­äÊׯA–ÀHzX Ó GEæ\:I“ÛB Ò£)‰tHIQ¯J ÓÚ;jµ¾•PÊ69zùPʱ7Ùàȉ?l×» ™v_,þ°t!}2rĶàNe0¢ž³rG,ˆlö7ðklÅo*߬ªÒ@)0—eã/añÂeÂ|"N³ñ> c²(úëLSŠ´,„Ûu«Æc?=4òÉiºCšpaíšR’)Ý{ÒË)Õ!c”¹Ì¯GiiÈ· ”½‡éâP²CX|s18lK4'ã<ìoŸè¬Ë(´þä¬À~uæãÃu˜…Åêä¤À5r5›“rãek5bÒ©EØË°U@®7Þ¾lQðTÄÜ„nÜôùa R$ˆíŽŸs1E0"ÓRZoµÚbmŠùÛ—ƒÐY}À´ƒ2¢ÞmÿÍN.´ý´ ÊP^D–ßM©Wß‹A˜ß—e‹©J2+ô†ã?ØÍ»/1÷ßìïÓÐþÆJ5cUæ½HŒ}ñoÏŸþÁ¼‡ëÐ<åéÏNAó†òç¼ØŒé ùƒOÙúÿ°j»Íz##Âÿ…3–ÁLŠ#TD^lû8P} ³×Q‰^Th8:R¯ôAõûùÁôñ—`Ùd_=å“Óàõ#Ô3â5—Ú¥ˆ¯üÅ`l–Æ$ÕF_©ñOt\+ØõÄYa%W¼D8K,”ÅŠî¨dIÜy7*¬ëŽËg"ÒÂ,@p&pœ©erí$ >F•ÍŽ¯š­ÔËV hGO}ÆzÙ»i_+©Ñnúø€¯WÍ:‡—!.'Io¢HÍéìNŠØúÓZÏ]žæî¨¥VùVáõ³yJ6¢ÌpVOI®¸}…o@€ˆ¾Ü·Ñÿ$ñ(‰+„v´t-sæ½týçZ+€ÿÒ®oã?¶ñ›ÿq~v;¬€FW¹Þ úßD;’BH,ØÆÙ»+ãF|éB‡›/!"• Ÿ/) ÑäF“êE ìD|kÜ>y ï¿bäGÄt¯ âÉɜ᡹[·ÖspFʈñ2Oª¨ÁÓ¦Ä8`Ÿéq޶=¨ 2 }ëürvç:æxdÂ÷œ2E“¥YnºÁ!'È@r²Ë糄†´º5,ÅYZhHÕ9ëC/ ýåy#*ž©*4p²]¯µ^%®"ÀµtîÕ\"ÿNœéÔyÄeÓCé Ì á£""3±Ä:•å¢ãKXØ¿UR㘥)æ^5Á\„¶êÖY­9«wS9ø<•·3UºŽŒ§ˆ7(ÅIÞ‚Ë€V›4ÂI~C’„ùÆ}—òR¦‹”G)í…¥Œ¾“ôºÄ¬uãw¾ÔçÆ@i¼$»ci.ìœÓnäC¼‹\xÐçêÌ­Ø@ˆI"/ LÒ>—üØ•õ{3Ê4àcêÌž[:Œ ŒZ,97bþ¹£ìGO÷¡œ`  -ÃÕ×ê6ê|WûÁ#Û8&ƒ01O¯%M^ñIDÏfkqÿ/ÿ:]~wË6î—1ßlðk—žH{  lÓÇÂæQÎa<>‡E$ñ²[0iÛ^/”’1†Yð˜}Þ&ÛµùeƒÒ¶êš7yRõk¦ä¸%ø~`âz]= $›ë‡¯&Ý1Ãb½'ïøX•KŒcwö½ï¡I|RäUxñe|†šþªòF†§ÑkΟr´/Hc®$Æ1Nñ—7ûSsv76ýÑ±ÏØ3µæ÷ ùî3A™Rð5¾Ç~MøOv~Fq)‡2ŽYáRn•äl;ªÕzª‡2Ò×¶CÆÙR|lÐa£Që%»ØvJò®ýDBAÒ¾ü‹’|(Á¹ð«¾ˆk ¸Ñêô²§Š™ˆ(Ÿ ôÛ©5“²{vžÕÁ ¼g·Ú(›Áà#30kA¼çBmâ™Sj€_GÍŒ>Œvaä0'¬Q‡h<-Õƒ‘bKÈ缈°Hm€ÿ¢PaÆ2|dÿG&“©Õ¤ÍU¶ ­þO«¬ÿÛ®5ë[ûÿÖþ¿iöÿ¡¿IŒOÀ“)‹½ßh?@‘·U+ÿÌ\T(Yoã¢]ù÷σ›_’êQˆZP²øšÉ°3¬ oú—·ý“áÙÕå+šícfvMó}€w9möôTñB?ÑÌ/hwA(Xr梸• é¾t8€˜ž=%u]­Š¡îøK{¾t 4‡ôY‰W^9„:Þqû¢_‡W|eàW±Àéz"ÿlñ`’™þY³÷´ uK Üòq¤8J dOS)21u€y(œB³ÈÐZeèwSgôÅ;¤ÀW{IñûÝìL©¬õ‚Òo~ã%Ì]%™xÎ\-Ö\¦àNe;+—i¾¤÷ªÛ4VM±–µŸ`»ÞÛó n c£VmÛóï þ­mñá^D…lˆB“v6gb6O0–X›’ Û™$Ö¾C\ÒÜN»PªR§¢ÿyxuruqq64fxÇÙ÷,+¦¶/FŸç1:Vü¦âƒÞ´&” Ó¸² ˜L`?br*dâþt#¥‡qTæ•÷±´RÈ•[ƒ,üwð6‹Ë´þÀyƒžž’/È0’=ª&ÍsC:Kœ‰ÁÕOwÛE¹p„{ÒbÉ"74p&Ùª 4¼X¹ ǃVÉõxû80´«ºq:#}êêyÏ–KfJNäô+È>$!¸e´r]J™P†_ˆJ”1(‡87Wççú'ÍLé ¼ÏÙ  ÂJi£²àDŸ]ªÓ]¹ÎL|ÎkŒ4óR]wI­é‰‘LŸphp&Ý£²ØX0,U [.•ÐZù°0¾U[C•OWWÙ§‡Uâz2°Y±…ÝÕœáþ)§?…ÊŠXSIƒ ­ÄáD«Åu¼×%f’‡èµE„"Äš¨Âœ–J@CJíåC„ üélø©¢("^ X†×•ÿåCð¨Ò N¯×ôjv¸Ô{A¢%*üTëyî¹,kòB¸æ´ˆw œ†ÿbÁŠ„KÞ‹×ÿitš¡ú?ÝZmkÿÛÚÿ6ÿebîòdðÔÿ§Ôÿ‰ ý˜%ôWHŒˆ˜_Á£$ã »B“žPý[-k¡2ø˜~[¹~ueÚˈêÕ¹·f øI\Ë„=Eå¡Ã–°aÄIT:2ŒèÝCqSÒÊæŸ…ÏòҬ׺-5¢Aqΰ^çqž«¶ï&a¼4ëõZ«õ*!º!¶å©“i›ºkN§üá¥ñSBã‘Û…EŠ&fX§<Ãúã+ŽpBUhÖ¼êsbÀJîµ[yÃ<9ez™c!X ßð¼‘%¡m´+©Ó7‰ofç´Î,“°`LàÎ|úäKqûAG o+U3¨i†R5Î&ùèd5ØÈHÚ¹C3`ú•°SÉ×§Np¡&±)‚í£Ô/PT$ñJÿ%€£4ëV£QE$c:÷&޳w`¥AmíŽV¢ï¥ H çŽ7œ`Ÿo+–Ž«´öšµü¸Eø‰<µÚ—Fž€åˆ.¢¯?'7,5)/@q.®@#E@ ²ÞÁbC(Õ ûïš 4´1X‡#†óþí0l`ð’CÀåàç ÌézU€_6V³›„]Å’˜ë«Û³d/lTƒå„4ëÍn[yÑÁµ¹n?t<—•“b͵2{›â›f[(™_bhoëBþ_±Ê7Á”ƒ›äŒ ûÿ*Õ…ò@’íÿèŠý¿†öÿV}kÿßÚÿ7Îþÿñìò´rÚö?ôoß‚ùŸ§nÚ`ŠÏ34cLŸÒ Ò•ŸñKweR…d¯´è—àÝ èÅ*Æ×::TO©&ÒÚž‡Æ›ý=yÛ3à:þhyö ~ãÐãxöäý.+Ó§ïø³ïè‘Ý}>óYÓ®¶ ó† •‹_à¿Çô_ÿ~öŸ­^ó¨~zrú_ª£Éû9“hNâÈ Ã/_ººÖ[7ŽA‡ZbNÂ’wòÙ0CÛ 0#ܴ‘ë«Ûá7d‹ÿk€7ÓFnÞ„ˆO\+hY[̼IíLyx¤¼Ñ£¦ºDÍWŽ%ÒÕOÚœ †ƒ]¯Ïç@ Ã$Þ¨[ôWß¾]›˜õ@´tÛÍ”@ò×çkøð쨧!)¾èP„&°‹2ëåÀ7ÅÃÅ«µñD;å…^4j]½P`rèÅO¤ñÓ©äYâ*²WlžÁ‘éUæ£Õ,ÎAwR{(~¨Žb$ÁöÄÇŠÄÛÂN±ËØÜâ7òÐ¥l'Ë} àlªë„¯À$¶ºíWDáRå~À–/Ìí—ý‹„’ˆ{S®–èƒ'†Út{=8ÉF”ßhò¤q>ÎÑO„|µ@¿ÑN›”‹wW†åÊ ¥ê?ß&åçÃ+Ҷù28¦Ò¨õšV\˜ íæ¼O «¥ÉmÔjÄtãXùÁ.’ %èe3£]²úÏŠF¼h{±„ —üµ|±/AìÄ¿Äyq·9¹›’ÿKÜ×ð^2ÿî ÁøŸv·½ÿÙÆÿlþ_ÿùÇ÷gÍÿ¥¨[VEoò,‰MI…~xð;"ÑFFÏ#@ëk‚§yÍ(Ÿ·62Û74)eÄ÷謔 µ~â”á£÷Çàn,èD§>)A %(ÀzHÑsDöÔ[f]Í’Y3ÝWg]¶í~.£{þ¹³ƒïÝZ·ñ¡@Av§±àõ‘,÷³q1™fzJdmeŒ€õæ|jéë'Ên³šÿ鳚?ˆ ®çLg®·ºº±?"ú'I*³ºjl0tÇ É®!gÏs›‡y7¡)/8Éùss &= pQ™úÌ+Ô‰tc%ãÙúÜÙóõRˆ…PŠÎyæ­FÒ‘;áyWØ¡|ªsÓ›”¸•ø,¨ÖØUBÆs½Õkwùjé§½ñëÄq~ŽÃaiùÎ@Y·Ù©½B¾3ôÜëªÚÑç;×[GµÖQçõò€zO+ù’ùÎLCŽº®‘Ò–éL¯MsŽè›Òü’{ö_-Ðo¦+îû¤¬Törù ³° º 5¸6¡ÍFçªf¸oD¦j¦›q.;½²†6ÀB¯X]¶Fù?¡ýŸm^c©ü>ÒìÿÝz-€ÿÙl5Z[ûÿÖþ¿qù¿ClL…®¼@×?u] ¥ ÌÀcQð ¿7Ÿ/OðT‘É îsôÀD‚Ŷ-¯Âµz½Ñ·'ý“O\ß$°é³Ámåtð±ÿù|øö5³‚ó­‹5Ý 1œÑêB©SVJ¡<|]·þ€L¥Î7›… å\D¡"KV86YÞ1S›yrE²o>𮯖'éaÆ={ÒdIâÕè#cÑ|lŒ­©E¸Ö.¬žl…™õšGÜ3Ç"/X ¿EIÅž’Ùƒi3òcVŽ ¥ZÅ jb •¼Æ ñˆM+ qS;{Z`.ÎÌ'Œveô`xÞ›¸nE^)#ʨ±jq×HzA¹@*#îÓC¥;àY½¯Áσ“Ï ‘±\Dÿò4¶×@#áÚ;rŠ«ó:Õ4Äx;8OŠad¯¨ãß!⮟äæP/VÇ:T«^Qe´šº+†† L9¬,*ñ+ e*™‘ì›urÍU6æï˜8„‚ûH;Ýß‹c=»@"ΰ¯˜¢4ªÓLK¬õB´…Žã÷xçàO@8«¢©êTçõl¼vÕ~BGþ™ŽoÛ£ú]p¬ÆWÛDÔshkÅF,º%Õ¡Ì ¸0˜ÓΕÈ)b²Ž…«RßFM²ÌV…g¬MVȪËñ2Km€û%E|V‡ ÙÿÇw”=S™™T&®e‰¬ºâ­ïH¶ÿc&k=ÿßmnñ?·öÿͳÿ¿=ý@yU•‹þÏ•7T9)ÛêìêòöíŸT¤ÞÙ¡´ÖóT´³<"ûm‚ Æh‹ËC)·_ÓÜŸº Ö4ðÇðuSPA£gªŒldÆJs}ÒyUb.A25¤~rÑ2ød †B†á=8«éX˜$ÅD ÙŒuà/–µ ×"1oÆű$ÊÔ¡Z­Õëu”¸:ÿ91¼3X&÷Øa¦~øòaqó®Úµ† ]ª=*zkeì'.¦z©·U°„¨˜bXŸÀw`;Ü‚ C”þ¦)¸³&ˆõˆ—?‡X5R€ÐF3¡I± 7šXì¥@vÃfª"» …š™;põÆÚÌè–±9~Z‘¡Õk墑fÄBtÙÚ@›¶a~½§…À/@¡edÞÁ ŠPü Ïþ;‡aQ(ýZ¨žÖOø¸{{^AAslÔªm{þÁ?£ .>Äuß ¸Å°!`j“1• z‘˜î˜“Â/Õ&±=&Ö^džÃл’âÒ²EÕÂÂhÕzµ‚†íEmjOli–?­\ ð™Z~,±lCü=4P¬g`ô¶Áâ,(*-]œÇ¤‚‚™È¥ƒlÀúC¬a°(K \Oì¯Clz„ Sª÷Õ ¥*0Θ©EæH)Ǫ¥§k\ÁMŒ%ë¥dg ©¢°9E×îcµEeö<ëß±Æ!Eû ?´Q‰~±'C4u¡dÝsë cÃ_IQÏ‹´ý(ox•eé³Ï‡ÑiL€²3•zD‘þ•õ&§.\ Öð#•eùêL¿Â²aFmÌÞlįÆv^r–¯ìñkÍ’ßÿsÎÒv‘kpoËhr†X­• Š(ú!ŠêDÔ§¢­Ëƒ<õÊ%žâfi<d3  ?ÓCtº+€íí»òÚk!Š’ç\²¿íúHX3˜NPê_[ŒW$ϵ$ú>f>u'òO®ר™¢ž¸ÖøP™NYÄ ‹ø¤/Œ«~¡¢ìÖQ«—Z”ú=ƒ|RËdÅ /ƒb½ÉhÙlkx=4#PÜsÙ r9?tkÒ&q°Iý3x>8þƒê{iü‡V·Ó Ä6»ÆÖþ¿µÿošý¡HüéB=K(Øãˆ¯>òz&už×´ô§|ØNuÊ0öK* |=–hÚ—½EÿƪXÒiÃ&ó‚‘—wÖòÑB|ÇQ9iÞ¼9ýpqû,µÝëõ^Cƒí[Z²R¨ÎQhÎÙÊa¥–èÊüôÄqGûܨ7Mµ4ÚÆ•€×,{KÇóy<«[÷”z×jeæÝ5‰×®*ŸZTž’7&Só^×ßÇ‹ÅØ:¡RoÚ€ìI±:op'Árœw«%§ÃøU­YQ¬ŽXˆÄ{V]. o‰XÕ¡ÍÉGŽÝœ‘…¼Z^ôâQ#\¤ §Ž·ÌÇ‹aùœÈ„jÌ uw=šžF•Ïö¼É ã²å¾C\áçÄÃnÔ›ÍV»“èȺÄxù».5Dm^ÔjÙ[Âr§O¾cLrsfÎᔦReET«¹àéaÚ*Ñ+:kÅ …ôÍK1FÅ[2$n=ÊÕÊÜJúSÁ£ã$‰¹’½8¶‘uÈì«\‘@$l¢ÌØÚ±ÝIL}†HíWÚÒ¡”¼§šœ–W¤Cä¬@Iix*aý ½`µõw<¿âzN CÁ7*PNПQîg)‹¬Üͨ…y(HmJ–bî~ wî}5~¥ÓÉš »%UÎ0ð°’ÅϹ ãõ0y÷䕨&—1CÜbÞsä.‚$0$¬Œ <’Ülë5)î'¨eÇùÅ)Õ ±‡Ë¯¯U|½Þj6ë<é%ay®ô ÿ;ŽÙ¿ÂóñÌš9îÓ±qu=¸ÄzÏ'? ú¢ºµjÅ<í´ê5Þ`YðñÀ£V¯—ßÜ´}”{ÛXùÉæZw$|ø¡ =‚BŠÉìêšðõ0ràg'#|}Ié6¹ØRBK–zÔXA ÖÊ ßÛ–OžÜºB}åÎJåøQ6¿lfê°›¯öF<-Îæ€øõ6š®·)V/R9¦Èk¸{^ó4¼¡çÎ÷‚uÒ®7;ß>R^+æ¦äf¥Ù5s9%ã¬Û›àž$‹y‡¤ÌÿYÚ3ËY-Ÿ!ý'Õÿתµƒù?ÍVgëÿÛúÿ61ÿgxv1¸ú<ü“¦ÿÀ Ç•Qtá@ôáàâúê¦óK¦D  &±1ÿAÈžoDúOpÎKÈþ‰däF¤…椬ì‹Zòvø”œû£õš!õçQ³¹ù6¤Ñ3€ÊêKeý´ºÝZ¯Õ{¬Ÿùxii&Z{s¶ÉGÛä£MI>ju{µF7 o(OΑ¥¦jøþ_!VxVÒÂuP,£@ò,,rÈ5'ø‹¥ôlx.Ý(_=œñ\aà§rÞ¡µhŒëY¢f°Ü„Ø|EŠ£îµf&DÆsfm(3¡%g”¤ʶ OÜFdUl³ã¶ÙqÛì¸mvÜ6;n›·ÍŽ+?;®Õ=êö­ÜÙq^áô¸Ãüoªš¬¶ j\¸Q¢ ë&êù zÞÆgèe´ÛmXš^&›^î ½€­wCÒô³ñ›0[ý¹ò¥ë?×ÚV7˜ÿ×®móÿ¶þ¿óÿ ôŸ.ý¯”µ’ÏÅJG¼Ž P™ö5=á— IŒC].Áõ' €Ëò ü¸)ÑÑ'ã]Ñ¿7daŸ–K0U›NKÖXe0¼tâë¥û{­Z£}Ô(Ϩeã÷$`+ ¸Y¸÷†w\a–¶¤GŸÃÓi‚rpÔÉà‹!îØžˆüµ\ö‰_7õùO²'TÄ|¾|zp¹uí¯âå­î¨'Ë·D0b±<ÎåÙÀ@lWíĸtd­l–„|í–¦¹–¹|†ŠßÕ¼œe­›•˜CØæº“%žQè.tªoohÿâÞjUÐRà’ZTa•Ð+„†¹îµ0 ÿ½Ó à¿4àÃíýo{ÿÛ@ü—ÛáÕÍ“­*7ƒþéà¦rûËå°ÿs°¿‰k!ÛØz¨¸Ü ß ¶ÆA,âp3>UÆp¸`±ÖäÐ;8¿:韟ÿR9=»¥"§!þ%Ü'6FKͳtóñ Ú\&tñZp2iËfÍkeÆéÈyÙŒYë\33Lf9ð3‰ W@i¾R¡j)¢{«¼¾Ý0² ï÷e5»pƒ°–£Ð`²*Úž»cùpµtŸð{è…9r lêx„k5ÅÖ…°Id¼ð8¥AÈ”ãlÖTØËxðV¨­ºf˜!jl5“à ´_Ø¥·¡¾%2h3›ÌŒ—)3׺’R'SÜeÖ6evÎpi£cŽ€èT`16ï/Ëâ•”!͝ŽÁwœú¨üŘ©ô{|DÂRhS牦JIU‡µÔk%TB|ïKÌWfº8J²­q°§®¢ØIHë/0þ’É/M1y¯¤ !ËzÊ9ϱ)÷u¸"µÔÜ€¨”{å@ ÉÖ+…º`Z6_„ìÜ0ô>›/à*0±ùZÀ@8::’s'.FÓªw“Óè‡ žFôÊKgzÚm5o7c:{\"oîs  £#*h æÏ•P¾î‘Qü¬È‘ ¾æ™°Æa•Ȳeèú¢3/åå‰ÏdfVâK»)ÆØA2–@‘(³z­ÑÒª>%D™©×´°v¡€þÄKú’ý"äñŒ‰ëÌš>qf3gNmpH¯9û¥© /¶qã· y ¶fx/Òj|›†h|£CÐ ßô‹ú>´V×w}4ärƒ¤J¥ p…$  tаø/×YTüq½4þ{³«â?Ôÿ>ívkÿßÚÿ7.þëæêºrvy:øù[0õOÆãi@íáGÜb0Ñ8Å3‘%¯ž›óû•yoûOOÏlÿ,¬ EH±á€1(Á¢7öºû:?»²×¯ ÿ®Móš¦ù0·rZá³ÏÙ:†ùðœ”ú%éɳ¦Ìð/ÙÒO¡è1ÿ9Ý{µîQ§<³¸Ï¡À*𚮵˜š# g@lΉ ¾f|Ä{ö¤2v,¯2w–,%æ=â]Ys2ËÑH­/nÕoôêõN«÷ðÁŠ@³Ö§ÙuŽ} ·×Ár`· Ìn{˜1‡çõ¡²D@i8Üú,ç£Ú4˜Hާ9ð²2‚Ò‹?@I?”TB休m¿´ñ%ná,e´V ˜à MVS™0éÆqÃQ—î`y5îq„4gq½ßWÌÈÏŒºÞkÔ{)xRxÊ6ã.ª<;Þ, Y·¶r®)„ãö‡€«Â@ÈSZ"î5‰;ù@V” «‚a–'²"xÈQ'»jno”èÇ T+/ù9œöZ£V—u¼Q å¢e1² \ TvÙÊt¸ãA¶©S(wéÈ\e1 õ­Êjc+¦0/B.piÂÊW/pEÙS{ùd`}iãâ dt)àÙ½Fï(xö>Îãb+ ã׉ãü&𮇻ûþêa_Ç¡Y4øŠo%· KJð¥<@ì^³–Ý;ןóÙB‹- oÁ+òŠ“¼Ž§XLë^³ÑP“›1­s‰ªòq§{Íf·S+Ž;9%?´¦¿3S4Ù1jwO +™‘þ¢Á†ÅH<#ß pïÌßðãBÏ/,:HõcåcœIòuAZ8w–„¶ù^ÄwšÑ, Ë­¼^Äq—ͦëŽS^/л._ƒ5¡kî_¹Ž¥@o¢|gZ£×j´TÈöxgZñuŸu÷{¸°?ÂzTÐÛ”kFfSAHm/–ÁPÐçŒÁykcÌ¢óDÒ?v}(-ÔCì,zÈæ¸ã²X÷ŠzÞ|óm ~·lö½|ÙFŠXÛš*ç¶YE¹üÜ0™´‚Vúò]€)þ¿f­S úÿÚõæÖÿ·õÿmþûàß?.O•ËÁÏÃ?± P 8~€’EçýÛaú»µ¬ÈfŽ-<Vds×W· bø‘೿. |˜‰éL˜©RáU®ú¨ðê‘T&"¼Ú9 Ïæ Ä‰\{ygU݇‚–çð 6Xò¤<¢Æ·çu"òí=SÑg`ãQ»ózøÄœ½¸“ïŸÝG–©˜pptsÊ.¸·ÜçõN5nMͨ‹ðNù¢ 1ÛGº”Ò–s^í°°6ónÂË‹Mö:^`呿èËàeÐ_Ý!ÐT¾E)ªÛJü¶øm§4C³Ñ¬7U\ Dƒ–ývò,—]M;¿“¢Œ¿ÙUÇŸä£P3‡Øè)vœœ,¡C¾½š)¦>½„iéþà“^Ÿ4£ä'{: U”/ÅešU´Ä*à·ðýܾÞxî5étF5jµWr:H 5Êï TÞ4׃h¤HV££‰ Ð¼T´Šº?ÄûQAAŠ D6Q€)ø£ý òæ‘ê 5´1i7ôT"°B¼ßÇÑ`ù~¢f£ÕÕê}Gû‰ò\¿cþ¹<3›]66“‰c#ü#9ù ²Õ · ÙQûnë2ùûü*ÉÏÑGšÿ§Æÿn´»[ÿÏÖÿ³qþQfûφþÙÜÍ€ãy&á|³»…Va xA‘ѯèÚ»6¾÷f¢{GÍB)Îâ›ïµ¡ƒ¤Lw µO~šk×&ä—‰ãÎx±Ë;,›Én”äçHõª·ª%e]G ±J\Èå"½ “ÕtúÊÙTõNý¨×z _Kpðæü¾qç8Sˤ˜jºcÍï1W€!=8Æ‚–‘9ócÅØÿ™lQ–ÇõæÈGÌ~hgHP¨[.;½t¥v;9½…öŒ±i–¾Itúµ…DÑë8{>lÌËÓþÍiåêóðúóÐÏEQ2¸"BË9 k8VçV1jó>g°xý]›ÃQmS˜tˆ–‰ ™+*†N ¥`6˜*LÈç  ùp°»Ë~&F­ÖªÔ:•zÓ¨·kÝãæÑn¥à?™,œüGÊþÏû›Ó³Ë c­> ÃäÁñ–ï–ügalþJ“öäý>ÕûœÛS5;#öU¸²/ï]K}?ÿ«Ï! Íà«”œ·ñÝȈ'ø­aÏ,XOÇ!þBwöÒŠ}µ0ÅÊ1–ik§ÿ_¸Ÿò—ÔõÕÕùàžBL”[ÃøñlðÓíœ(Š_»üïÚÚër½£–kB‹Wq\‹Å·øµh±ì™.!«Þ­×ÚŒnÖ"è±IXõn£¡†$98‹tœ%¹ªÞm6 $W•†‚´Úª-^wª©æxìåÙœlB=ªø7 ýË®ÁƒSy•w3E4VÀ»}½ç·ñ”®‹¡.Föxzv›Ö©ÿjñaæ©GÇÛP[o A ÎÇ1ÆŒg—þü'@* ${¯9Ó%#ržê½zOE³ŽöeÅí×Mªíó­TöÉjhÉå@’†¶ plv[·Ñ?ÿ'¤R–ë JõÿÔTü¿Æ¿ÔêíV£¾õÿlý?›æÿ¹f….Õ´Q6Ýd.Ö|lèóOÿñ?ýê?þçT˜¾>ˆB… ® _TèMúœIpÑõZR|_Ññ5£kú€‚,ÊéJ›œuü@Êðþèêfˆs{±.Ñê Ú÷(Zž°±ÑÔ2Ýc¸»-¤:•˜1c¨Ïª*k$å ? оsM×&e9â¦N±ª_·šGÝZ‹_e«@O3ŠV D¾¬jÌ-kìíîkõˆ°¹£:>ø$£™~©·}‚팦6Æ1—Š` ÓÍqù¤[QŠø|t{X Ÿ‹J.7¿’6ÀÏC†¹­wçOáÿ‘ùÚ¨TP²‘v_–(ÍÿÓh5ù?fm‹ÿ¶õÿl^ý'îõ®\ö/•7W•ÛëÁÉŸ.!H •E ¾ ÙcšÀöše bg{MQû6%S(bZJ)ÍJ¿*Tô Tf‰¨h (µèÆGV’Wxº&óëãÈqA]8ó1Ýœ]~safÅ@¡UfYH? (°GF‰ÙHµ‘µ\°q;ñPÒÑÌφ²æ® EK-WJÂ)9­ Xª#ñ½\ZS#3œâVÜ¡ñøàx´lW#à—E€ä;;T.ø´ä7ʇÁ‹z97fÍ ÍUµ ü¹P«‘£Ö\Mbà–{hØU«j˜”<¢lë*‚.€mY L]\TKÎðª5ÚÒ½“áE¦¯{.`Ä–6–äO5cÊ.7¾š¦ú0s^„4dVN|7H¶åGg5£ ŽAŽsœ uô¨`xE)+e!M\$`w™}9r D±6OΉ3’#h1ö,,r… _¸g̉˜Cra ÓNü>cžt|æÑ|\‰%Ò&·5(ÙKJ@[:Q½bñ—À¦ÔGV]' ÖR·S«åJA‹9Œ7û{H$¨ñsëÑòìüÆ? Æ1™Eì}úŽ?ûŽÙÝÖð ib"Ðö_þuºüŽTáÊÅ/ðßcú¯ O5þ³ÕkÕOONÿ ŒÉ#±%ÑœÄÌiù,…¥_—c€a¾-K6ÿN>fHb[f„›V8r}u;üáf€lñ ð¦qÚÈÍ›ñ‰kog‹™7©â %”#zÔ"飿+Çi Žê'mΆ@ÃÁ®×çs ƒ„aoü:UÁWß¾]›˜õ“¤@´µS°(ƒ†æ"9Qõ£f½^K.L•§Ÿ )PÐe£ÑÎŒŸÈ ñÉlä‚J?¨¶ÙeÇñg‹ˆ·‘G¥vf†ÑCñeø-~G2Ùsê’¨ÒÁgxy„“Û…§ªëdx[:üu0Ãkç%R»JÌ£R²wv 'î[º-µ›–¸Sì‡þx é™`è6Ò‡”Éβ)©C-/¹eF×tê¨|Êé͉š‘uœ8ÑÜ/Ã#Ø%µUqt”è©}0× ´O™ÆŒŠ0mÕ3f0ÃhÊS€¬ uÅ?\½Ûì´zµÒàë4 ¸g*»“ ©Uº;¸uÔQ¹õremúú.ò‚x?u<ºáû‰>!Cûè/ô—_〙À5Šü$-ZWìN—ùžh§ØgkÆC­iúôw'y+¬”í•è¶ZÍNJášIî" ‡±U„ò ÷¬íÚ] LLðÖ¼‘³à¾yqhànô˜¤ÓŽ!ž$c¤¥_ â)²úκ7çeÄOõb@¬óA!¯Ù =kжä_ßþf“;ƒêÐÀï¶5ÓuØ ÙQ^ªm*ßñý ñ+PJ–DépÇžqL.Þ£ùµ²0m×3Þìïÿzgº¿õûûoÆh”{¢¥Üdïï×E»ûBœf£º(—Ê*à3Þ;R±•’¥NÔé¯h-Çœ‚èém€B"üO<ÐT¤éù3…ÅPäk¨MLá½é®"|rîklÊtumL,¸4ÖëíEBã(4’KJÍ£1Ï› ¢š 1Lù2©£É¨CW¬ Ò¶Ej‰à.êïr¤’UYÛ jŽïE6ˆ^Z¢-½Ûn·z½Üpb·diöB–ì õ‡Tëµ?ƒÅ1³Æ<ßU£/Û}4]ò(§’Ç”%‘<ߘÄÉöpqY¬gm…Á^¸úʼ2*Á´ôZ/_¹(´Îµa†ý›¡zKŒ¯ ³aòáŒÅÞqßgÙ-yúÊy5Žë?ØLJÌñXkCˆŠÊƒã| †œžjt‰;ZåÓÕÕ_ciLì `M!s…èáé¢&ýÏë”iÓ›(@¿ñËö§³á§L«6ØLù…ŒêÝN·Ýì|ûàoɆ•¢î›Ð–àÂÉnwÉåÅaKzÜ7Aá´õàüsølAâ#ú^Èç÷ÿ´5ÿåÿtêÛú?[ÿÏÆùÎ.φgýó³ÿí` WöŸ+(3n¼‹(SQ¡×q %LóšN¢¾mJæOc·oQ}=5æà)Ñ›Gy—$öEËk‘sÏQB¨Ö;j6z¥9â¸ç{’¢,R}E®å­¦ËòËÕŽêZúË;„²ä™„@ÍÐÈæs:˜m¢ùf˜‘GÍù2w•"ã xÚiÈÏ!­>2~T÷OerƒÐ#\?ySa‹ ĦM¶ÏôR=6³NÛÊ60s‰QÏKcbÚSï ”QCÄöüh{¥çÛÀ ívZ©ž-ŽÄ²iHhåÝ-–BE&c².N]8£žÈ|L!ÀrÕ xÆC³2ú)báóÞ*¯èKÂóýcðš`¹íœ ù´e®eŸT}*ñ¢·²Õ!¾Î#%Op<êXô, RŠÉ0|[æ2ì+ôw³ì#¾ÅüýJ‰!ê9w–¢Œ]ÕqÉ˱“1ˆð(ÅH8ZŒH/ŽèkZ¬_u|bp¡4¨¨­BãÌôb Þé¡Ûª½›£w}ƒÜ’á˜6ç¹FžÈ4’“'|@#pü”¯…뀞U׫ƒW»£N7gÒd鮼åĈ‘†”!–ÿ®Áèãó`£GOœÙÂÆhã¼ñá´oìÿåø‡ÞQ× =üqT«³ƒc#êÍ¡³¨œ“óé£ãÎÔg¤5à ÷ÕIdin§Œ"9µ¦¬åÊÔŽU¹Ø‚‰ÕáN©RÆ"ž*KVó)"÷ÙËÌ ÈO$Ìžu¦_ÑÛù$@é`™Ó©b Ö¾j1êIìŠlAæÉÓ6 y;P‡a`ja¯Wï«¢ÊýAI°© oö\wQ_à›sk 2ï }M(®è;4¬å¨zÀäp@ê00U.—-¶¥t›·Ø¹üZ¬çW±4'eˆÙêÚE’jm½e„C¸´’üúW„O¡ §’ÊÔ[ò©ÖëöZ9òä!…èÎó‘³Âk*V’\¹âÈè~þr=ÔwÓÌ|âgkÒÂçW΃o½’SõZ«Õ{iohü T<ò¯³§ú}6©ôQâúÊ_ *jÉÈ<|ì>ê$&P·ÊvŠÁô¶jjT¢æÛ\4¼Lv£MÉdÊ`IÊåÿÒ,Šà“&Êÿ÷ÿ¨ñ{¥g%û5Ø”üŸV§ÓÙú¶þŸÍóÿÜn†Vµöö[ðúLƳ@ÅaÐ- ‹ËæÜ^¬x1Žss~¿2ï-cÿãéÅùARZ9z€c¥^å÷•……O„öO>Á¹Õ|+ÿþyps6¸Mð­c,œ§Š ÙÒçëS,9ǹþª~¡Àô¯›2ÇÜ>¡àz µ‚Év™AEz ¼x:oôvU÷£­X½Ô³°‰ g8:ÑÌ7²ì¼PP~”{ j”6Œðæ+6ÖNFêõåMI„\XwBÞ1,Ë[zá¹ ­,ƒ¡—Ô½öÂDo3.Ÿ3ã²Ñj׺j$w„_ZRÌ̹bÉx¶0Ý3©ªù«³Ô2`Ïs `?E&˜â™—³Z ºží…h§ð¿‰ý•@I‰c£}†h.¯˜rÄ¡e–‰ÅÇ*°9qa÷/|rTX’ÍšRÒðÞÉÏNÊ&‚³f™‚èSç0Û»QjSÖŽÃ r8ƒ`Q ò¬Ð3¾ˆö8…ØaÂvú”¹}ÙÅHÏaˆµ¥ÈÄž, xöÁ¯³h×ÖÀu„„]︈—e™WÅZ&Šï²`/.ãx¥¯•ð,T¡Ñê6V.P@g?!üfüŠùÖâwkfÚÓß|=–ã l«ódY¿ù_<’Jòë÷ìK{ü›Q¯k/&@1D*ÈNŒÀZSÎÍ7û¬CãÞuV øIƒùݯq(ì7H¸!ýô?½ëÉFçüܼ·\{|îœÏæ›ýzݨ{¿¬\{ÏØûÁ¼7]{¿Ý³ßþ_Ïùj[K´Óï%õ D`B¼Þ”ìïgÒÁAiè°t[zNv:„q¡!#¡¸1@y“ûcãoZÝv·ž!.Ñt݈•V·[ËŽÐ+ÉéçGÀ_t@\Ûžj ¢¥{X$¸À\Ú¼| º´¸r¡€‡^KẫD\ aA‡ tª†¥—€'ÐhõjM¥ùe"hr8â¢Pô& EÆL­8Nçƒ 4èMh• ’g˜2gF„éÑ@%„Ök>ÂE¼ÑK“Ú-y¢­Ò½0qiôÇætô¦¿XHh<ÁB’qÐù@d¸@yk,8"46‘¾F…øjÍÇŽ[…¼hÑÍ«¼ Qä_.ªÑ³¶´î-WϺ—͉­î{6)KWo%SôQiCå⻌aRSå ñ™BÞ‚çPž‘×òzìB+'^騥JˆˆW —Ü&j”( ÚÑ7 'œ\5)ªÚn_i0Ä)1b*§y¿pÀT9ˆøU#×1Äû°½ ‡ÌÝ“ Ÿc´Î,“´hsØB9¹9/„Êa/™—Ä;4f+oÉ#Œ\Þ&ŽflXS/K !“ã2D|€”’aÝVú~̈ºÐHi‡:¢†À›0êïžrR’¸‡rY®Šð©ÚÅ® íž'ó€¢0aô‚8øåÞtÇ„ì ƒilXÿDFU¼"Ø{>qÜ™,¶LáþÔe0GV’S'¯{ò|;ôÛ°%ÿP¸(,fgW€êsaå£ÁƒxEš¾ú™¬ö ”Ü"öaßÜUâ½PŠÕÄÛû¦ÿiý ”`ˆ£v»SϽ²¸FJ§¹ïZ—*g—ÃÖ¡ÿëíШ•ç?jwk*f|¢#¼ˆ‹9Ö·}Ôî5ÔâëI¾í|¹|øQû¨ÛÍï/¯hŸïQ§vÔxqÔÝ,•h;Œ÷¸)àö-hÇÌFkîÁGV»SûöÁÙŒ¨Å}Àãò|Àų̀¹<ÁºÑ}œÀQK~ë ÞLÿ/œø›À²[˯›æÿmÁï:þw«ÑÙÖÝú7Îÿ{r3ÀÈ ¸ù{KnZõ ]g¡"ßÖtsuÍøþŠþßÀô¯éý ¨›è÷ ÎFÞ^•‰R#UO =½j_äç=¡~^Ò¡ÛƒY‰ÕbUeóãΉÙ½±ª‘6¿ó7Ò™›ü Y©\Óž/ó :(v¼WEjè5õŽ/ç¯ Nm~Wíëø<ÿÙÝ„1{(+A‰œŽÙ[y|Ì~¶ûäÅ¡âvz–A€Ê5µÌ93þ …°þÆb˜6†2ÜcGíZWƒKŽðޱcÊ“± #–Y’G$juKZõΊÝì<ÍD`úi“ÅÊ¥>³Ó*fŸù®+¾vÃhfÉ.ø¹'Òô…1è2d9Þäð,=ƒ‡Vv‚,? ¹¿Bv}G8¡®ZfMÌp$džq©º«1`ö5ÏÄd~(Í…júù¯þLû­@C”=Ãã?@¨¿;~²AK½x†Åz‡© P1ÛÚ/КºA1Wêl>wN?ˆ¥ SJ{fÌ×zƒÄÁP{+¥Tw½Ûª«§~GŠª»±Óy…µ±Ñ³ÂƒÂ)–û¿>X¨«ÿfL¦Ž¹Œz€eCîó5ÐhD=„µq+üfÀmþ¯¹jùm–M#L©ŒÒ SoìFįë-"*ŽåŽ8^ÍíßAâ+;â .ó“×çô‡I¥SÂßç¤ò ®çÕíÿfïóåÙ¿ûÐî!´×ڽ뛳‹þÍ/Æ_¿Ðç{™É.­²x½ÛÑóï’\fýð*¯P–Ó hï5U¤› vºÕë½Z½Ñ+žx¨ûœët—9£~þiªÌxMfdjæ«N¼OˆkqàÉJ‹,áÀ6I)å­ë°¢Ôå—qMf°cŦ€ÊW‹ú"éå($uœâyd/èZozï,EQæ„Ä 7ñ 5‘ë½^§ÛHsz⡈–¡#Ö„!báLiIP®¶9 CÔ¢îjcãB@ ê—5[<˜dŠß“}Y¿d±ýný±´æ)QÈžr‡‰Òd"Õgà ԉ¥}gOíå“ñ¡dV7Ù#fØÝ_tÓn>”þÌé ðNûbøOî“&ÿo°Ä¿¼¨ÿ·ÕitƒþßzkëÿÝú7Ïÿ›R|w£ÂEÞÖÿñJ£MC5¤GÓ•.­ùu#kEke¢_ɧ›^Oy-ˆÿÓrºyé©âî[½`P1ç­ âÀÊX0<Ök+†žêÚ÷R=WÎ ¦ž§LÌC]WübFJéôt×É3ÑŽoê$@S¿Æ¬Ïw¼Ji¹z6š§Ü‰9²Èr, wy>&”t…É'Y¹{BSµFkº00VPEwöS¸æªä|—OÛžò ¡©ùŠ7ãéÝê\;£=ä—ð£iŸ]\ÖzºC=Êë)üe¹ˆ…È` ™ñ.ÐÌbå.Ú —ÿåYnEd !Îl¹³&Ù£»¦2Ž3»bOøÕ—õ-/3U9ûȯÎo3úTsyqœÅ .Iƒva“väí_+ù%÷@ì}Ÿ¿¤\ô«…88¾«,gZ™™T&®e IB÷UÎÌÓ•ë««óÊEÿçÊÇ›Á Â‰;»ºÌÁ×OÎ#B!>Ø¡tcxÎjÊkçú"É2€bDãûbY‹‚ã 5å˜eöÞæÚÂ-ô®©+ª®]¥JqÀ÷1U×£Y”h_yV!‚Ó*/¾O*¹˜™ôsQmDÒ£>Œµ¤§VV¦ËHØHD)kV«yS]‡(…§žN ÂËÛÌIJ¤Q¿-/kýÕ .a¯àâóÊ{༩\ö/²:?XË@Q“…ëÓWÁƒ™Òb£(wuQ¹½œá®$–è玱`±fª%ßÃÌÕõ#Rué@]s&ñ¡í½Ü3!ÿàL$PêH‚º³ÛÜ{oŠÑ A>פ‰NCk"NÀÁi> =’Z¬Å(Z‹‰­¨Š¦Z¡ÏÌD¢ÿôÜâ:ÅYöà:«ûÃ^¾ñ”àŽêšgÅÿ¿½«ÿm7Ãûµù+ˆ°K‹8mÉ_Ãs÷.[SŽÛ^QÅQ¡¶eHvzÙnûÛÇ—¤(Rß’åXYIpª#‰ÔË—_ïÇóÄ®oÁBÑ(§«üýž¢@Þko˜ˆU .Í='4ðÑoæmïw„~c­¿YxìGÅÇHÙœŸ^^—6®v½ñWëépú!ÿBqåBh‹˜lÞ8›5âË’p )·¾Q§KHY¸qa ž…£’Kn½È!/ܨóÑõt2þ\¼Uì}Þ¶íZ¹ÎMDTW“ñi I­-ˆÞ"AUpJÓ„<©—j!ñ{†7*ÄaZ|BvzÁñ«ßìËø¡Åò Àß—}9ÝYXÜŸ.¦¿—öèwkFÒ×å(oÀ­Er¡N#™ñ7ïð €ì¡’µ–~Püˆ~Xè\QÉ /„óùòwG¢Hk„ªœi®LõÙEïÒ+5WGævé:8¹jÖËÝHü¶õMÜxNÿ_«etÃø¿z§¥üÊÿW7ÿßÇ‹Ñ'Åô'€’ ÌqAf ¤4ªo¶wŽû8º&X{t †{yK`XXµÌôŒvJ¹ž’$¹«OZn*Ìö”j£c~\€íw‘A{vëÛì´:íNu°¾’ÜJæ€Ö Ê×µ<¼•®G·Ùikrù ÊË„>VP´*Ç4ùûüQS2r§ÀŸ]½§e¦MÉK¢âdÐäëhfDup›%û¸8”bI MŽbh®‘³œ?ÑyŒ$ PÒ¬Gëwsa3œË²­Lǹô8cšQ¬&ÜÜŸ=2htYpά‰‡âS‚ƒƒ6ZV¸‹]C—²±r¤ Jë<ú2·–öÒk6Çä‹á~g‹]£ÓÓ{/b±kôÚ=}‹]£oˆ»šçÉcbç²EŽ;«Áž;9¼'x¸ ›d(D+&¡û©ÕòËæO¥ŸlS³§È£;@kìvô–ˆƒŸ¸Täà@fô%  ZCFfŸÈk‘¢“ïL^È&¨q l⢹GACî1ÿgîr¢ù´‡üŸn§e„íÿ-½©ìÿÊþ_7ûÿÕäâý”0­~~ÖÿE†õÿÒ\Ú« KØÍÉ—©öÿ`ªào&BI±úSwù™ëÑ;ˆߟ¥_îÏ-íü‚P¶4ñ§õÊ6F~±ª0ï âã»Ua-©Ð´/Ôx1|,,(0—D“ªµ’y;aëëtû-‘JaK³¾ ±|F}rk#°—1ð“Ï+»HCéŠ<áAc‘û×x¿»ØµÓ¡zÚ¾NO—¼<ÏçnHS„£ðp)äîÜÏÏ#U°Éü`²ìò¯D¯—<P1’UYli‰ùµQ t)ÔÖ+=F.5oâÃ)~ 5­}.<ÜV¸Vûfþ„ð‘tý$#4Ñ1ðÂ}ò „aÈ”^L²<~˜z’Dëß&Uåg0ÙžÐìDB£ã‰±Ìˆ7 ”O~ö®¨Q{+ÇÈ,“ ³(ìd 7ë0àc…¾¥˜I°Äåõ™e`à¥|quÜzá9¼Èç.7‹¼SÝýçV×ÁÑ5(™ ³Y¯6kDŸÞÑÇTä¡ÓÚº€ã¡KÙ[AkÙÎ* ëºy"¿Ó9ÈË.\Ǿ‡‹A–ú1Åd¢bd™aÐJß½ÔÒ)‘‘î]²µÃ"‡A'GËbv@´]$"@†±…™<]Ë$·¦ÀÌÿMôïÞ6¨2¿Þ6£QËà rèÑýÐqœƒ5kfðýŠæ|î|c|lbz å ¯4â((ìªï(%Ë‘€ÁJÔ›~o:àldô›ÅˆÝ‚&0œWòÀ1îx+KOay™Ó‡ ûPlâ°4­ƒñ©FÆ!gk‘¨9 {i/6 HÒD%8ñ8 ,BP’‚«§€ÕË©þèmb_RŽÇ["I2¤Àù¼‘ÆË(ÇK>.pizˆ¹N›rþ; G “x¯© ¼„8þ-ƒ×ȪJº‘ŒóJœÞMCW™NoጾÐþïl×[7(Äíü(¿¶¦=ÿ-Sv@°+ºÂ¤Û &úòç9>9ò:ß"÷ØòãÑáÅù!:|;žŒ Ù_^˜°«ÑåðâÀ¾^œ#ÿÄþŒùk¨þƒ&Bçæ­½°]ô¼ýð+qûÿÍsm|žqÜ{rg ¡¿;žuGàœ×æœÜê‘ ùÖƒ6¯r–4ÈÌuÖÞ×'<'Ð éÖ¡÷öW{mâ;ÿán¼Ùƒõˆ¾² ñVÈVî,fUBTnǤ§þIBB Ÿèé%Š$âwåeO‘ο"ã0$ñòGÈceŽ * \9”S×ú×Ã8ºaW²:}Þ¸6ßòÙy$9[äJ¾»‹%ÉÆ:î¡3ü¥KkùÕA3ÿJk¡Kû눗Ÿ÷Æ$}pï_Iw÷qcϤ|¶ðJJ´à‰^…Ô ©ª…ÐÕfM• ­à*¤]¼ƒ«*iBpÇ^‚Jš½¾ˆ÷šTR¦â\Á"-­eç㼸cAq•&­Ã–—¶¹eÞ’% H /Á§ço~å5€ü ~aû†`}@aÞ7Ö™_"~¥Õjêúsǯ$z*’¢8D;l¡h§S×ù¸‘^ÿX‰æ*®ÊËáUFüÁ2ñ1À†nVQ|áñ8מ*QYŠÏ(©&úÈ.pÚà¬~ùt©©^ªòa/‹êÂ^²¼T…^ÈH¨A¬ UÛúE¹øXÖx'æ¸@Ò@„*ã@²ò?;-]ˆÿhýIk]MῪøÚÅàXc:º¼O†“ÏÑd2ž¼„8`6 `xòkÎü¿¢ë'O)q ¤¡ ‰ãßÀTZlÌ?öÂr6ë¤N/.GãSáUû‰‰×€-#GRÅZ0–$¾O·Š‰ï*Hb¤Éw]1‹R…%15“À’Ì´FO?àñ›à³¶Èil«‡Ïé_­å-7 ä?¥àM…‚NÎàw„û}fÝ’ä¨wô¤lGõ®ÞÒÚÂ)7ö‘Œ$ ñ•rR u;*'à€FÏ–)³ƒßãEÏ©ðÕi H¨7Gu1µ$ÝMÄ–IúÍ|"Î| çk-×v6^Ü{eÃïÊçlüþüQÓe®-]Nù¿y-§3:$y<õ®ÑÔD[LŒÇS ~± 7 »B¼ µµ g6Û¸$ îäÅÌÍÌ%P3ÁøÑùZ¹̪2 Œ¹Ùô!ÔfæÆ³Ž%þ‹šË‘M¼ˆÞB;˜Uˆ`4ûl„x)[Þ"c{ÞÆ (hnžø­§—Èâ;lðvrÇ€Ó¤h&º>€$H:É@|¥Ð;žuÏX·~x“ô'øÑ†Fø‡?Zž¨¬{ y¸AhJÜý~š_,¤Eyê²OŽ©4ÁáO#ˆ§¹Lý‚¾F›0}°b Í5úf‚ŸóÑ™?RF·õƒd/g„ìó$É<ñœ½Deeßî«—‚úwÙKK<Š\{ñ <”î($öÎ&Xð~†ÍFvtè'¥'‘O!äY p>ÌÉù!Léhæcø[Zš˜9+ÝêNfNÀ–aÜŠ¶.béÄ¡ÔÁ‰˜ÜCÈõ ËK̾^.ÓSz“ˆB„c ¸#!íf˜ÚïñÌåâíâÉ b¬¥ÔÃ7~ƒuŒL?pï‚Ò |=þ ßq‚ð„@Ï3R >—±¾ ë‚ð”›-¼\Ñ„–€‡ÉÃ+13¦&ͤN¡B®¡Ð§3sC!!ðÿíÁ !pî½½lÀä:@Ú‰a/ÿ‚ØodBó„AßñN²wáo“A´?ÍJYàíÏÝSAÉm$\# Ùò ”wj/ѯÐwTöÖ^hœ{’vŒÌN¶ÛìÂó›v„w1wèMìó OøT$ÑÒð_úkðŠ$e?·æÿ~“½Þ-Ú3}=#ö™Îœ\I™Yºã à:ìwéBh B°‰V亥µ)‹ODÒ J)’s¾?cù¼\8wÞYE–â©úÈÎU³Õ§Šº\VLÓètšýÖ6)wŽ#ð¢qÓ¿ Aä{ë0ÿ¡Ô7¾°C*ã\ÁÝí·´œðCªÖ¸£áÓVÃ3n˜U®‰¹R|[p[›]Y±rp VA*:™œFæÂÏ+fðé‚LP¢bf…‚TZ0jÀûH@\~z¡Pv!`­L6±¾¬VKÿŽHtvÈg“Zo”R:‘4?gM…Ξ¦ÑÃÿéyB—Ëë:s®ó*þÚ0òaÊyp§4=uŽtÎa@©KOJ1Þú`R¨»(˜(”ÇèÿÞÿÓ€£\ƒŒü ]AþŸfÛ0"ø/MCù”ÿ§¶þŸÆÛÉø²qönx}ý\AŽñ©qoìÚ4ô3ÙÉ0gx„ð‘ŽÎÁʦFo©Àˆ¬²üBäVÜV•<>ª…oHîûíC¿#²+è)*Ú“[û‹¤^ªÔc$ˆ6ê<§]ø‘„º©KÉšã>¢ŠD kaÈùGî]ø–´^SoKV¡Š|K‚äò¹™l”õ8ÕÃk„EÚíé{ñ¥È0Î9ñ*ÞsTV&¨4‰Qæ#¾Ã¯ìŒj„Ï#C~~—Ó3Rç&ÏmTåÜ]¯ªwìô›†Öƒœcü:ká]‘CY§)‚nÇú3^Ñ%5ÐI²ªú×|e­ÄU[ÔÕEKoœ§âÕ§‹À# ´"ÿFGm>ÞÛ-ÌöUàÆöºíüxᯆHãÉ‘\Œû†½ä …WáÏ_„Ï‚Bþðƒùh¼ò6wwö v™h9FÄoAbáo…½’W¡¾g·;=ˆ ªÜ,ƒ}Ø$g»—·­™füèv¬ÐxþÓV"è¸ôŠtãzÑœ”ˆ©÷eJZ…Œœ]g{t¾“ZY“´pB¯Ê&yL+d•–U«.†ifP¦é­ì¿Zà)  `ÕYYñÿš„ÿ ñÿ†¦)û¯²ÿÖÎþ;úutö/úgãËËáûóïšžîù®5ÃÛ¯È>äÝ‹i2:OÎÓ¬¾©Dòû±óFûxkoTP5%ˆÉA*°ë†DÉw…¡õ¦Bkn¨FbÈÑÚå4GÍ¥&?ðré°Ø_nØý²=CU2Ç=MëWÇ’c>Û®ÌéýrM»X˜m)¸ùùL»É"|y¬ëxm_[ 66 ˆ%”ñ­ ƒBñ©Wϧ^ £³Ñ×z½t[0›=ÁÆC&Œ<”ĉªæiæ°µHAO³ 3Lvpo ˆ&n…+GL„&e¿:]jªÛ@\‰8h‰Yâ!.•òGªÑ×C¹A]Bó>bö*ßpù°óÎ=:¸M²—=jk¯ÉïôŸ]íõëÃ0~ËÁî*€÷Ó:"¿|z°ñ+éf„ ßúVɀޕlvWãëéÏ“¾—Yý[ïi§­ÓÎùˆ½;R¢@‚2–ûžAÜ«G$dûýÅ»"Ÿ„Ì}ý x3Þø28}äD­Ëq/„iâ÷$'a×^ló´ú2<O¦¿áûÈ¤Žµ}ê¬ïpÛæ¹ÞnÝlî±R¨_bÕƒ5_åêÝ£Hþ8º:Ãÿ{;¼ž6.GÓ_Æç(à mߎ¦(¦Ã_¿þ#æS‰¾l–ÀaÜ0ÝûU(t—ùhÚsP‘·ÆˆçÚÙ¸3¬G”næÇ( p¥æƒÑ¯Wøû¯/ÆïÑÉÉIÌ{µß–6xÁCRõèà¯*µÏk^;Ãô ïKE Yô÷dÚÓ`Uxàgl°-wþ$NÇàÈÀ Êɶ$²F¿'MÎ1Þ#b°®3Öè÷;bjMº(*6Y],χ«Ž,6 ŠÝŠ!¶ÀZŠÓ§jÜ®3ÆVæDáè1ï\ò¢„u±N^“<ÆZðŽf? zKDX ¼%D…•›DUTQEUTQEUTQEUTQEUTQEUTQEUTQEUTQEUTQEUTQEU^tùõ¿Ècl-sql-6.4.1/doc/entities.inc0000644000175000017500000000324110667176647015037 0ustar kevinkevinASDF"> CLOCC"> CCLAN"> UFFI"> FFI"> CLSQL"> MaiSQL"> SQL"> UncommonSQL"> CommonSQL"> MySQL"> PostgreSQL"> SQLite version 2"> SQLite version 3"> Oracle"> ODBC"> AODBC"> CMUCL"> SCL"> MD5"> SBCL"> OpenMCL"> Lispworks"> AllegroCL"> ANSI Common Lisp"> T"> NIL"> NULL"> C"> UNIX"> Microsoft Windows"> cl-sql-6.4.1/doc/csql.xml0000644000175000017500000005750111345753563014204 0ustar kevinkevin %myents; ]> &commonsql; Tutorial Based on the &usql; Tutorial Introduction The goal of this tutorial is to guide a new developer thru the process of creating a set of &clsql; classes providing a Object-Oriented interface to persistent data stored in an &sql; database. We will assume that the reader is familiar with how &sql; works, how relations (tables) should be structured, and has created at least one &sql; application previously. We will also assume a minor level of experience with Common Lisp. &clsql; provides two different interfaces to &sql; databases, a Functional interface, and an Object-Oriented interface. The Functional interface consists of a special syntax for embedded &sql; expressions in Lisp, and provides lisp functions for &sql; operations like SELECT and UPDATE. The object-oriented interface provides a way for mapping Common Lisp Objects System (CLOS) objects into databases and includes functions for inserting new objects, querying objects, and removing objects. Most applications will use a combination of the two. &clsql; is based on the CommonSQL package from LispWorks Ltd, so the documentation that LispWorks makes available online is useful for &clsql; as well. It is suggested that developers new to &clsql; read their documentation as well, as any differences between CommonSQL and &clsql; are minor. LispWorks makes the following documents available: &lw; User Guide - The &commonsql; Package &lw; Reference Manual - The SQL Package &commonsql; Tutorial by Nick Levine Data Modeling with &clsql; Before we can create, query and manipulate &clsql; objects, we need to define our data model as noted by Philip Greenspun Philip Greenspun's "SQL For Web Nerds" - Data Modeling When data modeling, you are telling the relational database management system (RDBMS) the following: What elements of the data you will store. How large each element can be. What kind of information each element can contain. What elements may be left blank. Which elements are constrained to a fixed range. Whether and how various tables are to be linked. With &sql; database one would do this by defining a set of relations, or tables, followed by a set of queries for joining the tables together in order to construct complex records. However, with &clsql; we do this by defining a set of CLOS classes, specifying how they will be turned into tables, and how they can be joined to one another via relations between their attributes. The &sql; tables, as well as the queries for joining them together are created for us automatically, saving us from dealing with some of the tedium of &sql;. Let us start with a simple example of two &sql; tables, and the relations between them. CREATE TABLE EMPLOYEE ( emplid NOT NULL number(38), first_name NOT NULL varchar2(30), last_name NOT NULL varchar2(30), email varchar2(100), companyid NOT NULL number(38), managerid number(38)) CREATE TABLE COMPANY ( companyid NOT NULL number(38), name NOT NULL varchar2(100), presidentid NOT NULL number(38)) This is of course the canonical &sql; tutorial example, "The Org Chart". In &clsql;, we would have two "view classes" (a fancy word for a class mapped into a database). They would be defined as follows: (clsql:def-view-class employee () ((emplid :db-kind :key :db-constraints :not-null :type integer :initarg :emplid) (first-name :accessor first-name :type (string 30) :initarg :first-name) (last-name :accessor last-name :type (string 30) :initarg :last-name) (email :accessor employee-email :type (string 100) :nulls-ok t :initarg :email) (companyid :type integer :initarg :companyid) (managerid :type integer :nulls-ok t :initarg :managerid)) (:base-table employee)) (clsql:def-view-class company () ((companyid :db-kind :key :db-constraints :not-null :type integer :initarg :companyid) (name :type (string 100) :initarg :name) (presidentid :type integer :initarg :presidentid)) (:base-table company)) The DEF-VIEW-CLASS macro is just like the normal CLOS DEFCLASS macro, except that it handles several slot options that DEFCLASS doesn't. These slot options have to do with the mapping of the slot into the database. We only use a few of the slot options in the above example, but there are several others. :column - The name of the &sql; column this slot is stored in. Defaults to the slot name. If the slot name is not a valid &sql; identifier, it is escaped, so foo-bar becomes foo_bar. :db-kind - The kind of database mapping which is performed for this slot. :base indicates the slot maps to an ordinary column of the database view. :key indicates that this slot corresponds to part of the unique keys for this view, :join indicates a join slot representing a relation to another view and :virtual indicates that this slot is an ordinary CLOS slot. Defaults to :base. :db-reader - If a string, then when reading values from the database, the string will be used for a format string, with the only value being the value from the database. The resulting string will be used as the slot value. If a function then it will take one argument, the value from the database, and return the value that should be put into the slot. :db-writer - If a string, then when reading values from the slot for the database, the string will be used for a format string, with the only value being the value of the slot. The resulting string will be used as the column value in the database. If a function then it will take one argument, the value of the slot, and return the value that should be put into the database. :db-type - A string which will be used as the type specifier for this slots column definition in the database. :void-value - The Lisp value to return if the field is &null;. The default is &nil;. :db-info - A join specification. In our example each table as a primary key attribute, which is required to be unique. We indicate that a slot is part of the primary key (&clsql; supports multi-field primary keys) by specifying the :db-kind key slot option. The &sql; type of a slot when it is mapped into the database is determined by the :type slot option. The argument for the :type option is a Common Lisp datatype. The &clsql; framework will determine the appropriate mapping depending on the database system the table is being created in. If we really wanted to determine what &sql; type was used for a slot, we could specify a :db-type option like "NUMBER(38)" and we would be guaranteed that the slot would be stored in the database as a NUMBER(38). This is not recomended because it could makes your view class unportable across database systems. DEF-VIEW-CLASS also supports some class options, like :base-table. The :base-table option specifies what the table name for the view class will be when it is mapped into the database. Another class option is :normalizedp, which signals &clsql; to use a normalized schema for the mapping from slots to &sql; columns. By default &clsql; includes all the slots of a parent class that map to &sql; columns into the child class. This option tells &clsql; to normalize the schema, so that a join is done on the primary keys of the concerned tables to get a complete column set for the classes. For more information, see def-view-class. Class Relations In an &sql; only application, the EMPLOYEE and COMPANY tables can be queried to determine things like, "Who is Vladimir's manager?", "What company does Josef work for?", and "What employees work for Widgets Inc.". This is done by joining tables with an &sql; query. Who works for Widgets Inc.? SELECT first_name, last_name FROM employee, company WHERE employee.companyid = company.companyid AND company.company_name = "Widgets Inc." Who is Vladimir's manager? SELECT managerid FROM employee WHERE employee.first_name = "Vladimir" AND employee.last_name = "Lenin" What company does Josef work for? SELECT company_name FROM company, employee WHERE employee.first_name = "Josef" AND employee.last-name = "Stalin" AND employee.companyid = company.companyid With &clsql; however we do not need to write out such queries because our view classes can maintain the relations between employees and companies, and employees to their managers for us. We can then access these relations like we would any other attribute of an employee or company object. In order to do this we define some join slots for our view classes. What company does an employee work for? If we add the following slot definition to the employee class we can then ask for it's COMPANY slot and get the appropriate result. ;; In the employee slot list (company :accessor employee-company :db-kind :join :db-info (:join-class company :home-key companyid :foreign-key companyid :set nil)) Who are the employees of a given company? And who is the president of it? We add the following slot definition to the company view class and we can then ask for it's EMPLOYEES slot and get the right result. ;; In the company slot list (employees :reader company-employees :db-kind :join :db-info (:join-class employee :home-key companyid :foreign-key companyid :set t)) (president :reader president :db-kind :join :db-info (:join-class employee :home-key presidentid :foreign-key emplid :set nil)) And lastly, to define the relation between an employee and their manager: ;; In the employee slot list (manager :accessor employee-manager :db-kind :join :db-info (:join-class employee :home-key managerid :foreign-key emplid :set nil)) &clsql; join slots can represent one-to-one, one-to-many, and many-to-many relations. Above we only have one-to-one and one-to-many relations, later we will explain how to model many-to-many relations. First, let's go over the slot definitions and the available options. In order for a slot to be a join, we must specify that it's :db-kind :join, as opposed to :base or :key. Once we do that, we still need to tell &clsql; how to create the join statements for the relation. This is what the :db-info option does. It is a list of keywords and values. The available keywords are: :join-class - The view class to which we want to join. It can be another view class, or the same view class as our object. :home-key - The slot(s) in the immediate object whose value will be compared to the foreign-key slot(s) in the join-class in order to join the two tables. It can be a single slot-name, or it can be a list of slot names. :foreign-key - The slot(s) in the join-class which will be compared to the value(s) of the home-key. :set - A boolean which if false, indicates that this is a one-to-one relation, only one object will be returned. If true, than this is a one-to-many relation, a list of objects will be returned when we ask for this slots value. There are other :join-info options available in &clsql;, but we will save those till we get to the many-to-many relation examples. Object Oriented Class Relations &clsql; provides an Object Oriented Data Definition Language, which provides a mapping from &sql; tables to CLOS objects. By default class inheritance is handled by including all the columns from parent classes into the child class. This means your database schema becomes very much denormalized. The class option :normalizedp can be used to disable the default behaviour and have &clsql; normalize the database schemas of inherited classes. See def-view-class for more information. Object Creation Now that we have our model laid out, we should create some object. Let us assume that we have a database connect set up already. We first need to create our tables in the database: Note: the file examples/clsql-tutorial.lisp contains view class definitions which you can load into your list at this point in order to play along at home. (clsql:create-view-from-class 'employee) (clsql:create-view-from-class 'company) Then we will create our objects. We create them just like you would any other CLOS object: (defvar company1 (make-instance 'company :companyid 1 :presidentid 1 :name "Widgets Inc.")) (defvar employee1 (make-instance 'employee :emplid 1 :first-name "Vladimir" :last-name "Lenin" :email "lenin@soviet.org" :companyid 1)) (defvar employee2 (make-instance 'employee :emplid 2 :first-name "Josef" :last-name "Stalin" :email "stalin@soviet.org" :companyid 1 :managerid 1)) In order to insert an objects into the database we use the UPDATE-RECORDS-FROM-INSTANCE function as follows: (clsql:update-records-from-instance employee1) (clsql:update-records-from-instance employee2) (clsql:update-records-from-instance company1) After you make any changes to an object, you have to specifically tell &clsql; to update the &sql; database. The UPDATE-RECORDS-FROM-INSTANCE method will write all of the changes you have made to the object into the database. Since &clsql; objects are just normal CLOS objects, we can manipulate their slots just like any other object. For instance, let's say that Lenin changes his email because he was getting too much spam from the German Socialists. ;; Print Lenin's current email address, change it and save it to the ;; database. Get a new object representing Lenin from the database ;; and print the email ;; This lets us use the functional &clsql; interface with [] syntax (clsql:locally-enable-sql-reader-syntax) (format t "The email address of ~A ~A is ~A" (first-name employee1) (last-name employee1) (employee-email employee1)) (setf (employee-email employee1) "lenin-nospam@soviets.org") ;; Update the database (clsql:update-records-from-instance employee1) (let ((new-lenin (car (clsql:select 'employee :where [= [slot-value 'employee 'emplid] 1])))) (format t "His new email is ~A" (employee-email new-lenin))) Everything except for the last LET expression is already familiar to us by now. To understand the call to CLSQL:SELECT we need to discuss the Functional &sql; interface and it's integration with the Object Oriented interface of &clsql;. Finding Objects Now that we have our objects in the database, how do we get them out when we need to work with them? &clsql; provides a functional interface to &sql;, which consists of a special Lisp reader macro and some functions. The special syntax allows us to embed &sql; in lisp expressions, and lisp expressions in &sql;, with ease. Once we have turned on the syntax with the expression: (clsql:locally-enable-sql-reader-syntax) We can start entering fragments of &sql; into our lisp reader. We will get back objects which represent the lisp expressions. These objects will later be compiled into &sql; expressions that are optimized for the database backed we are connected to. This means that we have a database independent &sql; syntax. Here are some examples: ;; an attribute or table name [foo] => #<CLSQL-SYS::SQL-IDENT-ATTRIBUTE FOO> ;; a attribute identifier with table qualifier [foo bar] => #<CLSQL-SYS::SQL-IDENT-ATTRIBUTE FOO.BAR> ;; a attribute identifier with table qualifier [= "Lenin" [first_name]] => #<CLSQL-SYS::SQL-RELATIONAL-EXP ('Lenin' = FIRST_NAME)> [< [emplid] 3] => #<CLSQL-SYS::SQL-RELATIONAL-EXP (EMPLID < 3)> [and [< [emplid] 2] [= [first_name] "Lenin"]] => #<CLSQL-SYS::SQL-RELATIONAL-EXP ((EMPLID < 2) AND (FIRST_NAME = 'Lenin'))> ;; If we want to reference a slot in an object we can us the ;; SLOT-VALUE sql extension [= [slot-value 'employee 'emplid] 1] => #<CLSQL-SYS::SQL-RELATIONAL-EXP (EMPLOYEE.EMPLID = 1)> [= [slot-value 'employee 'emplid] [slot-value 'company 'presidentid]] => #<CLSQL-SYS::SQL-RELATIONAL-EXP (EMPLOYEE.EMPLID = COMPANY.PRESIDENTID)> The SLOT-VALUE operator is important because it let's us query objects in a way that is robust to any changes in the object->table mapping, like column name changes, or table name changes. So when you are querying objects, be sure to use the SLOT-VALUE &sql; extension. Since we can now formulate &sql; relational expression which can be used as qualifiers, like we put after the WHERE keyword in &sql; statements, we can start querying our objects. &clsql; provides a function SELECT which can return use complete objects from the database which conform to a qualifier, can be sorted, and various other &sql; operations. The first argument to SELECT is a class name. it also has a set of keyword arguments which are covered in the documentation. For now we will concern ourselves only with the :where keyword. Select returns a list of objects, or nil if it can't find any. It's important to remember that it always returns a list, so even if you are expecting only one result, you should remember to extract it from the list you get from SELECT. ;; all employees (clsql:select 'employee) ;; all companies (clsql:select 'company) ;; employees named Lenin (clsql:select 'employee :where [= [slot-value 'employee 'last-name] "Lenin"]) (clsql:select 'company :where [= [slot-value 'company 'name] "Widgets Inc."]) ;; Employees of Widget's Inc. (clsql:select 'employee :where [and [= [slot-value 'employee 'companyid] [slot-value 'company 'companyid]] [= [slot-value 'company 'name] "Widgets Inc."]]) ;; Same thing, except that we are using the employee ;; relation in the company view class to do the join for us, ;; saving us the work of writing out the &sql;! (company-employees company1) ;; President of Widgets Inc. (president company1) ;; Manager of Josef Stalin (employee-manager employee2) Deleting Objects Now that we know how to create objects in our database, manipulate them and query them (including using our predefined relations to save us the trouble writing alot of &sql;) we should learn how to clean up after ourself. It's quite simple really. The function DELETE-INSTANCE-RECORDS will remove an object from the database. However, when we remove an object we are responsible for making sure that the database is left in a correct state. For example, if we remove a company record, we need to either remove all of it's employees or we need to move them to another company. Likewise if we remove an employee, we should make sure to update any other employees who had them as a manager. Conclusion There are many nooks and crannies to &clsql;, some of which are covered in the Xanalys documents we refered to earlier, some are not. The best documentation at this time is still the source code for &clsql; itself and the inline documentation for its various functions. cl-sql-6.4.1/doc/html_chunk.xsl0000644000175000017500000000034410667176647015405 0ustar kevinkevin cl-sql-6.4.1/doc/README0000644000175000017500000000057111345753563013373 0ustar kevinkevinBuilding the documentation: You will need the following packages: * xsltproc * docbook * docbook-xml * docbook-xsl * docbook-xsl-doc-html * fop These are the debian/ubuntu package names; on other systems there are probably similar. General Build: > make Check the validity of the source > make check Build just the html: > make html Build just the pdf: > make pdf cl-sql-6.4.1/doc/ref-transaction.xml0000644000175000017500000006710710667176647016354 0ustar kevinkevin %myents; ]> Transaction Handling This section describes the interface provided by &clsql; for handling database transactions. The interface allows for opening transaction blocks, committing or rolling back changes made and controlling autocommit behaviour. In contrast to &commonsql;, &clsql;, by default, starts in transaction AUTOCOMMIT mode (see set-autocommit). To begin a transaction in autocommit mode, start-transaction has to be called explicitly. START-TRANSACTION START-TRANSACTION Open a transaction block. Function Syntax start-transaction &key database => &nil; Arguments and Values database A database object. This will default to the value of *default-database*. Description Starts a transaction block on database which defaults to *default-database* and which continues until rollback or commit are called. Examples (in-transaction-p) => NIL (select [*] :from [foo] :field-names nil) => NIL (start-transaction) => NIL (in-transaction-p) => T (insert-records :into [foo] :av-pairs '(([bar] 1) ([baz] "one"))) => (select [*] :from [foo] :field-names nil) => ((1 "one")) (rollback) => NIL (in-transaction-p) => NIL (select [*] :from [foo] :field-names nil) => NIL Side Effects Autocommit mode is disabled and if database is currently within the scope of a transaction, all commit and rollback hooks are removed and the transaction level associated with database is modified. Affected by None. Exceptional Situations Signals an error of type sql-database-error if database is not a database object. See Also commit rollback in-transaction-p set-autocommit with-transaction Notes start-transaction is a &clsql; extension. COMMIT COMMIT Commit modifications made in the current transaction. Function Syntax commit &key database => &nil; Arguments and Values database A database object. This will default to the value of *default-database*. Description If database, which defaults to *default-database*, is currently within the scope of a transaction, commits changes made since the transaction began. Examples (in-transaction-p) => NIL (select [*] :from [foo] :field-names nil) => NIL (start-transaction) => NIL (in-transaction-p) => T (insert-records :into [foo] :av-pairs '(([bar] 1) ([baz] "one"))) => (select [*] :from [foo] :field-names nil) => ((1 "one")) (commit) => NIL (in-transaction-p) => NIL (select [*] :from [foo] :field-names nil) => ((1 "one")) Side Effects Changes made within the scope of the current transaction are committed in the underlying database and the transaction level of database is reset. Affected by The transaction level of database which indicates whether a transaction has been initiated by a call to start-transaction since the last call to rollback or commit. Exceptional Situations Signals an error of type sql-database-error if database is not a database object. A warning of type sql-warning is signalled if there is no transaction in progress. See Also start-transaction rollback in-transaction-p add-transaction-commit-hook set-autocommit with-transaction Notes None. ROLLBACK ROLLBACK Roll back modifications made in the current transaction. Function Syntax rollback &key database => &nil; Arguments and Values database A database object. This will default to the value of *default-database*. Description If database, which defaults to *default-database*, is currently within the scope of a transaction, rolls back changes made since the transaction began. Examples (in-transaction-p) => NIL (select [*] :from [foo] :field-names nil) => NIL (start-transaction) => NIL (in-transaction-p) => T (insert-records :into [foo] :av-pairs '(([bar] 1) ([baz] "one"))) => (select [*] :from [foo] :field-names nil) => ((1 "one")) (rollback) => NIL (in-transaction-p) => NIL (select [*] :from [foo] :field-names nil) => NIL Side Effects Changes made within the scope of the current transaction are reverted in the underlying database and the transaction level of database is reset. Affected by The transaction level of database which indicates whether a transaction has been initiated by a call to start-transaction since the last call to rollback or commit. Exceptional Situations Signals an error of type sql-database-error if database is not a database object. A warning of type sql-warning is signalled if there is no transaction in progress. See Also start-transaction commit in-transaction-p add-transaction-rollback-hook set-autocommit with-transaction Notes None. IN-TRANSACTION-P IN-TRANSACTION-P A predicate for testing whether a transaction is currently in progress. Function Syntax in-transaction-p &key database => result Arguments and Values database A database object. This will default to the value of *default-database*. result A Boolean. Description A predicate to test whether database, which defaults to *default-database*, is currently within the scope of a transaction. Examples (in-transaction-p) => NIL (start-transaction) => NIL (in-transaction-p) => T (commit) => NIL (in-transaction-p) => NIL Side Effects None. Affected by None. Exceptional Situations None. See Also start-transaction commit rollback set-autocommit Notes in-transaction-p is a &clsql; extension. ADD-TRANSACTION-COMMIT-HOOK ADD-TRANSACTION-COMMIT-HOOK Specify hooks to be run when committing changes. Function Syntax add-transaction-commit-hook commit-hook &key database => result Arguments and Values commit-hook A designator for a function with no required arguments. database A database object. This will default to the value of *default-database*. result The list of currently defined commit hooks for database. Description Adds commit-hook, which should a designator for a function with no required arguments, to the list of hooks run when commit is called on database which defaults to *default-database*. Examples (start-transaction) => NIL (add-transaction-commit-hook #'(lambda () (print "Successfully committed."))) => (#<Interpreted Function (LAMBDA # #) {48E2E689}>) (commit) "Successfully committed." => NIL Side Effects commit-hook is added to the list of commit hooks for database. Affected by None. Exceptional Situations If commit-hook has one or more required arguments, an error will be signalled when commit is called. See Also commit rollback add-transaction-rollback-hook with-transaction Notes add-transaction-commit-hook is a &clsql; extension. ADD-TRANSACTION-ROLLBACK-HOOK ADD-TRANSACTION-ROLLBACK-HOOK Specify hooks to be run when rolling back changes. Function Syntax add-transaction-rollback-hook rollback-hook &key database => result Arguments and Values rollback-hook A designator for a function with no required arguments. database A database object. This will default to the value of *default-database*. result The list of currently defined rollback hooks for database. Description Adds rollback-hook, which should a designator for a function with no required arguments, to the list of hooks run when rollback is called on database which defaults to *default-database*. Examples (start-transaction) => NIL (add-transaction-rollback-hook #'(lambda () (print "Successfully rolled back."))) => (#<Interpreted Function (LAMBDA # #) {48E37C31}>) (rollback) "Successfully rolled back." => NIL Side Effects rollback-hook is added to the list of rollback hooks for database. Affected by None. Exceptional Situations If rollback-hook has one or more required arguments, an error will be signalled when rollback is called. See Also commit rollback add-transaction-commit-hook Notes add-transaction-rollback-hook is a &clsql; extension. SET-AUTOCOMMIT SET-AUTOCOMMIT Turn on or off autocommit for a database. Function Syntax set-autocommit value &key database => result Arguments and Values value A Boolean specifying the desired autocommit behaviour for database. database A database object. This will default to the value of *default-database*. result The previous autocommit value for database. Description Turns autocommit off for database if value is &nil;, and otherwise turns it on. Returns the old value of autocommit flag. For RDBMS (such as Oracle) which don't automatically commit changes, turning autocommit on has the effect of explicitly committing changes made whenever SQL statements are executed. Autocommit is turned on by default. Examples Side Effects database is associated with the specified autocommit mode. Affected by None. Exceptional Situations None. See Also start-transaction commit add-transaction-commit-hook with-transaction Notes set-autocommit is a &clsql; extension. WITH-TRANSACTION WITH-TRANSACTION Execute a body of code within a transaction. Macro Syntax with-transaction &key database &rest body => result Arguments and Values database A database object. This will default to the value of *default-database*. body A body of Lisp code. result The result of executing body. Description Starts a transaction in the database specified by database, which is *default-database* by default, and executes body within that transaction. If body aborts or throws, database is rolled back and otherwise the transaction is committed. Examples (in-transaction-p) => NIL (select [email] :from [employee] :where [= [emplid] 1] :flatp t :field-names nil) => ("lenin@soviet.org") (with-transaction () (update-records [employee] :av-pairs '((email "lenin-nospam@soviet.org")) :where [= [emplid] 1])) => NIL (select [email] :from [employee] :where [= [emplid] 1] :flatp t :field-names nil) => ("lenin-nospam@soviet.org") (in-transaction-p) => NIL Side Effects Changes specified in body may be made to the underlying database if body completes successfully. Affected by None. Exceptional Situations Signals an error of type sql-database-error if database is not a database object. See Also start-transaction commit rollback add-transaction-commit-hook add-transaction-rollback-hook Notes None. cl-sql-6.4.1/doc/global-index.xml0000644000175000017500000002156210667176647015615 0ustar kevinkevin %myents; ]> Index Alphabetical Index for package CLSQL Clickable index of all symbols *BACKEND-WARNING-BEHAVIOR* *CACHE-TABLE-QUERIES-DEFAULT* *CONNECT-IF-EXISTS* *DB-AUTO-SYNC* *DEFAULT-DATABASE* *DEFAULT-DATABASE-TYPE* *DEFAULT-UPDATE-OBJECTS-MAX-LEN* *DEFAULT-STRING-LENGTH* *INITIALIZED-DATABASE-TYPES* ADD-SQL-STREAM ADD-TRANSACTION-COMMIT-HOOK ADD-TRANSACTION-ROLLBACK-HOOK ATTRIBUTE-TYPE CACHE-TABLE-QUERIES COMMIT CONNECT CONNECTED-DATABASES CREATE-DATABASE CREATE-INDEX CREATE-SEQUENCE CREATE-TABLE CREATE-VIEW CREATE-VIEW-FROM-CLASS DATABASE DATABASE-NAME DATABASE-NAME-FROM-SPEC DATABASE-TYPE DEF-VIEW-CLASS DELETE-INSTANCE-RECORDS DELETE-RECORDS DELETE-SQL-STREAM DESTROY-DATABASE DISABLE-SQL-READER-SYNTAX DISCONNECT DISCONNECT-POOLED DO-QUERY DROP-INDEX DROP-SEQUENCE DROP-TABLE DROP-VIEW DROP-VIEW-FROM-CLASS ENABLE-SQL-READER-SYNTAX EXECUTE-COMMAND FIND-DATABASE IN-TRANSACTION-P INDEX-EXISTS-P INITIALIZE-DATABASE-TYPE INSERT-RECORDS INSTANCE-REFRESHED LIST-ATTRIBUTE-TYPES LIST-ATTRIBUTES LIST-CLASSES LIST-DATABASES LIST-INDEXES LIST-SEQUENCES LIST-SQL-STREAMS LIST-TABLES LIST-VIEWS LOCALLY-DISABLE-SQL-READER-SYNTAX LOCALLY-ENABLE-SQL-READER-SYNTAX LOOP-FOR-AS-TUPLES MAP-QUERY PROBE-DATABASE QUERY RECONNECT RESTORE-SQL-READER-SYNTAX-STATE ROLLBACK SELECT SEQUENCE-EXISTS-P SEQUENCE-LAST SEQUENCE-NEXT SET-AUTOCOMMIT SET-SEQUENCE-POSITION SQL SQL-CONDITION SQL-CONNECTION-ERROR SQL-DATABASE-DATA-ERROR SQL-DATABASE-ERROR SQL-DATABASE-WARNING SQL-ERROR SQL-EXPRESSION SQL-FATAL-ERROR SQL-OPERATION SQL-OPERATOR SQL-RECORDING-P SQL-STREAM SQL-TEMPORARY-ERROR SQL-TIMEOUT-ERROR SQL-USER-ERROR SQL-WARNING START-SQL-RECORDING START-TRANSACTION STATUS STOP-SQL-RECORDING TABLE-EXISTS-P TRUNCATE-DATABASE UPDATE-INSTANCE-FROM-RECORDS UPDATE-OBJECTS-JOINS UPDATE-RECORD-FROM-SLOT UPDATE-RECORD-FROM-SLOTS UPDATE-RECORDS UPDATE-RECORDS-FROM-INSTANCE UPDATE-SLOT-FROM-RECORD VIEW-EXISTS-P WITH-DATABASE WITH-DEFAULT-DATABASE WITH-TRANSACTION cl-sql-6.4.1/doc/COPYING.GFDL0000644000175000017500000004076010667176647014275 0ustar kevinkevin GNU Free Documentation License Version 1.1, March 2000 Copyright (C) 2000 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. 0. PREAMBLE The purpose of this License is to make a manual, textbook, or other written document "free" in the sense of freedom: to assure everyone the effective freedom to copy and redistribute it, with or without modifying it, either commercially or noncommercially. Secondarily, this License preserves for the author and publisher a way to get credit for their work, while not being considered responsible for modifications made by others. This License is a kind of "copyleft", which means that derivative works of the document must themselves be free in the same sense. It complements the GNU General Public License, which is a copyleft license designed for free software. We have designed this License in order to use it for manuals for free software, because free software needs free documentation: a free program should come with manuals providing the same freedoms that the software does. But this License is not limited to software manuals; it can be used for any textual work, regardless of subject matter or whether it is published as a printed book. We recommend this License principally for works whose purpose is instruction or reference. 1. APPLICABILITY AND DEFINITIONS This License applies to any manual or other work that contains a notice placed by the copyright holder saying it can be distributed under the terms of this License. The "Document", below, refers to any such manual or work. Any member of the public is a licensee, and is addressed as "you". A "Modified Version" of the Document means any work containing the Document or a portion of it, either copied verbatim, or with modifications and/or translated into another language. A "Secondary Section" is a named appendix or a front-matter section of the Document that deals exclusively with the relationship of the publishers or authors of the Document to the Document's overall subject (or to related matters) and contains nothing that could fall directly within that overall subject. (For example, if the Document is in part a textbook of mathematics, a Secondary Section may not explain any mathematics.) The relationship could be a matter of historical connection with the subject or with related matters, or of legal, commercial, philosophical, ethical or political position regarding them. The "Invariant Sections" are certain Secondary Sections whose titles are designated, as being those of Invariant Sections, in the notice that says that the Document is released under this License. The "Cover Texts" are certain short passages of text that are listed, as Front-Cover Texts or Back-Cover Texts, in the notice that says that the Document is released under this License. A "Transparent" copy of the Document means a machine-readable copy, represented in a format whose specification is available to the general public, whose contents can be viewed and edited directly and straightforwardly with generic text editors or (for images composed of pixels) generic paint programs or (for drawings) some widely available drawing editor, and that is suitable for input to text formatters or for automatic translation to a variety of formats suitable for input to text formatters. A copy made in an otherwise Transparent file format whose markup has been designed to thwart or discourage subsequent modification by readers is not Transparent. A copy that is not "Transparent" is called "Opaque". Examples of suitable formats for Transparent copies include plain ASCII without markup, Texinfo input format, LaTeX input format, SGML or XML using a publicly available DTD, and standard-conforming simple HTML designed for human modification. Opaque formats include PostScript, PDF, proprietary formats that can be read and edited only by proprietary word processors, SGML or XML for which the DTD and/or processing tools are not generally available, and the machine-generated HTML produced by some word processors for output purposes only. The "Title Page" means, for a printed book, the title page itself, plus such following pages as are needed to hold, legibly, the material this License requires to appear in the title page. For works in formats which do not have any title page as such, "Title Page" means the text near the most prominent appearance of the work's title, preceding the beginning of the body of the text. 2. VERBATIM COPYING You may copy and distribute the Document in any medium, either commercially or noncommercially, provided that this License, the copyright notices, and the license notice saying this License applies to the Document are reproduced in all copies, and that you add no other conditions whatsoever to those of this License. You may not use technical measures to obstruct or control the reading or further copying of the copies you make or distribute. However, you may accept compensation in exchange for copies. If you distribute a large enough number of copies you must also follow the conditions in section 3. You may also lend copies, under the same conditions stated above, and you may publicly display copies. 3. COPYING IN QUANTITY If you publish printed copies of the Document numbering more than 100, and the Document's license notice requires Cover Texts, you must enclose the copies in covers that carry, clearly and legibly, all these Cover Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on the back cover. Both covers must also clearly and legibly identify you as the publisher of these copies. The front cover must present the full title with all words of the title equally prominent and visible. You may add other material on the covers in addition. Copying with changes limited to the covers, as long as they preserve the title of the Document and satisfy these conditions, can be treated as verbatim copying in other respects. If the required texts for either cover are too voluminous to fit legibly, you should put the first ones listed (as many as fit reasonably) on the actual cover, and continue the rest onto adjacent pages. If you publish or distribute Opaque copies of the Document numbering more than 100, you must either include a machine-readable Transparent copy along with each Opaque copy, or state in or with each Opaque copy a publicly-accessible computer-network location containing a complete Transparent copy of the Document, free of added material, which the general network-using public has access to download anonymously at no charge using public-standard network protocols. If you use the latter option, you must take reasonably prudent steps, when you begin distribution of Opaque copies in quantity, to ensure that this Transparent copy will remain thus accessible at the stated location until at least one year after the last time you distribute an Opaque copy (directly or through your agents or retailers) of that edition to the public. It is requested, but not required, that you contact the authors of the Document well before redistributing any large number of copies, to give them a chance to provide you with an updated version of the Document. 4. MODIFICATIONS You may copy and distribute a Modified Version of the Document under the conditions of sections 2 and 3 above, provided that you release the Modified Version under precisely this License, with the Modified Version filling the role of the Document, thus licensing distribution and modification of the Modified Version to whoever possesses a copy of it. In addition, you must do these things in the Modified Version: A. Use in the Title Page (and on the covers, if any) a title distinct from that of the Document, and from those of previous versions (which should, if there were any, be listed in the History section of the Document). You may use the same title as a previous version if the original publisher of that version gives permission. B. List on the Title Page, as authors, one or more persons or entities responsible for authorship of the modifications in the Modified Version, together with at least five of the principal authors of the Document (all of its principal authors, if it has less than five). C. State on the Title page the name of the publisher of the Modified Version, as the publisher. D. Preserve all the copyright notices of the Document. E. Add an appropriate copyright notice for your modifications adjacent to the other copyright notices. F. Include, immediately after the copyright notices, a license notice giving the public permission to use the Modified Version under the terms of this License, in the form shown in the Addendum below. G. Preserve in that license notice the full lists of Invariant Sections and required Cover Texts given in the Document's license notice. H. Include an unaltered copy of this License. I. Preserve the section entitled "History", and its title, and add to it an item stating at least the title, year, new authors, and publisher of the Modified Version as given on the Title Page. If there is no section entitled "History" in the Document, create one stating the title, year, authors, and publisher of the Document as given on its Title Page, then add an item describing the Modified Version as stated in the previous sentence. J. Preserve the network location, if any, given in the Document for public access to a Transparent copy of the Document, and likewise the network locations given in the Document for previous versions it was based on. These may be placed in the "History" section. You may omit a network location for a work that was published at least four years before the Document itself, or if the original publisher of the version it refers to gives permission. K. In any section entitled "Acknowledgements" or "Dedications", preserve the section's title, and preserve in the section all the substance and tone of each of the contributor acknowledgements and/or dedications given therein. L. Preserve all the Invariant Sections of the Document, unaltered in their text and in their titles. Section numbers or the equivalent are not considered part of the section titles. M. Delete any section entitled "Endorsements". Such a section may not be included in the Modified Version. N. Do not retitle any existing section as "Endorsements" or to conflict in title with any Invariant Section. If the Modified Version includes new front-matter sections or appendices that qualify as Secondary Sections and contain no material copied from the Document, you may at your option designate some or all of these sections as invariant. To do this, add their titles to the list of Invariant Sections in the Modified Version's license notice. These titles must be distinct from any other section titles. You may add a section entitled "Endorsements", provided it contains nothing but endorsements of your Modified Version by various parties--for example, statements of peer review or that the text has been approved by an organization as the authoritative definition of a standard. You may add a passage of up to five words as a Front-Cover Text, and a passage of up to 25 words as a Back-Cover Text, to the end of the list of Cover Texts in the Modified Version. Only one passage of Front-Cover Text and one of Back-Cover Text may be added by (or through arrangements made by) any one entity. If the Document already includes a cover text for the same cover, previously added by you or by arrangement made by the same entity you are acting on behalf of, you may not add another; but you may replace the old one, on explicit permission from the previous publisher that added the old one. The author(s) and publisher(s) of the Document do not by this License give permission to use their names for publicity for or to assert or imply endorsement of any Modified Version. 5. COMBINING DOCUMENTS You may combine the Document with other documents released under this License, under the terms defined in section 4 above for modified versions, provided that you include in the combination all of the Invariant Sections of all of the original documents, unmodified, and list them all as Invariant Sections of your combined work in its license notice. The combined work need only contain one copy of this License, and multiple identical Invariant Sections may be replaced with a single copy. If there are multiple Invariant Sections with the same name but different contents, make the title of each such section unique by adding at the end of it, in parentheses, the name of the original author or publisher of that section if known, or else a unique number. Make the same adjustment to the section titles in the list of Invariant Sections in the license notice of the combined work. In the combination, you must combine any sections entitled "History" in the various original documents, forming one section entitled "History"; likewise combine any sections entitled "Acknowledgements", and any sections entitled "Dedications". You must delete all sections entitled "Endorsements." 6. COLLECTIONS OF DOCUMENTS You may make a collection consisting of the Document and other documents released under this License, and replace the individual copies of this License in the various documents with a single copy that is included in the collection, provided that you follow the rules of this License for verbatim copying of each of the documents in all other respects. You may extract a single document from such a collection, and distribute it individually under this License, provided you insert a copy of this License into the extracted document, and follow this License in all other respects regarding verbatim copying of that document. 7. AGGREGATION WITH INDEPENDENT WORKS A compilation of the Document or its derivatives with other separate and independent documents or works, in or on a volume of a storage or distribution medium, does not as a whole count as a Modified Version of the Document, provided no compilation copyright is claimed for the compilation. Such a compilation is called an "aggregate", and this License does not apply to the other self-contained works thus compiled with the Document, on account of their being thus compiled, if they are not themselves derivative works of the Document. If the Cover Text requirement of section 3 is applicable to these copies of the Document, then if the Document is less than one quarter of the entire aggregate, the Document's Cover Texts may be placed on covers that surround only the Document within the aggregate. Otherwise they must appear on covers around the whole aggregate. 8. TRANSLATION Translation is considered a kind of modification, so you may distribute translations of the Document under the terms of section 4. Replacing Invariant Sections with translations requires special permission from their copyright holders, but you may include translations of some or all Invariant Sections in addition to the original versions of these Invariant Sections. You may include a translation of this License provided that you also include the original English version of this License. In case of a disagreement between the translation and the original English version of this License, the original English version will prevail. 9. TERMINATION You may not copy, modify, sublicense, or distribute the Document except as expressly provided for under this License. Any other attempt to copy, modify, sublicense or distribute the Document is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 10. FUTURE REVISIONS OF THIS LICENSE The Free Software Foundation may publish new, revised versions of the GNU Free Documentation License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. See http://www.gnu.org/copyleft/. Each version of the License is given a distinguishing version number. If the Document specifies that a particular numbered version of this License "or any later version" applies to it, you have the option of following the terms and conditions either of that specified version or of any later version that has been published (not as a draft) by the Free Software Foundation. If the Document does not specify a version number of this License, you may choose any version ever published (not as a draft) by the Free Software Foundation. cl-sql-6.4.1/db-postgresql/0000755000175000017500000000000012134026703014513 5ustar kevinkevincl-sql-6.4.1/db-postgresql/postgresql-package.lisp0000644000175000017500000000450711335067642021217 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; FILE IDENTIFICATION ;;;; ;;;; Name: postgresql-package.cl ;;;; Purpose: Package definition for low-level PostgreSQL interface ;;;; Programmer: Kevin M. Rosenberg ;;;; Date Started: Feb 2002 ;;;; ;;;; This file, part of CLSQL, is Copyright (c) 2002 by Kevin M. Rosenberg ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* (in-package #:cl-user) (defpackage #:pgsql #-(and :lispworks (not :lispworks4)) (:nicknames #:postgresql) (:use #:cl #:clsql-uffi) (:export #:pgsql-oid #:pgsql-conn-status-type #:pgsql-conn-status-type#connection-ok #:pgsql-conn-status-type#connection-bad #:pgsql-exec-status-type #:pgsql-exec-status-type#empty-query #:pgsql-exec-status-type#command-ok #:pgsql-exec-status-type#tuples-ok #:pgsql-exec-status-type#copy-out #:pgsql-exec-status-type#copy-in #:pgsql-exec-status-type#bad-response #:pgsql-exec-status-type#nonfatal-error #:pgsql-exec-status-type#fatal-error #:pgsql-conn #:pgsql-result #:pgsql-ftype#bytea #:pgsql-ftype#int2 #:pgsql-ftype#int4 #:pgsql-ftype#int8 #:pgsql-ftype#float4 #:pgsql-ftype#float8 ;; Used by PQresultErrorField to get the sql error code #:+PG-DIAG-SQLSTATE+ ;; Functions #:PQsetdbLogin #:PQlogin #:PQfinish #:PQstatus #:PQerrorMessage #:PQexec #:PQresultStatus #:PQresultErrorField ; used to grab the SQLSTATE code from an error #:PQresultErrorMessage #:PQntuples #:PQnfields #:PQfname #:PQfnumber #:PQftype #:PQfsize #:PQcmdStatus #:PQoidStatus #:PQcmdTuples #:PQgetvalue #:PQgetlength #:PQgetisnull #:PQclear #:PQisBusy ;;Large Objects (Marc B) #:lo-create #:lo-open #:lo-write #:lo-read #:lo-lseek #:lo-close #:lo-unlink ) (:documentation "This is the low-level interface to PostgreSQL.")) cl-sql-6.4.1/db-postgresql/postgresql-loader.lisp0000644000175000017500000000330611335067642021066 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; FILE IDENTIFICATION ;;;; ;;;; Name: postgresql-loader.sql ;;;; Purpose: PostgreSQL library loader using UFFI ;;;; Programmer: Kevin M. Rosenberg ;;;; Date Started: Feb 2002 ;;;; ;;;; This file, part of CLSQL, is Copyright (c) 2002 by Kevin M. Rosenberg ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* (in-package #:pgsql) (defvar *postgresql-supporting-libraries* '("crypt" "c") "Used only by CMU. List of library flags needed to be passed to ld to load the PostgresSQL client library succesfully. If this differs at your site, set to the right path before compiling or loading the system.") (defvar *postgresql-library-loaded* nil "T if foreign library was able to be loaded successfully") (defmethod clsql-sys:database-type-library-loaded ((database-type (eql :postgresql))) *postgresql-library-loaded*) (defmethod clsql-sys:database-type-load-foreign ((database-type (eql :postgresql))) (clsql-uffi:find-and-load-foreign-library "libpq" :module "postgresql" :supporting-libraries *postgresql-supporting-libraries*) (setq *postgresql-library-loaded* t)) (clsql-sys:database-type-load-foreign :postgresql) cl-sql-6.4.1/db-postgresql/Makefile0000644000175000017500000000011510667176647016176 0ustar kevinkevinSUBDIRS := include ../Makefile.common .PHONY: distclean distclean: clean cl-sql-6.4.1/db-postgresql/postgresql-sql.lisp0000644000175000017500000004351111544475457020432 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; FILE IDENTIFICATION ;;;; ;;;; Name: postgresql-sql.lisp ;;;; Purpose: High-level PostgreSQL interface using UFFI ;;;; Date Started: Feb 2002 ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* (in-package #:cl-user) (defpackage #:clsql-postgresql (:use #:common-lisp #:clsql-sys #:pgsql #:clsql-uffi) (:export #:postgresql-database) (:documentation "This is the CLSQL interface to PostgreSQL.")) (in-package #:clsql-postgresql) ;;; Field conversion functions (defun make-type-list-for-auto (num-fields res-ptr) (let ((new-types '())) (dotimes (i num-fields) (declare (fixnum i)) (let* ((type (PQftype res-ptr i))) (push (case type ((#.pgsql-ftype#bytea #.pgsql-ftype#int2 #.pgsql-ftype#int4) :int32) (#.pgsql-ftype#int8 :int64) ((#.pgsql-ftype#float4 #.pgsql-ftype#float8) :double) (otherwise t)) new-types))) (nreverse new-types))) (defun canonicalize-types (types num-fields res-ptr) (if (null types) nil (let ((auto-list (make-type-list-for-auto num-fields res-ptr))) (cond ((listp types) (canonicalize-type-list types auto-list)) ((eq types :auto) auto-list) (t nil))))) (defun tidy-error-message (message &optional encoding) (unless (stringp message) (setq message (uffi:convert-from-foreign-string message :encoding encoding))) (let ((message (string-right-trim '(#\Return #\Newline) message))) (cond ((< (length message) (length "ERROR:")) message) ((string= message "ERROR:" :end1 6) (string-left-trim '(#\Space) (subseq message 6))) (t message)))) (defmethod database-initialize-database-type ((database-type (eql :postgresql))) t) (uffi:def-type pgsql-conn-def pgsql-conn) (uffi:def-type pgsql-result-def pgsql-result) (defclass postgresql-database (generic-postgresql-database) ((conn-ptr :accessor database-conn-ptr :initarg :conn-ptr :type pgsql-conn-def) (lock :accessor database-lock :initform (make-process-lock "conn")))) (defmethod database-type ((database postgresql-database)) :postgresql) (defmethod database-name-from-spec (connection-spec (database-type (eql :postgresql))) (check-connection-spec connection-spec database-type (host db user password &optional port options tty)) (destructuring-bind (host db user password &optional port options tty) connection-spec (declare (ignore password options tty)) (concatenate 'string (etypecase host (null "localhost") (pathname (namestring host)) (string host)) (when port (concatenate 'string ":" (etypecase port (integer (write-to-string port)) (string port)))) "/" db "/" user))) (defmethod database-connect (connection-spec (database-type (eql :postgresql))) (check-connection-spec connection-spec database-type (host db user password &optional port options tty)) (destructuring-bind (host db user password &optional port options tty) connection-spec (uffi:with-cstrings ((host-native host) (user-native user) (password-native password) (db-native db) (port-native port) (options-native options) (tty-native tty)) (let ((connection (PQsetdbLogin host-native port-native options-native tty-native db-native user-native password-native))) (declare (type pgsql-conn-def connection)) (when (not (eq (PQstatus connection) pgsql-conn-status-type#connection-ok)) (let ((pqstatus (PQstatus connection)) (pqmessage (tidy-error-message (PQerrorMessage connection)))) (PQfinish connection) (error 'sql-connection-error :database-type database-type :connection-spec connection-spec :error-id pqstatus :message pqmessage))) (make-instance 'postgresql-database :name (database-name-from-spec connection-spec database-type) :database-type :postgresql :connection-spec connection-spec :conn-ptr connection))))) (defmethod database-disconnect ((database postgresql-database)) (PQfinish (database-conn-ptr database)) (setf (database-conn-ptr database) nil) t) (defmethod database-query (query-expression (database postgresql-database) result-types field-names) (let ((conn-ptr (database-conn-ptr database))) (declare (type pgsql-conn-def conn-ptr)) (uffi:with-cstring (query-native query-expression) (let ((result (PQexec conn-ptr query-native))) (when (uffi:null-pointer-p result) (error 'sql-database-data-error :database database :expression query-expression :message (tidy-error-message (PQerrorMessage conn-ptr) (encoding database)))) (unwind-protect (case (PQresultStatus result) ;; User gave a command rather than a query (#.pgsql-exec-status-type#command-ok nil) (#.pgsql-exec-status-type#empty-query nil) (#.pgsql-exec-status-type#tuples-ok (let ((num-fields (PQnfields result))) (when result-types (setq result-types (canonicalize-types result-types num-fields result))) (let ((res (loop for tuple-index from 0 below (PQntuples result) collect (loop for i from 0 below num-fields collect (if (zerop (PQgetisnull result tuple-index i)) (convert-raw-field (PQgetvalue result tuple-index i) (nth i result-types) :encoding (encoding database)) nil))))) (if field-names (values res (result-field-names num-fields result)) res)))) (t (error 'sql-database-data-error :database database :expression query-expression :error-id (PQresultErrorField result +PG-DIAG-SQLSTATE+) :message (tidy-error-message (PQresultErrorMessage result) (encoding database))))) (PQclear result)))))) (defun result-field-names (num-fields result) "Return list of result field names." (let ((names '())) (dotimes (i num-fields (nreverse names)) (declare (fixnum i)) (push (uffi:convert-from-cstring (PQfname result i)) names)))) (defmethod database-execute-command (sql-expression (database postgresql-database)) (let ((conn-ptr (database-conn-ptr database))) (declare (type pgsql-conn-def conn-ptr)) (uffi:with-cstring (sql-native sql-expression) (let ((result (PQexec conn-ptr sql-native))) (when (uffi:null-pointer-p result) (error 'sql-database-data-error :database database :expression sql-expression :message (tidy-error-message (PQerrorMessage conn-ptr) (encoding database)))) (unwind-protect (case (PQresultStatus result) (#.pgsql-exec-status-type#command-ok t) ((#.pgsql-exec-status-type#empty-query #.pgsql-exec-status-type#tuples-ok) (warn "Strange result...") t) (t (error 'sql-database-data-error :database database :expression sql-expression :error-id (PQresultErrorField result +PG-DIAG-SQLSTATE+) :message (tidy-error-message (PQresultErrorMessage result) (encoding database))))) (PQclear result)))))) (defstruct postgresql-result-set (res-ptr (uffi:make-null-pointer 'pgsql-result) :type pgsql-result-def) (types nil) (num-tuples 0 :type integer) (num-fields 0 :type integer) (tuple-index 0 :type integer)) (defmethod database-query-result-set ((query-expression string) (database postgresql-database) &key full-set result-types) (let ((conn-ptr (database-conn-ptr database))) (declare (type pgsql-conn-def conn-ptr)) (uffi:with-cstring (query-native query-expression) (let ((result (PQexec conn-ptr query-native))) (when (uffi:null-pointer-p result) (error 'sql-database-data-error :database database :expression query-expression :message (tidy-error-message (PQerrorMessage conn-ptr) (encoding database)))) (case (PQresultStatus result) ((#.pgsql-exec-status-type#empty-query #.pgsql-exec-status-type#tuples-ok) (let ((result-set (make-postgresql-result-set :res-ptr result :num-fields (PQnfields result) :num-tuples (PQntuples result) :types (canonicalize-types result-types (PQnfields result) result)))) (if full-set (values result-set (PQnfields result) (PQntuples result)) (values result-set (PQnfields result))))) (t (unwind-protect (error 'sql-database-data-error :database database :expression query-expression :error-id (PQresultErrorField result +PG-DIAG-SQLSTATE+) :message (tidy-error-message (PQresultErrorMessage result) (encoding database))) (PQclear result)))))))) (defmethod database-dump-result-set (result-set (database postgresql-database)) (let ((res-ptr (postgresql-result-set-res-ptr result-set))) (declare (type pgsql-result-def res-ptr)) (PQclear res-ptr) t)) (defmethod database-store-next-row (result-set (database postgresql-database) list) (let ((result (postgresql-result-set-res-ptr result-set)) (types (postgresql-result-set-types result-set))) (declare (type pgsql-result-def result)) (if (>= (postgresql-result-set-tuple-index result-set) (postgresql-result-set-num-tuples result-set)) nil (loop with tuple-index = (postgresql-result-set-tuple-index result-set) for i from 0 below (postgresql-result-set-num-fields result-set) for rest on list do (setf (car rest) (if (zerop (PQgetisnull result tuple-index i)) (convert-raw-field (PQgetvalue result tuple-index i) (nth i types) :encoding (encoding database)) nil)) finally (incf (postgresql-result-set-tuple-index result-set)) (return list))))) ;;; Large objects support (Marc B) (defmethod database-create-large-object ((database postgresql-database)) (lo-create (database-conn-ptr database) (logior pgsql::+INV_WRITE+ pgsql::+INV_READ+))) #+mb-original (defmethod database-write-large-object (object-id (data string) (database postgresql-database)) (let ((ptr (database-conn-ptr database)) (length (length data)) (result nil) (fd nil)) (with-transaction (:database database) (unwind-protect (progn (setf fd (lo-open ptr object-id pgsql::+INV_WRITE+)) (when (>= fd 0) (when (= (lo-write ptr fd data length) length) (setf result t)))) (progn (when (and fd (>= fd 0)) (lo-close ptr fd)) ))) result)) (defmethod database-write-large-object (object-id (data string) (database postgresql-database)) (let ((ptr (database-conn-ptr database)) (length (length data)) (result nil) (fd nil)) (database-execute-command "begin" database) (unwind-protect (progn (setf fd (lo-open ptr object-id pgsql::+INV_WRITE+)) (when (>= fd 0) (when (= (lo-write ptr fd data length) length) (setf result t)))) (progn (when (and fd (>= fd 0)) (lo-close ptr fd)) (database-execute-command (if result "commit" "rollback") database))) result)) ;; (MB) the begin/commit/rollback stuff will be removed when with-transaction wil be implemented ;; (KMR) Can't use with-transaction since that function is in high-level code (defmethod database-read-large-object (object-id (database postgresql-database)) (let ((ptr (database-conn-ptr database)) (buffer nil) (result nil) (length 0) (fd nil)) (unwind-protect (progn (database-execute-command "begin" database) (setf fd (lo-open ptr object-id pgsql::+INV_READ+)) (when (>= fd 0) (setf length (lo-lseek ptr fd 0 2)) (lo-lseek ptr fd 0 0) (when (> length 0) (setf buffer (uffi:allocate-foreign-string length :unsigned t)) (when (= (lo-read ptr fd buffer length) length) (setf result (uffi:convert-from-foreign-string buffer :length length :null-terminated-p nil :encoding (encoding database))))))) (progn (when buffer (uffi:free-foreign-object buffer)) (when (and fd (>= fd 0)) (lo-close ptr fd)) (database-execute-command (if result "commit" "rollback") database))) result)) (defmethod database-delete-large-object (object-id (database postgresql-database)) (lo-unlink (database-conn-ptr database) object-id)) ;;; Object listing (defmethod database-create (connection-spec (type (eql :postgresql))) (destructuring-bind (host name user password) connection-spec (let ((database (database-connect (list host "postgres" user password) type))) (setf (slot-value database 'clsql-sys::state) :open) (unwind-protect (database-execute-command (format nil "create database ~A" name) database) (database-disconnect database))))) (defmethod database-destroy (connection-spec (type (eql :postgresql))) (destructuring-bind (host name user password) connection-spec (let ((database (database-connect (list host "postgres" user password) type))) (setf (slot-value database 'clsql-sys::state) :open) (unwind-protect (database-execute-command (format nil "drop database ~A" name) database) (database-disconnect database))))) (defmethod database-probe (connection-spec (type (eql :postgresql))) (when (find (second connection-spec) (database-list connection-spec type) :test #'string-equal) t)) (defun %pg-database-connection (connection-spec) (check-connection-spec connection-spec :postgresql (host db user password &optional port options tty)) (macrolet ((coerce-string (var) `(unless (typep ,var 'simple-base-string) (setf ,var (coerce ,var 'simple-base-string))))) (destructuring-bind (host db user password &optional port options tty) connection-spec (coerce-string db) (coerce-string user) (let ((connection (PQsetdbLogin host port options tty db user password))) (declare (type pgsql::pgsql-conn-ptr connection)) (unless (eq (PQstatus connection) pgsql-conn-status-type#connection-ok) ;; Connect failed (error 'sql-connection-error :database-type :postgresql :connection-spec connection-spec :error-id (PQstatus connection) :message (PQerrorMessage connection))) connection)))) (defmethod database-reconnect ((database postgresql-database)) (let ((lock (database-lock database))) (with-process-lock (lock "Reconnecting") (with-slots (connection-spec conn-ptr) database (setf conn-ptr (%pg-database-connection connection-spec)) database)))) ;;; Database capabilities (when (clsql-sys:database-type-library-loaded :postgresql) (clsql-sys:initialize-database-type :database-type :postgresql)) cl-sql-6.4.1/db-postgresql/postgresql-api.lisp0000644000175000017500000001763011335067642020376 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; FILE IDENTIFICATION ;;;; ;;;; Name: postgresql.cl ;;;; Purpose: Low-level PostgreSQL interface using UFFI ;;;; Programmers: Kevin M. Rosenberg based on ;;;; Original code by Pierre R. Mai ;;;; Date Started: Feb 2002 ;;;; ;;;; This file, part of CLSQL, is Copyright (c) 2002 by Kevin M. Rosenberg ;;;; and Copyright (c) 1999-2001 by Pierre R. Mai ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* (in-package #:pgsql) ;;;; This file implements as little of the FFI bindings to the ;;;; PostgreSQL client libraries as we could get away with. ;;;; Especially all the PostgreSQL-specific goodies aren't there, and ;;;; we just use void pointers where we can get away with it, which ;;;; thanks to the design of the PostgreSQL client libraries is pretty ;;;; much everywhere, in contrast to the MySQL client libraries for ;;;; example. ;;;; Type definitions ;;; Basic Types (uffi:def-foreign-type pgsql-oid :unsigned-int) (uffi:def-enum pgsql-conn-status-type (:connection-ok :connection-bad)) (uffi:def-enum pgsql-exec-status-type (:empty-query :command-ok :tuples-ok :copy-out :copy-in :bad-response :nonfatal-error :fatal-error)) (uffi:def-foreign-type pgsql-conn :pointer-void) (uffi:def-foreign-type pgsql-result :pointer-void) (uffi:def-type pgsql-conn-ptr :pointer-void) (uffi:def-enum pgsql-ftype ((:bytea 17) (:int2 21) (:int4 23) (:int8 20) (:float4 700) (:float8 701))) ;;(declaim (inline PQsetdbLogin)) ;; causes compile error in LW 4.2.0 (uffi:def-function ("PQsetdbLogin" PQsetdbLogin) ((pghost :cstring) (pgport :cstring) (pgoptions :cstring) (pgtty :cstring) (dbName :cstring) (login :cstring) (pwd :cstring)) :module "postgresql" :returning pgsql-conn) (declaim (inline PQfinish)) (uffi:def-function ("PQfinish" PQfinish) ((conn pgsql-conn)) :module "postgresql" :returning :void) (declaim (inline PQstatus)) (uffi:def-function ("PQstatus" PQstatus) ((conn pgsql-conn)) :module "postgresql" :returning pgsql-conn-status-type) (declaim (inline PQerrorMessage)) (uffi:def-function ("PQerrorMessage" PQerrorMessage) ((conn pgsql-conn)) :module "postgresql" :returning :cstring) (declaim (inline PQexec)) (uffi:def-function ("PQexec" PQexec) ((conn pgsql-conn) (query :cstring)) :module "postgresql" :returning pgsql-result) (declaim (inline PQresultStatus)) (uffi:def-function ("PQresultStatus" PQresultStatus) ((res pgsql-result)) :module "postgresql" :returning pgsql-exec-status-type) ; From postgres_ext.h ; #define PG_DIAG_SEVERITY 'S' ; #define PG_DIAG_SQLSTATE 'C' ; #define PG_DIAG_MESSAGE_PRIMARY 'M' ; #define PG_DIAG_MESSAGE_DETAIL 'D' ; #define PG_DIAG_MESSAGE_HINT 'H' ; #define PG_DIAG_STATEMENT_POSITION 'P' ; #define PG_DIAG_INTERNAL_POSITION 'p' ; #define PG_DIAG_INTERNAL_QUERY 'q' ; #define PG_DIAG_CONTEXT 'W' ; #define PG_DIAG_SOURCE_FILE 'F' ; #define PG_DIAG_SOURCE_LINE 'L' ; #define PG_DIAG_SOURCE_FUNCTION 'R' (defconstant +PG-DIAG-SEVERITY+ (char-code #\S)) (defconstant +PG-DIAG-SQLSTATE+ (char-code #\C)) (defconstant +PG-DIAG-MESSAGE-PRIMARY+ (char-code #\M)) (defconstant +PG-DIAG-MESSAGE-DETAIL+ (char-code #\D)) (defconstant +PG-DIAG-MESSAGE-HINT+ (char-code #\H)) (defconstant +PG-DIAG-STATEMENT-POSITION+ (char-code #\P)) (defconstant +PG-DIAG-INTERNAL-POSITION+ (char-code #\p)) (defconstant +PG-DIAG-INTERNAL-QUERY+ (char-code #\q)) (defconstant +PG-DIAG-CONTEXT+ (char-code #\W)) (defconstant +PG-DIAG-SOURCE-FILE+ (char-code #\F)) (defconstant +PG-DIAG-SOURCE-LINE+ (char-code #\L)) (defconstant +PG-DIAG-SOURCE-FUNCTION+ (char-code #\R)) ; PQresultErrorField can return diagnostic information about an error (declaim (inline PQresultErrorField)) (uffi:def-function ("PQresultErrorField" PQresultErrorField) ((res pgsql-result) (field-code :int)) :module "postgresql" :returning :cstring) (declaim (inline PQresultErrorMessage)) (uffi:def-function ("PQresultErrorMessage" PQresultErrorMessage) ((res pgsql-result)) :module "postgresql" :returning :cstring) (declaim (inline PQntuples)) (uffi:def-function ("PQntuples" PQntuples) ((res pgsql-result)) :module "postgresql" :returning :int) (declaim (inline PQnfields)) (uffi:def-function ("PQnfields" PQnfields) ((res pgsql-result)) :module "postgresql" :returning :int) (declaim (inline PQfname)) (uffi:def-function ("PQfname" PQfname) ((res pgsql-result) (field-num :int)) :module "postgresql" :returning :cstring) (declaim (inline PQfnumber)) (uffi:def-function ("PQfnumber" PQfnumber) ((res pgsql-result) (field-name :cstring)) :module "postgresql" :returning :int) (declaim (inline PQftype)) (uffi:def-function ("PQftype" PQftype) ((res pgsql-result) (field-num :int)) :module "postgresql" :returning pgsql-oid) (declaim (inline PQfsize)) (uffi:def-function ("PQfsize" PQfsize) ((res pgsql-result) (field-num :int)) :module "postgresql" :returning :short) (declaim (inline PQcmdStatus)) (uffi:def-function ("PQcmdStatus" PQcmdStatus) ((res pgsql-result)) :module "postgresql" :returning :cstring) (declaim (inline PQoidStatus)) (uffi:def-function ("PQoidStatus" PQoidStatus) ((res pgsql-result)) :module "postgresql" :returning :cstring) (declaim (inline PQcmdTuples)) (uffi:def-function ("PQcmdTuples" PQcmdTuples) ((res pgsql-result)) :module "postgresql" :returning :cstring) (declaim (inline PQgetvalue)) (uffi:def-function ("PQgetvalue" PQgetvalue) ((res pgsql-result) (tup-num :int) (field-num :int)) :module "postgresql" :returning (* :unsigned-char)) (declaim (inline PQgetlength)) (uffi:def-function ("PQgetlength" PQgetlength) ((res pgsql-result) (tup-num :int) (field-num :int)) :module "postgresql" :returning :int) (declaim (inline PQgetisnull)) (uffi:def-function ("PQgetisnull" PQgetisnull) ((res pgsql-result) (tup-num :int) (field-num :int)) :module "postgresql" :returning :int) (declaim (inline PQclear)) (uffi:def-function ("PQclear" PQclear) ((res pgsql-result)) :module "postgresql" :returning :void) (declaim (inline PQisBusy)) (uffi:def-function ("PQisBusy" PQisBusy) ((conn pgsql-conn)) :module "postgresql" :returning :int) ;;; Large objects support (MB) (defconstant +INV_ARCHIVE+ 65536) ; fe-lobj.c (defconstant +INV_WRITE+ 131072) (defconstant +INV_READ+ 262144) (declaim (inline lo-creat)) (uffi:def-function ("lo_creat" lo-create) ((conn pgsql-conn) (mode :int)) :module "postgresql" :returning pgsql-oid) (declaim (inline lo-open)) (uffi:def-function ("lo_open" lo-open) ((conn pgsql-conn) (oid pgsql-oid) (mode :int)) :module "postgresql" :returning :int) (declaim (inline lo-write)) (uffi:def-function ("lo_write" lo-write) ((conn pgsql-conn) (fd :int) (data :cstring) (size :int)) :module "postgresql" :returning :int) (declaim (inline lo-read)) (uffi:def-function ("lo_read" lo-read) ((conn pgsql-conn) (fd :int) (data (* :unsigned-char)) (size :int)) :module "postgresql" :returning :int) (declaim (inline lo-lseek)) (uffi:def-function ("lo_lseek" lo-lseek) ((conn pgsql-conn) (fd :int) (offset :int) (whence :int)) :module "postgresql" :returning :int) (declaim (inline lo-close)) (uffi:def-function ("lo_close" lo-close) ((conn pgsql-conn) (fd :int)) :module "postgresql" :returning :int) (declaim (inline lo-unlink)) (uffi:def-function ("lo_unlink" lo-unlink) ((conn pgsql-conn) (oid pgsql-oid)) :module "postgresql" :returning :int) cl-sql-6.4.1/COPYING.SQL-ODBC0000644000175000017500000000204110667176647014146 0ustar kevinkevin;;; SQL/ODBC module for MCL, CMUCL, LispWorks, ACL and CormanLisp ;;; Version 0.9 ;;; Copyright (C) Paul Meurer 1999-2001 All rights reserved. ;;; paul.meurer@hit.uib.no ;;; ;;; Use and copying of this software and preparation of derivative works ;;; based upon this software are permitted, so long as the following ;;; conditions are met: ;;; o This copyright notice is included intact. ;;; o No fees or compensation are charged for use, copies, or ;;; access to this software. You may charge a nominal ;;; distribution fee for the physical act of transferring a ;;; copy, but you may not charge for the program itself. ;;; o You are allowed to use this software as part of a commercial ;;; software package, provided that its functionality significantly ;;; exceeds the functionality of this software, and that the use of ;;; this software is explicitly mentioned in your documentation. ;;; ;;; This software is made available AS IS, and no warranty is made about ;;; the software or its performance. cl-sql-6.4.1/README0000644000175000017500000000310311772211707012611 0ustar kevinkevinCLSQL is a Common Lisp to SQL engine interface by Kevin M. Rosenberg. It includes both functional and object oriented subsystems for data definition and manipulation as well as an integrated symbolic SQL syntax. CLSQL supports a number of RDBMS and uses the UFFI (http://uffi.b9.com) library for compatibility with Allegro CL, Lispworks, CMUCL, SBCL and OpenMCL. CLSQL has incorporated code from the following projects. At this point in 2004, development of has stopped on these incorporated projects. - Pierre Mai's MaiSQL - onShore Development's UncommonSQL - Paul Meurer's SQL/ODBC - Cadabra's Oracle interface CLSQL's home is http://clsql.b9.com. Documentation is available as a PDF file in doc/clsql.pdf and as HTML files in doc/html.tar.gz. CONTRIBUTING ------------ If you would like to report a bug please do so through the clsql mailing list. http://lists.b9.com/mailman/listinfo/CLSQL Patches are welcome. It will be much easier for us to incorporate if you use [git](http://git-scm.com/). Please keep distinct changes in seperate patches as it makes it much easier to review. If you have something small to to send to the mailing list `git format-patch` is your friend. If you have a bigger set of patches then I recommend creating a fork on github from https://github.com/UnwashedMeme/clsql. Once your patches are available there either issue a pull request or let us know about it on the mailing list. * http://help.github.com/ has some excellent tutorials on getting started. * http://git-scm.com/book is an excellent in depth tutorial on how to use git effectively. cl-sql-6.4.1/clsql-aodbc.asd0000644000175000017500000000264311332141035014602 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; FILE IDENTIFICATION ;;;; ;;;; Name: clsql-aodbc.asd ;;;; Purpose: ASDF definition file for CLSQL AODBC backend ;;;; Programmer: Kevin M. Rosenberg ;;;; Date Started: Aug 2002 ;;;; ;;;; This file, part of CLSQL, is Copyright (c) 2002-2010 by Kevin M. Rosenberg ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* (defpackage #:clsql-aodbc-system (:use #:asdf #:cl)) (in-package #:clsql-aodbc-system) #+(and allegro (not allegro-cl-trial)) (defsystem clsql-aodbc :name "cl-sql-aodbc" :author "Kevin M. Rosenberg " :maintainer "Kevin M. Rosenberg " :licence "Lessor Lisp General Public License" :description "Common Lisp SQL AODBC Driver" :long-description "cl-sql-aodbc package provides a database driver to AllegroCL's AODBC database interface." :depends-on (clsql) :components ((:module :db-aodbc :components ((:file "aodbc-package") (:file "aodbc-sql" :depends-on ("aodbc-package")))))) #-(and allegro (not allegro-cl-trial)) (defsystem clsql-aodbc) cl-sql-6.4.1/clsql-oracle.asd0000644000175000017500000000321011332141035014766 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; FILE IDENTIFICATION ;;;; ;;;; Name: clsql-oracle.asd ;;;; Purpose: ASDF definition file for CLSQL Oracle backend ;;;; Programmer: Kevin M. Rosenberg ;;;; Date Started: Aug 2002 ;;;; ;;;; This file is part of CLSQL. ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* (defpackage #:clsql-oracle-system (:use #:asdf #:cl)) (in-package #:clsql-oracle-system) ;;; System definition (defsystem clsql-oracle :name "clsql-oracle" :author "Kevin M. Rosenberg " :maintainer "Kevin M. Rosenberg " :licence "Lessor Lisp General Public License" :description "Common Lisp SQL Oracle Driver" :long-description "cl-sql-oracle package provides a database driver to the Oracle database system." :depends-on (clsql-uffi) :components ((:module :db-oracle :components ((:file "oracle-package") (:file "oracle-loader" :depends-on ("oracle-package")) (:file "foreign-resources" :depends-on ("oracle-package")) (:file "oracle-constants" :depends-on ("oracle-package")) (:file "oracle-api" :depends-on ("oracle-constants" "oracle-loader")) (:file "oracle-sql" :depends-on ("oracle-api" "foreign-resources")) (:file "oracle-objects" :depends-on ("oracle-sql")))))) cl-sql-6.4.1/uffi/0000755000175000017500000000000012134026703012656 5ustar kevinkevincl-sql-6.4.1/uffi/Makefile.32+64bits0000644000175000017500000000557311335067642015673 0ustar kevinkevin#!/usr/bin/make ########################################################################## # FILE IDENTIFICATION # # Name: Makefile # Purpose: Makefile for CLSQL UFFI interface # Programer: Kevin M. Rosenberg # Date Started: Mar 2002 # # This file, part of CLSQL, is Copyright (c) 2002-2010 by Kevin M. Rosenberg # # CLSQL users are granted the rights to distribute and use this software # as governed by the terms of the Lisp Lesser GNU Public License # (http://opensource.franz.com/preamble.html), also known as the LLGPL. ########################################################################## SUBDIRS= include ../Makefile.common PTRBITS:=$(shell gcc -o ptrbits ptrbits.c && ./ptrbits) base:=clsql_uffi basebits:=$(base) ifeq ($(PTRBITS),64) basebits:=$(base)64 endif source=$(base).c object=$(basebits).o shared_lib=$(basebits).so shared_lib32=$(base)32.so object32=$(base)32.o .PHONY: all ifeq ($(PTRBITS),64) all: $(shared_lib) $(shared_lib32) else all: $(shared_lib) endif $(shared_lib): $(source) Makefile ifneq ($(OS_AIX),0) gcc -c -D_BSD -D_NO_PROTO -D_NONSTD_TYPES -D_MBI=void $(source) make_shared -o $(shared_lib) $(object) else ifneq ($(OS_SUNOS),0) cc -KPIC -c $(source) -o $(object) cc -G $(object) -o $(shared_lib) else ifneq ($(OS_DARWIN),0) cc -dynamic -c $(source) -o $(object) ld -bundle /usr/lib/bundle1.o -flat_namespace -undefined suppress -o $(base).dylib $(object) ld -bundle /usr/lib/bundle1.o -flat_namespace -undefined suppress /usr/lib/libz.dylib -o z.dylib else ifneq ($(OS_CYGWIN),0) gcc -c $(source) -o $(object) ld -shared -soname=$(base) $(LDFLAGS) $(object) -o $(shared_lib) else gcc -fPIC -DPIC -c $(source) -o $(object) ld -shared -soname=$(base) -lc $(object) -o $(shared_lib) endif endif endif endif rm $(object) ifeq ($(PTRBITS),64) $(shared_lib32): $(source) Makefile ifneq ($(OS_AIX),0) gcc -m32 -c -D_BSD -D_NO_PROTO -D_NONSTD_TYPES -D_MBI=void $(source) -o ($object32) make_shared -o $(shared_lib32) $(object32) else ifneq ($(OS_SUNOS),0) cc -m32 -KPIC -c $(source) -o $(object32) cc -G $(object32) -o $(shared_lib32) else ifneq ($(OS_DARWIN),0) cc -m32 -dynamic -c $(source) -o $(object32) ld -bundle /usr/lib/bundle1.o -flat_namespace -undefined suppress -o $(base)32.dylib $(object32) ld -bundle /usr/lib/bundle1.o -flat_namespace -undefined suppress /usr/lib/libz32.dylib -o z.dylib else ifneq ($(OS_CYGWIN),0) gcc -m32 -c $(source) -o $(object32) ld -shared -soname=$(base) $(LDFLAGS) $(object32) -o $(shared_lib32) else gcc -m32 -fPIC -DPIC -c $(source) -o $(object32) ld -shared -soname=$(base) -L /lib32 -L /usr/lib32 -lc $(object32) -o $(shared_lib32) endif endif endif endif endif rm $(object32) .PHONY: distclean distclean: clean rm -f $(base).dylib $(base).dylib $(basebits).so $(base).o ptrbits cl-sql-6.4.1/uffi/clsql_uffi.dll0000644000175000017500000001100010667176647015520 0ustar kevinkevinMZÿÿ¸@𺴠Í!¸LÍ!This program cannot be run in DOS mode. $ß2£›c\ð›c\ð›c\ðkð™c\ð›c]ð’c\ðžoð˜c\ðžo<ðšc\ðžoSð˜c\ðžoð“c\ðžoðšc\ðžoðšc\ðRich›c\ðPEL½ÒÀ@à!   PÐ!BÄ <@th H ,.text< `.rdata  @@.data(0@À.relocˆ@@BU‹ì¸] ÌÌÌÌU‹ìƒìVWÇEðÇEôÇEü‹E¶‰Møƒ}ø+u ‹UƒÂ‰Uëƒ}ø-uÇEü‹EƒÀ‰E‹M¶…ÒtD‹E¶ƒé0‰Mìxƒ}ì ~ë.‹E왋ð‹újj ‹UôR‹EðPèŠðú‰uð‰}ô‹MƒÁ‰M벃}üt‹Uð÷Ú‹EôƒÐ÷؉Uð‰Eô‹Eð‹Uô± è‹M ‰‹Eð#0 _^‹å]ÃÌÌÌÌÌÌÌÌÌÌÌ€ù@s€ù s­ÐÓúËÂÁú€áÓøÃÁú‹ÂÃÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌ‹D$‹L$ È‹L$ u ‹D$÷áÂS÷á‹Ø‹D$÷d$Ø‹D$÷áÓ[‹D$…Àu90~.ÿ 0ƒø‹  ‹ ‰ 0uOh€ÿ …ÀY£ 0u3Àëyƒ ¡ 0£0èŒhxèpÇ$0h0è3ÿ0Yë?…Àu<¡ 0…Àt3ë‹ 0‹ …ÉtÿÑ¡ 0ƒ-090sÞPÿ$ ƒ% 0Y3À@ j h8 èÆ3À@‰Eä3ÿ‰}ü‹u ;÷u 9=0„¬;ðtƒþu1¡$0;Çt ÿuVÿuÿЉEä9}ä„…ÿuVÿuèåþÿÿ‰Eä;Çtr‹]SVÿuè?‰Eäƒþu;Çu SWÿuè»þÿÿ;÷tƒþu)SVÿuè¨þÿÿ…Àu‰}ä9}ät¡$0;Çt SVÿuÿЉEäƒMüÿ‹Eäë‹Eì‹‹ PQèÚYYËeèƒMüÿ3Àè, ÿ% ƒ= 0ÿuÿ% h0h 0ÿt$ èƒÄ Ãÿt$èÑÿÿÿ÷ØÀ÷ØYHÃj hH è¤ÇEä¸ }ä¸ s"ƒeü‹Eä‹…Àt ÿÐë3À@ËeèƒMüÿƒEäëÕè¨Ãj hX è`ÇEäÀ }äÀ s"ƒeü‹Eä‹…Àt ÿÐë3À@ËeèƒMüÿƒEäëÕèdÃÿ% ƒ|$uƒ=$0u ÿt$ÿ 3À@ ÌÌh0d¡P‹D$‰l$l$+àSVW‹Eø‰eèP‹EüÇEüÿÿÿÿ‰EøEðd£Ã‹Mðd‰ Y_^[ÉQÃÿ% ÿ% ¤!J!Z!4!Œ!š!l!@!,!ÿÿÿÿÿÿÿÿÔåÿÿÿÿaeÿÿÿÿ¥©H0° 0!€! !À! ¤!J!Z!4!Œ!š!l!@!,!¬free?_inittermßmalloc»_adjust_fdivL__CppXcptFilterñ_except_handler3MSVCR71.dllk__dllonexit¸_onexit„DisableThreadLibraryCallsKERNEL32.dll½ÒÀ@"ø!ü!" "uffi.dllatol64Næ@»\Û0^1f1o1w1„1Œ1š1Ÿ1©1µ1º1Å1Ñ1Ý1ê1ð1÷122222F2¹2ø2þ23 3373C3J3{3‡3Ž3¾3Ë3Ø3å32484 <0@0L0P0\0`0¤0¨0cl-sql-6.4.1/uffi/clsql-uffi.lisp0000644000175000017500000001152511577723152015634 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; FILE IDENTIFICATION ;;;; ;;;; Name: clsql-uffi.cl ;;;; Purpose: Common functions for interfaces using UFFI ;;;; Programmers: Kevin M. Rosenberg ;;;; Date Started: Mar 2002 ;;;; ;;;; This file, part of CLSQL, is Copyright (c) 2002-2010 by Kevin M. Rosenberg ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* (in-package #:clsql-uffi) (defun canonicalize-type-list (types auto-list) "Ensure a field type list meets expectations" (declare (optimize (speed 3) (safety 0))) (do ((i 0 (1+ i)) (new-types '()) (length-types (length types)) (length-auto-list (length auto-list))) ((= i length-auto-list) (nreverse new-types)) (declare (fixnum length-types length-auto-list i)) (if (>= i length-types) (push t new-types) ;; types is shorter than num-fields (push (case (nth i types) (:int (case (nth i auto-list) (:int32 :int32) (:int64 :int64) (t t))) (:double (case (nth i auto-list) (:double :double) (t t))) (:int32 (if (eq :int32 (nth i auto-list)) :int32 t)) (:int64 (if (eq :int64 (nth i auto-list)) :int64 t)) (:blob :blob) (:uint :uint) (t t)) new-types)))) (uffi:def-function "atoi" ((str (* :unsigned-char))) :returning :int) (uffi:def-function ("strtoul" c-strtoul) ((str (* :unsigned-char)) (endptr (* :unsigned-char)) (radix :int)) :returning :unsigned-long) (uffi:def-function "atol" ((str (* :unsigned-char))) :returning :long) (uffi:def-function "atof" ((str (* :unsigned-char))) :returning :double) (uffi:def-function "atol64" ((str (* :unsigned-char)) (high32 (* :unsigned-int))) :module "clsql-uffi" :returning :unsigned-int) (uffi:def-constant +2^32+ 4294967296) (uffi:def-constant +2^64+ 18446744073709551616) (uffi:def-constant +2^32-1+ (1- +2^32+)) (defmacro make-64-bit-integer (high32 low32) `(if (zerop (ldb (byte 1 31) ,high32)) (+ ,low32 (ash ,high32 32)) (- (+ ,low32 (ash ,high32 32)) +2^64+))) ;; From high to low ints (defmacro make-128-bit-integer (a b c d) `(+ ,d (ash ,c 32) (ash ,b 64) (ash ,a 96))) (defmacro split-64-bit-integer (int64) `(values (ash ,int64 -32) (logand ,int64 +2^32-1+))) (uffi:def-type char-ptr-def (* :unsigned-char)) (defun strtoul (char-ptr) (declare (optimize (speed 3) (safety 0) (space 0)) (type char-ptr-def char-ptr)) (c-strtoul char-ptr uffi:+null-cstring-pointer+ 10)) (defun convert-raw-field (char-ptr type &key length encoding) (declare (optimize (speed 3) (safety 0) (space 0)) (type char-ptr-def char-ptr)) (cond ((uffi:null-pointer-p char-ptr) nil) (t (case type (:double (atof char-ptr)) (:int (atol char-ptr)) (:int32 (atoi char-ptr)) (:uint32 (strtoul char-ptr)) (:uint (strtoul char-ptr)) ((:int64 :uint64) (uffi:with-foreign-object (high32-ptr :unsigned-int) (let ((low32 (atol64 char-ptr high32-ptr)) (high32 (uffi:deref-pointer high32-ptr :unsigned-int))) (if (zerop high32) low32 (make-64-bit-integer high32 low32))))) (:blob (if length (uffi:convert-from-foreign-usb8 char-ptr length) (error "Can't return blob since length is not specified."))) (t (if encoding (if length (uffi:convert-from-foreign-string char-ptr :null-terminated-p nil :length length :encoding encoding) (uffi:convert-from-foreign-string char-ptr :null-terminated-p t :encoding encoding)) (if length (uffi:convert-from-foreign-string char-ptr :null-terminated-p nil :length length) (uffi:convert-from-foreign-string char-ptr :null-terminated-p t)))))))) cl-sql-6.4.1/uffi/clsql_uffi.c0000644000175000017500000000333111335067642015162 0ustar kevinkevin/**************************************************************************** * FILE IDENTIFICATION * * Name: clsql-uffi.c * Purpose: Helper functions for common interfaces using UFFI * Programmer: Kevin M. Rosenberg * Date Started: Mar 2002 * * This file, part of CLSQL, is Copyright (c) 2002-2010 by Kevin M. Rosenberg * * CLSQL users are granted the rights to distribute and use this software * as governed by the terms of the Lisp Lesser GNU Public License * (http://opensource.franz.com/preamble.html), also known as the LLGPL. ***************************************************************************/ #if defined(WIN32)||defined(WIN64) #include BOOL WINAPI DllEntryPoint(HINSTANCE hinstdll, DWORD fdwReason, LPVOID lpvReserved) { return 1; } #define DLLEXPORT __declspec(dllexport) #else #define DLLEXPORT #endif const unsigned int bitmask_32bits = 0xFFFFFFFF; #define lower_32bits(int64) ((unsigned int) int64 & bitmask_32bits) #define upper_32bits(int64) ((unsigned int) (int64 >> 32)) /* Reads a 64-bit integer string, returns result as two 32-bit integers */ DLLEXPORT unsigned int atol64 (const unsigned char* str, unsigned int* pHigh32) { #if defined(WIN32)||defined(WIN64) __int64 result = 0; #else long long result = 0; #endif int minus = 0; int first_char = *str; if (first_char == '+') ++str; else if (first_char == '-') { minus = 1; ++str; } while (*str) { int i = *str - '0'; if (i < 0 || i > 9) /* Non-numeric character -- quit */ break; result = i + (10 * result); str++; } if (minus) result = -result; *pHigh32 = upper_32bits(result); return lower_32bits(result); } cl-sql-6.4.1/uffi/clsql-uffi-loader.lisp0000644000175000017500000000564411335067642017102 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; FILE IDENTIFICATION ;;;; ;;;; Name: clsql-uffi-loader.sql ;;;; Purpose: Library loader using CLSQL UFFI helper library ;;;; Author: Kevin M. Rosenberg ;;;; Created: Mar 2002 ;;;; ;;;; This file, part of CLSQL, is Copyright (c) 2002-2010 by Kevin M. Rosenberg ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* (in-package #:clsql-uffi) (defun find-and-load-foreign-library (filenames &key module supporting-libraries (errorp t)) "Attempt to load a foreign library. This will search for any of the filenames, as well as any of the filenames in any of the clsql:*foreign-library-search-paths*" (setq filenames (if (listp filenames) filenames (list filenames))) (flet ((try-load (testpath) (handler-case (uffi:load-foreign-library testpath :module module :supporting-libraries supporting-libraries) (error nil)))) ;(c) (warn "~A" c) nil)))) (or (loop for type in (uffi:foreign-library-types) thereis (loop for name in filenames for pn = (make-pathname :name name :type type) thereis (or (try-load pn) (loop for search-path in clsql:*foreign-library-search-paths* thereis (try-load (merge-pathnames pn search-path)))))) (when errorp (error "Couldn't load foreign librar~@P ~{~S~^, ~}. (searched ~S)" (length filenames) filenames 'clsql:*foreign-library-search-paths*))))) ;; searches clsql_uffi64 to accomodate both 32-bit and 64-bit libraries on same system (defvar *clsql-uffi-library-filenames* `(,@(when (> most-positive-fixnum (expt 2 32)) (list "clsql_uffi64")) "clsql_uffi")) (defvar *clsql-uffi-supporting-libraries* '("c") "Used only by CMU. List of library flags needed to be passed to ld to load the MySQL client library succesfully. If this differs at your site, set to the right path before compiling or loading the system.") (defvar *uffi-library-loaded* nil "T if foreign library was able to be loaded successfully") (defun load-uffi-foreign-library () (clsql:push-library-path clsql-uffi-system::*clsql-uffi-library-dir*) (find-and-load-foreign-library *clsql-uffi-library-filenames* :module "clsql-uffi" :supporting-libraries *clsql-uffi-supporting-libraries*) (setq *uffi-library-loaded* t)) (load-uffi-foreign-library) cl-sql-6.4.1/uffi/Makefile0000644000175000017500000000436011335104544014323 0ustar kevinkevin#!/usr/bin/make # FILE IDENTIFICATION # # Name: Makefile # Purpose: Makefile for CLSQL UFFI interface # Programer: Kevin M. Rosenberg # Date Started: Mar 2002 # # This file, part of CLSQL, is Copyright (c) 2002-2006 by Kevin M. Rosenberg # # CLSQL users are granted the rights to distribute and use this software # as governed by the terms of the Lisp Lesser GNU Public License # (http://opensource.franz.com/preamble.html), also known as the LLGPL. SUBDIRS= include ../Makefile.common base=clsql_uffi source=$(base).c object=$(base).o shared_lib=$(base).so shared64_lib=$(base)64.so dylib=$(base).dylib .PHONY: all all: $(shared_lib) $(shared_lib): $(source) Makefile ifneq ($(OS_AIX),0) gcc -c -D_BSD -D_NO_PROTO -D_NONSTD_TYPES -D_MBI=void $(source) make_shared -o $(shared_lib) $(object) else ifneq ($(OS_SUNOS),0) cc -KPIC -c $(source) -o $(object) cc -G $(object) -o $(shared_lib) else ifneq ($(OS_DARWIN64),0) cc -arch x86_64 -arch i386 -bundle /usr/lib/bundle1.o -flat_namespace -undefined suppress $(source) -o $(dylib) cc -arch x86_64 -arch i386 -bundle /usr/lib/bundle1.o -flat_namespace -undefined suppress /usr/lib/libz.dylib -o z.dylib else ifneq ($(OS_DARWIN),0) cc -arch i386 -bundle /usr/lib/bundle1.o -flat_namespace -undefined suppress $(source) -o $(dylib) cc -arch i386 -bundle /usr/lib/bundle1.o -flat_namespace -undefined suppress /usr/lib/libz.dylib -o z.dylib else ifneq ($(OS_CYGWIN),0) gcc -c $(source) -o $(object) ld -shared -soname=$(base) $(LDFLAGS) $(object) -o $(shared_lib) else ifneq ($(OS_LINUX64),0) gcc -fPIC -DPIC -c $(source) -o $(object) ld -shared -soname=$(base) -lc $(object) -o $(shared64_lib) rm -f $(object) @echo "Ensure that you have multiarch i386 build tools if you want to build 32-bit library" -gcc -m32 -fPIC -DPIC -c $(source) -o $(object) -ld -melf_i386 -shared -soname=$(base) -lc $(object) -o $(shared_lib) else gcc -fPIC -DPIC -c $(source) -o $(object) ld -shared -soname=$(base) -lc $(object) -o $(shared_lib) endif endif endif endif endif endif rm -f $(object) .PHONY: distclean distclean: clean @rm -f $(dylib) $(shared_lib) $(shared64_lib) $(object) z.dylib cl-sql-6.4.1/uffi/clsql_uffi.lib0000644000175000017500000000317210667176647015526 0ustar kevinkevin! / 1086378685 0 118 ` v–Ê__IMPORT_DESCRIPTOR_uffi__NULL_IMPORT_DESCRIPTORuffi_NULL_THUNK_DATA__imp__atol64_atol64/ 1086378685 0 128 ` v–Ê__IMPORT_DESCRIPTOR_uffi__NULL_IMPORT_DESCRIPTOR__imp__atol64_atol64uffi_NULL_THUNK_DATAuffi.dll/ 1086378685 0 483 ` L½ÒÀ@.debug$S?Œ@B.idata$2Ëß@0À.idata$6 ýß@ À uffi.dll(  Microsoft (R) LINK uffi.dll@comp.id ]ÿÿ.idata$2@Àh.idata$6.idata$4@Àh.idata$5@Àh6L__IMPORT_DESCRIPTOR_uffi__NULL_IMPORT_DESCRIPTORuffi_NULL_THUNK_DATA uffi.dll/ 1086378685 0 248 ` L½ÒÀ@·.debug$S?d@B.idata$3£@0À uffi.dll(  Microsoft (R) LINK@comp.id ]ÿÿ__NULL_IMPORT_DESCRIPTORuffi.dll/ 1086378685 0 273 ` L½ÒÀ@Ó.debug$S?Œ@B.idata$5Ë@0À.idata$4Ï@0À uffi.dll(  Microsoft (R) LINK@comp.id ]ÿÿuffi_NULL_THUNK_DATA uffi.dll/ 1086378685 0 37 ` ÿÿL½ÒÀ@_atol64uffi.dll cl-sql-6.4.1/uffi/ptrbits.c0000644000175000017500000000026210667176647014537 0ustar kevinkevin/* Prints the number of bits in a pointer. * Copyright (c) 2006 Kevin Rosenberg */ #include int main() { char *p; printf ("%d\n", 8*sizeof(p)); return (0); } cl-sql-6.4.1/uffi/Makefile.msvc0000644000175000017500000000154711335067642015305 0ustar kevinkevin# -*- Mode: Makefile -*- ########################################################################### # FILE IDENTIFICATION # # Name: Makefile.msvc # Purpose: Makefile for the CLSQL UFFI helper package (MSVC) # Author: Kevin M. Rosenberg # Created: Mar 2002 # # This file, part of CLSQL, is Copyright (c) 2002-2010 by Kevin M. Rosenberg # # CLSQL users are granted the rights to distribute and use this software # as governed by the terms of the Lisp Lesser GNU Public License # (http://opensource.franz.com/preamble.html), also known as the LLGPL. ########################################################################### BASE=clsql_uffi # Nothing to configure beyond here SRC=$(BASE).c OBJ=$(BASE).obj DLL=$(BASE).dll $(DLL): $(SRC) cl /MD /LD -D_MT /DWIN32=1 /D__LCC__=1 $(SRC) del $(OBJ) $(BASE).exp clean: del /q $(DLL) $(BASE).LIB cl-sql-6.4.1/uffi/clsql-uffi-package.lisp0000644000175000017500000000211011335067642017210 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; FILE IDENTIFICATION ;;;; ;;;; Name: clsql-uffi-package.cl ;;;; Purpose: Package definitions for common UFFI interface routines ;;;; Programmers: Kevin M. Rosenberg ;;;; Date Started: Mar 2002 ;;;; ;;;; This file, part of CLSQL, is Copyright (c) 2002-2010 by Kevin M. Rosenberg ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* (in-package #:cl-user) (defpackage #:clsql-uffi (:use #:cl #:uffi) (:export #:find-and-load-foreign-library #:canonicalize-type-list #:convert-raw-field #:atoi #:atol #:atof #:atol64 #:make-64-bit-integer #:make-128-bit-integer #:split-64-bit-integer) (:documentation "Common functions for interfaces using UFFI")) cl-sql-6.4.1/db-aodbc/0000755000175000017500000000000012134026703013360 5ustar kevinkevincl-sql-6.4.1/db-aodbc/aodbc-package.lisp0000644000175000017500000000211311335067642016720 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; FILE IDENTIFICATION ;;;; ;;;; Name: aodbc-package.cl ;;;; Purpose: Package definition for CLSQL AODBC backend ;;;; Programmer: Kevin M. Rosenberg ;;;; Date Started: Feb 2002 ;;;; ;;;; This file, part of CLSQL, is Copyright (c) 2002 by Kevin M. Rosenberg ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* (in-package #:cl-user) #+allegro (eval-when (:compile-toplevel :load-toplevel :execute) (require :aodbc-v2)) #-allegro (warn "This system requires Allegro's AODBC library to operate") (defpackage #:clsql-aodbc (:nicknames #:aodbc) (:use #:common-lisp #:clsql-sys) (:export #:aodbc-database) (:documentation "This is the CLSQL interface to Allegro's AODBC")) cl-sql-6.4.1/db-aodbc/Makefile0000644000175000017500000000011510667176647015043 0ustar kevinkevinSUBDIRS := include ../Makefile.common .PHONY: distclean distclean: clean cl-sql-6.4.1/db-aodbc/aodbc-sql.lisp0000644000175000017500000000711211335067642016130 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; FILE IDENTIFICATION ;;;; ;;;; Name: aodbc-sql.cl ;;;; Purpose: Low-level interface for CLSQL AODBC backend ;;;; Programmer: Kevin M. Rosenberg ;;;; Date Started: Feb 2002 ;;;; ;;;; This file, part of CLSQL, is Copyright (c) 2002 by Kevin M. Rosenberg ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* (in-package #:clsql-aodbc) ;; interface foreign library loading routines (defmethod clsql-sys:database-type-library-loaded ((database-type (eql :aodbc))) "T if foreign library was able to be loaded successfully. " (when (find-package :dbi) ;; finds Allegro's DBI (AODBC) package t)) (defmethod clsql-sys:database-type-load-foreign ((databae-type (eql :aodbc))) t) (when (find-package :dbi) (clsql-sys:database-type-load-foreign :aodbc)) ;; AODBC interface (defclass aodbc-database (generic-odbc-database) ((aodbc-db-type :accessor database-aodbc-db-type :initform :unknown))) (defmethod database-name-from-spec (connection-spec (database-type (eql :aodbc))) (check-connection-spec connection-spec database-type (dsn user password)) (destructuring-bind (dsn user password) connection-spec (declare (ignore password)) (concatenate 'string dsn "/" user))) (defmethod database-connect (connection-spec (database-type (eql :aodbc))) (check-connection-spec connection-spec database-type (dsn user password)) #+aodbc-v2 (destructuring-bind (dsn user password) connection-spec (handler-case (make-instance 'aodbc-database :name (database-name-from-spec connection-spec :aodbc) :database-type :aodbc :dbi-package (find-package '#:dbi) :odbc-conn (dbi:connect :user user :password password :data-source-name dsn)) (sql-error (e) (error e)) (error () ;; Init or Connect failed (error 'sql-connection-error :database-type database-type :connection-spec connection-spec :message "Connection failed"))))) (defmethod database-query (query-expression (database aodbc-database) result-types field-names) #+aodbc-v2 (handler-case (dbi:sql query-expression :db (clsql-sys::odbc-conn database) :types result-types :column-names field-names) #+ignore (error () (error 'sql-database-data-error :database database :expression query-expression :message "Query failed")))) (defmethod database-create (connection-spec (type (eql :aodbc))) (warn "Not implemented.")) (defmethod database-destroy (connection-spec (type (eql :aodbc))) (warn "Not implemented.")) (defmethod database-probe (connection-spec (type (eql :aodbc))) (warn "Not implemented.")) ;;; Backend capabilities (defmethod database-underlying-type ((database aodbc-database)) (database-aodbc-db-type database)) (defmethod db-backend-has-create/destroy-db? ((db-type (eql :aodbc))) nil) (defmethod database-initialize-database-type ((database-type (eql :aodbc))) t) (when (clsql-sys:database-type-library-loaded :aodbc) (clsql-sys:initialize-database-type :database-type :aodbc)) cl-sql-6.4.1/examples/0000755000175000017500000000000010667176647013571 5ustar kevinkevincl-sql-6.4.1/examples/clsql-tutorial.lisp0000644000175000017500000001374410667176647017452 0ustar kevinkevin(asdf:operate 'asdf:load-op 'clsql) (in-package #:clsql-user) ;; You must set these variables to appropriate values. (defvar *tutorial-database-type* nil "Possible values are :postgresql :postgresql-socket, :mysql, :oracle, :odbc, :aodbc or :sqlite") (defvar *tutorial-database-name* "clsqltut" "The name of the database we will work in.") (defvar *tutorial-database-user* "" "The name of the database user we will work as.") (defvar *tutorial-database-server* "" "The name of the database server if required") (defvar *tutorial-database-password* "" "The password if required") (clsql:def-view-class employee () ((emplid :db-kind :key :db-constraints :not-null :type integer :initarg :emplid) (first-name :accessor first-name :type (string 30) :initarg :first-name) (last-name :accessor last-name :type (string 30) :initarg :last-name) (email :accessor employee-email :type (string 100) :initarg :email) (companyid :type integer :initarg :companyid) (company :accessor employee-company :db-kind :join :db-info (:join-class company :home-key companyid :foreign-key companyid :set nil)) (managerid :type integer :initarg :managerid) (manager :accessor employee-manager :db-kind :join :db-info (:join-class employee :home-key managerid :foreign-key emplid :set nil))) (:base-table employee)) (clsql:def-view-class company () ((companyid :db-kind :key :db-constraints :not-null :type integer :initarg :companyid) (name :type (string 100) :initarg :name) (presidentid :type integer :initarg :presidentid) (president :reader president :db-kind :join :db-info (:join-class employee :home-key presidentid :foreign-key emplid :set nil)) (employees :reader company-employees :db-kind :join :db-info (:join-class employee :home-key companyid :foreign-key companyid :set t))) (:base-table company)) ;; Connect to the database (see the CLSQL documentation for vendor ;; specific connection specs). (case *tutorial-database-type* ((:mysql :postgresql :postgresql-socket) (clsql:connect `(,*tutorial-database-server* ,*tutorial-database-name* ,*tutorial-database-user* ,*tutorial-database-password*) :database-type *tutorial-database-type*)) ((:odbc :aodbc :oracle) (clsql:connect `(,*tutorial-database-name* ,*tutorial-database-user* ,*tutorial-database-password*) :database-type *tutorial-database-type*)) (:sqlite (clsql:connect `(,*tutorial-database-name*) :database-type *tutorial-database-type*))) ;; Record the sql going out, helps us learn what is going ;; on behind the scenes (clsql:start-sql-recording) ;; Create the tables for our view classes ;; First we drop them, ignoring any errors (ignore-errors (clsql:drop-view-from-class 'employee) (clsql:drop-view-from-class 'company)) (clsql:create-view-from-class 'employee) (clsql:create-view-from-class 'company) ;; Create some instances of our view classes (defvar company1 (make-instance 'company :companyid 1 :name "Widgets Inc." ;; Lenin is president of Widgets Inc. :presidentid 1)) (defvar employee1 (make-instance 'employee :emplid 1 :first-name "Vladamir" :last-name "Lenin" :email "lenin@soviet.org" :companyid 1)) (defvar employee2 (make-instance 'employee :emplid 2 :first-name "Josef" :last-name "Stalin" :email "stalin@soviet.org" :companyid 1 ;; Lenin manages Stalin (for now) :managerid 1)) (clsql:update-records-from-instance employee1) (clsql:update-records-from-instance employee2) (clsql:update-records-from-instance company1) ;; lets use the functional sql interface (clsql:locally-enable-sql-reader-syntax) (format t "The email address of ~A ~A is ~A" (first-name employee1) (last-name employee1) (employee-email employee1)) (setf (employee-email employee1) "lenin-nospam@soviets.org") ;; Update the database (clsql:update-records-from-instance employee1) (let ((new-lenin (car (clsql:select 'employee :where [= [slot-value 'employee 'emplid] 1] :flatp t)))) (format t "His new email is ~A" (employee-email new-lenin))) ;; Some queries ;; all employees (clsql:select 'employee) ;; all companies (clsql:select 'company) ;; employees named Lenin (clsql:select 'employee :where [= [slot-value 'employee 'last-name] "Lenin"]) (clsql:select 'company :where [= [slot-value 'company 'name] "Widgets Inc."]) ;; Employees of Widget's Inc. (clsql:select 'employee :where [and [= [slot-value 'employee 'companyid] [slot-value 'company 'companyid]] [= [slot-value 'company 'name] "Widgets Inc."]]) ;; Same thing, except that we are using the employee ;; relation in the company view class to do the join for us, ;; saving us the work of writing out the SQL! (company-employees company1) ;; President of Widgets Inc. (president company1) ;; Manager of Josef Stalin (employee-manager employee2) cl-sql-6.4.1/examples/sqlite3/0000755000175000017500000000000010667176647015155 5ustar kevinkevincl-sql-6.4.1/examples/sqlite3/init-func/0000755000175000017500000000000012134025332017020 5ustar kevinkevincl-sql-6.4.1/examples/sqlite3/init-func/Makefile0000644000175000017500000000142311335067642020474 0ustar kevinkevin#!/usr/bin/make ########################################################################## # FILE IDENTIFICATION # # Name: Makefile # Purpose: Makefile for SQLite 3 init function example. # Programer: Aurelio Bignoli # Date Started: Oct 2004 # # This file, part of CLSQL, is Copyright (c) 2004 by Aurelio Bignoli # # CLSQL users are granted the rights to distribute and use this software # as governed by the terms of the Lisp Lesser GNU Public License # (http://opensource.franz.com/preamble.html), also known as the LLGPL. ########################################################################## sqlite3-utils.so: iso-8859-15-coll.c Makefile gcc -c -fPIC iso-8859-15-coll.c -o iso-8859-15-coll.o gcc -shared iso-8859-15-coll.o -o sqlite3-utils.so -l sqlite3 cl-sql-6.4.1/examples/sqlite3/init-func/example.lisp0000644000175000017500000000562012134025332021347 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; FILE IDENTIFICATION ;;;; ;;;; Name: example.lisp ;;;; Purpose: Sample code for SQLite 3 initialization functions ;;;; Authors: Aurelio Bignoli ;;;; Created: Oct 2004 ;;;; ;;;; This file, part of CLSQL, is Copyright (c) 2004 by Aurelio Bignoli ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* ;;;; Load CLSQL. (asdf:oos 'asdf:load-op :clsql-sqlite3) ;;;; Load sqlite3-utils.so library. See Makefile for library creation. (unless (uffi:load-foreign-library "/usr/lib/clsql/sqlite3-utils.so" :module "sqlite3-utils" :supporting-libraries '("c")) (error "Unable to load foreign library")) ;;;; Define the foreign function to be used as init function. (uffi:def-function ("create_iso_8859_15_ci_collation" create-coll) ((db sqlite3:sqlite3-db)) :returning :int :module "sqlite3-utils") ;;;; Create the DB using create-coll as init function. (defparameter db-name "init-func-test.db") (clsql:destroy-database (list db-name) :database-type :sqlite3) (clsql:connect (list db-name #'create-coll) :database-type :sqlite3) ;;;; Create a table. Field f2 uses the newly defined collating ;;;; sequence. (clsql:execute-command "CREATE TABLE t1 (f1 CHAR(1), f2 CHAR(1) COLLATE ISO_8859_15_CI)") ;;;; Populate the table. (clsql:execute-command "INSERT INTO t1 VALUES ('à', 'à')") (clsql:execute-command "INSERT INTO t1 VALUES ('a', 'a')") (clsql:execute-command "INSERT INTO t1 VALUES ('A', 'A')") (clsql:execute-command "INSERT INTO t1 VALUES ('é', 'é')") (clsql:execute-command "INSERT INTO t1 VALUES ('e', 'e')") (clsql:execute-command "INSERT INTO t1 VALUES ('E', 'E')") (clsql:execute-command "INSERT INTO t1 VALUES ('ì', 'ì')") (clsql:execute-command "INSERT INTO t1 VALUES ('i', 'i')") (clsql:execute-command "INSERT INTO t1 VALUES ('I', 'I')") (clsql:execute-command "INSERT INTO t1 VALUES ('ò', 'ò')") (clsql:execute-command "INSERT INTO t1 VALUES ('o', 'o')") (clsql:execute-command "INSERT INTO t1 VALUES ('O', 'O')") (clsql:execute-command "INSERT INTO t1 VALUES ('ù', 'ù')") (clsql:execute-command "INSERT INTO t1 VALUES ('u', 'u')") (clsql:execute-command "INSERT INTO t1 VALUES ('U', 'U')") ;;;; Perform some SELECTs. (format t "~&SELECT * FROM t1 ==> ~A~%"(clsql:query "SELECT * FROM t1")) (format t "~&SELECT * FROM t1 ORDER BY f1 ==> ~A~%" (clsql:query "SELECT * FROM t1 ORDER BY f1")) (format t "~&SELECT * FROM t1 ORDER BY f2 ==> ~A~%" (clsql:query "SELECT * FROM t1 ORDER BY f2")) ;;;; Disconnect from database. (clsql:disconnect) cl-sql-6.4.1/examples/sqlite3/init-func/iso-8859-15-coll.c0000644000175000017500000000675411335067642021573 0ustar kevinkevin/**************************************************************************** * FILE IDENTIFICATION * * Name: iso-8859-15-coll.c * Purpose: SQLite 3 initialization function for * ISO-8859-15 collating sequence. * Programmer: Aurelio Bignoli * Date Started: Oct 2004 * * This file, part of CLSQL, is Copyright (c) 2004 by Aurelio Bignoli * * CLSQL users are granted the rights to distribute and use this software * as governed by the terms of the Lisp Lesser GNU Public License * (http://opensource.franz.com/preamble.html), also known as the LLGPL. ***************************************************************************/ /* Collating sequence name. CI = Case Insensitive */ #define ISO_8859_15_CI_NAME "ISO_8859_15_CI" /* Conversion table. */ const unsigned char iso_8859_15_ci [] = { /* 0 */ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, /* 1 */ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, /* 2 */ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, /* 3 */ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, /* 4 */ 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, /* 5 */ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, /* 6 */ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, /* 7 */ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F, /* 8 */ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x73, 0x8B, 0x6F, 0x8D, 0x7A, 0x79, /* 9 */ 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x73, 0x9B, 0x6F, 0x9D, 0x7A, 0x79, /* A */ 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0x73, 0xA7, 0x73, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, /* B */ 0xB0, 0xB1, 0xB2, 0xB3, 0x7A, 0xB5, 0xB6, 0xB7, 0x7A, 0xB9, 0xBA, 0xBB, 0x6F, 0xBD, 0x79, 0xBF, /* C */ 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x65, 0x63, 0x65, 0x65, 0x65, 0x65, 0x69, 0x69, 0x69, 0x69, /* D */ 0x64, 0x6E, 0x6F, 0x6F, 0x6F, 0x6F, 0x6F, 0xD7, 0x6F, 0x75, 0x75, 0x75, 0x75, 0x79, 0xDE, 0x73, /* E */ 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x65, 0x63, 0x65, 0x65, 0x65, 0x65, 0x69, 0x69, 0x69, 0x69, /* F */ 0x64, 0x6E, 0x6F, 0x6F, 0x6F, 0x6F, 0x6F, 0xF7, 0x6F, 0x75, 0x75, 0x75, 0x75, 0x79, 0xFE, 0x73 }; /* * A modified version of sqlite3StrNICmp in sqlite/src/util.c */ int iso_8859_15_ci_StrCmp(const char *zLeft, const char *zRight, int N){ register unsigned char *a, *b; a = (unsigned char *)zLeft; b = (unsigned char *)zRight; while( N-- > 0 && *a!=0 && iso_8859_15_ci[*a]==iso_8859_15_ci[*b]){ a++; b++; } return N<0 ? 0 : iso_8859_15_ci[*a] - iso_8859_15_ci[*b]; } /* * A modified version of nocaseCollatinFunc in sqlite/src/main.c. */ int iso_8859_15_ci_CollatingFunc( void *NotUsed, int nKey1, const void *pKey1, int nKey2, const void *pKey2 ){ int r = iso_8859_15_ci_StrCmp( (const char *)pKey1, (const char *)pKey2, (nKey1 $LISP_CMD_FILE ALLEGRO=mlisp if [ "`which $ALLEGRO`" ]; then $ALLEGRO -q -L $LISP_CMD_FILE fi CMUCL=lisp if [ "`which $CMUCL`" ]; then $CMUCL -init $LISP_CMD_FILE fi LISPWORKS=lw-console #if [ "`which $LISPWORKS`" ]; then $LISPWORKS -init $LISP_CMD_FILE #fi OPENCML=openmcl #if [ "`which $OPENMCL`" ]; then $OPENMCL -init $LISP_CMD_FILE #fi SBCL=sbcl if [ "`which $SBCL`" ]; then $SBCL --noinform --disable-debugger --userinit $LISP_CMD_FILE fi if [ -s $SEXP_REPORT_FILE ]; then echo "$SUMMARY_CMD" | $SBCL fi #rm -rf $LISP_CMD_FILE cl-sql-6.4.1/examples/dot.clsql-test.config0000644000175000017500000000100210667176647017631 0ustar kevinkevin;; -*- Mode: Lisp -*- ;; Emacs mode line ;; ;; Example CLSQL test configuration file ;; Since this file is read by Lisp, it is okay to use ;; comments in this file ;; This file should be named .clsql-test.config and ;; placed in your home directory ((:mysql ("localhost" "a-mysql-db" "user1" "secret")) (:aodbc ("my-dsn" "a-user" "pass")) (:postgresql ("localhost" "another-db" "user2" "dont-tell")) (:postgresql-socket ("pg-server" "a-db-name" "user" "secret-password")) (:sqlite ("path-to-sqlite-db"))) cl-sql-6.4.1/clsql-mysql.asd0000644000175000017500000000702011577723152014712 0ustar kevinkevin;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*- ;;;; ************************************************************************* ;;;; FILE IDENTIFICATION ;;;; ;;;; Name: clsql-mysql.asd ;;;; Purpose: ASDF definition file for CLSQL MySQL backend ;;;; Programmer: Kevin M. Rosenberg ;;;; Date Started: Aug 2002 ;;;; ;;;; This file, part of CLSQL, is Copyright (c) 2002-2010 by Kevin M. Rosenberg ;;;; ;;;; CLSQL users are granted the rights to distribute and use this software ;;;; as governed by the terms of the Lisp Lesser GNU Public License ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL. ;;;; ************************************************************************* (defpackage #:clsql-mysql-system (:use #:asdf #:cl)) (in-package #:clsql-mysql-system) (eval-when (:compile-toplevel :load-toplevel :execute) (unless (find-package 'uffi) (asdf:operate 'asdf:load-op 'uffi))) (defvar *library-file-dir* (merge-pathnames "db-mysql/" (make-pathname :name nil :type nil :defaults *load-truename*))) (defclass clsql-mysql-source-file (c-source-file) ()) (defmethod output-files ((o compile-op) (c clsql-mysql-source-file)) (let* ((library-file-type (funcall (intern (symbol-name'#:default-foreign-library-type) (symbol-name '#:uffi)))) (found (some #'(lambda (dir) (probe-file (make-pathname :directory dir :name (component-name c) :type library-file-type))) '((:absolute "usr" "lib" "clsql"))))) (list (if found found (make-pathname :name (component-name c) :type library-file-type :defaults *library-file-dir*))))) (defmethod perform ((o load-op) (c clsql-mysql-source-file)) t) (defmethod operation-done-p ((o load-op) (c clsql-mysql-source-file)) (and (find-package '#:mysql) (symbol-function (intern (symbol-name '#:mysql-get-client-info) (find-package '#:mysql))) t)) (defmethod perform ((o compile-op) (c clsql-mysql-source-file)) (unless (operation-done-p o c) #-(or win32 win64 windows mswindows) (unless (zerop (run-shell-command #-freebsd "cd ~A; make" #+freebsd "cd ~A; gmake" (namestring *library-file-dir*))) (error 'operation-error :component c :operation o)))) (defmethod operation-done-p ((o compile-op) (c clsql-mysql-source-file)) (or (and (probe-file #p"/usr/lib/clsql/clsql_mysql.so") t) (let ((lib (make-pathname :defaults (component-pathname c) :type (uffi:default-foreign-library-type)))) (and (probe-file lib) (probe-file (component-pathname c)) (> (file-write-date lib) (file-write-date (component-pathname c))))))) ;;; System definition (defsystem :clsql-mysql :name "cl-sql-mysql" :author "Kevin M. Rosenberg " :maintainer "Kevin M. Rosenberg " :licence "Lessor Lisp General Public License" :description "Common Lisp SQL MySQL Driver" :long-description "cl-sql-mysql package provides a database driver to the MySQL database system." :depends-on (clsql clsql-uffi) :components ((:module :db-mysql :components ((:file "mysql-package") (:clsql-mysql-source-file "clsql_mysql" :depends-on ("mysql-package")) (:file "mysql-loader" :depends-on ("mysql-package" "clsql_mysql")) (:file "mysql-client-info" :depends-on ("mysql-loader")) (:file "mysql-api" :depends-on ("mysql-client-info")) (:file "mysql-sql" :depends-on ("mysql-api")) (:file "mysql-objects" :depends-on ("mysql-sql"))))))