[Cl-perec-devel] Lots of questions :-)

Mihai Bazon mihai at bazon.net
Mon Sep 14 10:01:21 UTC 2009


Hi Attila,

Thanks for your fast reply!

Indeed, I knew about pinterface series, it helped a lot to get started.
I tried defining my own type today and after some embarrassing amount of
trial and error I came up with this:

(cl-perec:defptype password ()
  '(text 128))

(cl-perec::defmapping password (cl-rdbms::sql-character-varying-type :size 128)
  'cl-perec:identity-reader             ; unexported
  'password-writer)

(defun password-writer (val rdbms-values index)
  (setf (elt rdbms-values index)
        (ironclad:byte-array-to-hex-string
         (ironclad:digest-sequence :sha1 (babel:string-to-octets val)))))

(pushnew 'password cl-perec::*canonical-types*)
(pushnew 'password cl-perec::*mapped-type-precedence-list*)

It works, it creates SHA1 automatically for password fields, but there's
one weird side effect: now *all* columns of a TEXT type are
VARCHAR(128), and they are all mangled to SHA1. :-) Could you point out
what did I do wrong?

Cheers,
-Mihai

Attila Lendvai <attila.lendvai at gmail.com> wrote:
> hi!
> 
> loads of useful information is available here:
> 
> http://lichteblau.blogspot.com/2009/08/cl-perec-blog-series-by-pinterface.html
> 
> 
> > 1. I'm defining my own DB package in which I :USE :CL-PEREC.  This
> >   introduces some conflicts that can be mitigated by
> >   :shadowing-import-from :cl-perec :set :time.  What is the recommended
> >   way, though?  Would it be better if I don't :USE :cl-perec and prefix
> >   all names with "cl-perec:"?
> 
> 
> these are usual CL namespace (package) issues. using
> :shadowing-import-from is the right way, unless you want to do more
> magic...
> 
> 
> > 2. I have a (defpclass* page) which shows the following warning in SBCL:
> >
> >   ; caught STYLE-WARNING:
> >   ;   defclass* for CL-PEREC:PAGE while its home package is not *package* (#<PACKAGE "DLWEB.DB">)
> >
> >   I can guess that there's a class named "page" in cl-perec?
> 
> 
> not a class, but an exported symbol. defclass* interns some symbols,
> and it's warning you that you are defining a class called
> cl-perec:page while you are in another package. this _may_ lead to
> problems (symbols interned into cl-perec instead of your package
> causing some clashes, redefinitions, etc)
> 
> if you want to be tidy then you should (:shadow #:page) in your package.
> 
> 
> > 3. OIDs seem to be randomly generated.  Are they generated by cl-perec,
> >   or by Postgres itself? (I haven't use PG in many years so sorry if
> >   it's PG-related).
> 
> 
> oid's encode both the class and the identity of persistent objects,
> that's why the oid's seem to be random. first n bits are the class,
> last k bits are the identity.
> 
> 
> > 4. I have a Perl background and have used various DB-to-Object mappers
> >   (and even wrote my own).  Most of them, in Perl, provide an easy way
> >   to "inflate/deflate" columns.  For example, if a column is of type
> >   TIMESTAMP (which the DB server returns as a string), when an instance
> >   is retrieved I can make that slot return an object of type DateTime,
> >   which is more comfortable to work with.  So in other words, an
> >   automatic conversion happens when a row is fetched from the DB, and
> >   the reverse conversion when it's stored into DB.
> >
> >   Another example is storing hashed passwords in the DB.  In Perl I
> >   would do:
> >
> >      $user->password("foobar");
> >      $user->update;
> >      ## and now $user->password is some MD5 of "foobar"
> >
> >   Is there a way to do this with cl-perec?
> 
> 
> i think that's how perec works... just look at the predefined
> timestamp type, it returns localtime:timestamp instances.
> 
> you can define your own persistent types, see the blog entries above,
> or look at the standard-type.lisp in perec (which should be plural,
> standard-types.lisp, but someone else needs to convince Levy, i've
> tried already... :)
> 
> 
> > 5. I plan to use cl-perec with hunchentoot for creating sites.  One of
> >   the things I commonly did in Perl was to use the same code (and
> >   server) for multiple websites; because they had different data, the
> >   database connection was selected at runtime, depending on the target
> >   domain name of the incoming request.  I presume a way to do this in
> >   cl-perec would be to set the value of *database* accordingly on each
> >   request, but since Hunchentoot is multithreaded, would this be safe?
> >   If not, can you recommend a better way?
> 
> 
> you should never set these contextual variables when working with
> multiple threads, but bind them at a high enough point:
> 
> (defmethod handle-request :around ((x some-of-my-stuff))
>   (let ((*database* *my-database*))
>   ....)))
> 
> this will introduce a new separate thread-local binding of the special
> variable in each thread when they get to that point.
> 
> btw, we will start a website Real Soon Now (weeks at most) that will
> demo our web architecture, including a detailed shell script that can
> reproduce that site locally on your machine and start it up.
> 
> 
> > 7. How do I define columns of type VARCHAR(255)?  It seems wasteful to
> >   use TEXT for every string..
> 
> (text 255)
> 
> hth, and good luck with perec!
> 
> -- 
>  attila



More information about the cl-perec-devel mailing list