Ignore:
Timestamp:
10/03/2007 05:21:21 PM (19 years ago)
Author:
David Owen <dsowen@…>
branch-nick:
xbase
revision id:
dsowen@fugue88.ws-20071003172121-56qbaz5sxe3k71ys
Message:

Now exports SQL do insert data.
Makefile creates executable.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • version/0.1/xbase.lisp

    r3 r4  
     1(require '#:asdf)
     2(require '#:cl-ppcre)
     3
     4(use-package '#:cl-ppcre)
     5
     6
     7
    18;;; Fairly generic file-reading stuff.
    29
     
    130137     ,@(mapcar #'slot-from-field descs)))
    131138
     139(defstruct dbf-desc
     140  name
     141  filename
     142  sql-create)
     143
     144(defvar *dbfs* (make-hash-table :test 'eq))
     145
     146(defun sql-escape-fieldname (name)
     147  (let ((name (string-downcase name)))
     148    (if (member name '("user") :test 'equal)
     149        (concatenate 'string "\"" name "\"")
     150        name)))
     151
     152(defun sql-escape-data (value)
     153  (if (string= value "")
     154      "null"
     155      (format nil "'~A'" (cl-ppcre:regex-replace-all "'" value "''"))))
     156
    132157(defun sql-column (desc)
    133158  (with-slots (name type size precision) desc
    134159    (format nil "~A ~A"
    135             name
     160            (sql-escape-fieldname name)
    136161            (cond
    137162              ((string= type "C")
     
    156181          (mapcar 'sql-column descs)))
    157182
    158 (defstruct dbf-desc
    159   name
    160   filename
    161   sql-create)
    162 
    163 (defvar *dbfs* (make-hash-table :test 'eq))
     183(defun make-sql-function (type name descs)
     184  `(defmethod sql-insert ((obj ,type))
     185     (format
     186      nil
     187      ,(format nil "INSERT INTO ~A(~{~A~@{,~A~}~}) VALUES(~{~A~@{,~A~}~})"
     188               name
     189               (mapcar (lambda (desc)
     190                         (sql-escape-fieldname (field-desc-name desc)))
     191                       descs)
     192               (mapcar (lambda (d)
     193                         (declare (ignore d))
     194                         "~A")
     195                       descs))
     196      ,@(mapcar (lambda (desc)
     197                  `(sql-escape-data
     198                    (slot-value obj ',(intern (field-desc-name desc)))))
     199                descs))))
    164200
    165201(defmacro define-dbf-struct (name filename)
     
    170206                            :filename ,filename
    171207                            :sql-create ,(sql-create name descs)))
    172        ,(struct-from-field-descs name descs))))
     208       ,(struct-from-field-descs name descs)
     209       ,(make-sql-function name name descs))))
    173210
    174211
     
    193230(define-dbf-struct phone "/home/dsowen/scott/local/bent-data/bentphon.dbf")
    194231(define-dbf-struct tenent-change "/home/dsowen/scott/local/bent-data/benttchg.dbf")
     232
     233
     234
     235(defun import-dbf (filename table-name)
     236  "Reads the DBF file, analyzing meta-data to create Lisp structures,
     237populating those structures, and constructing descriptive SQL."
     238  (let ((field-descs (nth-value 1 (read-dbf-structure filename))))
     239    (setf (gethash 'import-struct *dbfs*)
     240          (make-dbf-desc :name 'import-struct
     241                         :filename filename
     242                         :sql-create (sql-create table-name field-descs)))
     243    (eval (struct-from-field-descs 'import-struct field-descs))
     244    (eval (make-sql-function 'import-struct table-name field-descs))
     245    (read-dbf 'import-struct)))
     246
     247(defun split-name (filename)
     248  (unless (pathnamep filename)
     249    (setf filename (pathname filename)))
     250  (let ((name (pathname-name filename)))
     251    (values (subseq name 0 4)
     252            (subseq name 4))))
     253
     254(defun do-dbf (filename)
     255  (multiple-value-bind (db-name table-name) (split-name filename)
     256    (let ((recs (import-dbf filename table-name)))
     257      (format t "~A;~%~%~%~%"
     258              (slot-value (gethash 'import-struct *dbfs*) 'sql-create))
     259      (dolist (rec recs)
     260        (format t "~A;~%~%" (sql-insert rec))))))
     261
     262(defun main ()
     263  (when (/= (length *posix-argv*) 2)
     264    (format *error-output* "Usage: xbase dbf-file~%")
     265    (quit))
     266  (do-dbf (second *posix-argv*))
     267  (quit))
Note: See TracChangeset for help on using the changeset viewer.