From: Bill Atkins
Subject: Re: Common Lisp ORM
Date: 
Message-ID: <87r73wr86d.fsf@rpi.edu>
···············@gmail.com" <··············@gmail.com> writes:

> Hi, folks.
>
> Anybody know about some projects for creation dynamic ORM, like
> ActiveRecord, for Common Lisp?
> (I know about CL-SQL, but it is low level).

CLSQL isn't _that_ low-level.  Have you read up on DEF-VIEW-CLASS?
It's pretty straightforward to use once you get used to it.  It's no
more low-level than ActiveRecord, except that fields must be
explicitly specified instead of getting pulled from the schema - this
is IMO a better way to go about it.

CLSQL has the added advantage that you can develop your schema from
within CLSQL by defining a view class and then asking CLSQL to create
a table based on your class specification.  It's really quite handy.

Here is some sample code showing off the ORM parts of CLSQL, loosely
based on a project I just did:

;; define the columns in the table
(def-view-class user ()
  ((id
    :accessor id
    :initarg :id
    :type integer
    :db-type "serial"
    :db-kind :key)
   (username
    :accessor username
    :initarg :username
    :type string)
   (password-hash
    :accessor password-hash
    :initarg :password-hash
    :type string
    :column password_hash))
  (:base-table users))


;; add a record to the database
(update-records-from-instance
        (make-instance 'user
		       :id 1
		       :username "foo"
		       :password-hash (hash-login-information "foo" "foobar"))))

;; select the user with ID 1 and set his username column to joe
(let ((user (first (select 'user :where [= [id] 1] :flatp t :refresh t))))
  (setf (username user) "joe")
  (update-records-from-instance user))  

;; drop the table associated with the user class and then rebuild it
;; based on the information provided in the DEF-VIEW-CLASS.
(drop-view-from-class 'user) 
(create-view-from-class 'user)

From: ··············@gmail.com
Subject: Re: Common Lisp ORM
Date: 
Message-ID: <1145264057.870495.64760@u72g2000cwu.googlegroups.com>
I knew about this, and I using CL-SQL, but i want somthing like this:
(defORM category ()
  (tree)
  (has-many :products)
  (scheme
   (text-field :name "name" :size 25)
   (date)
   (clsql
    ;; CL-SQL additional scheme
    )))

I am started to write  wrapper around CL-SQL to achiev this. But i want
to know is someone already written somthing like this.
From: Bill Atkins
Subject: Re: Common Lisp ORM
Date: 
Message-ID: <87vet82wo3.fsf@rpi.edu>
···············@gmail.com" <··············@gmail.com> writes:

> I knew about this, and I using CL-SQL, but i want somthing like this:
> (defORM category ()
>   (tree)
>   (has-many :products)
>   (scheme
>    (text-field :name "name" :size 25)
>    (date)
>    (clsql
>     ;; CL-SQL additional scheme
>     )))
>
> I am started to write  wrapper around CL-SQL to achiev this. But i want
> to know is someone already written somthing like this.

Fair enough.  But that macro could probably be written in more
idiomatic common Lisp like so:

  (def-table-class category ()
      ((name :type :text :size 25)
       (date :type :date))
    (:tree t) ;; maybe there's a more descriptive name for this
    (:has-many products))

since macros that resemble classes tend to have an interface that
resembles DEFCLASS.  If you use the metaobject protocol, you
could even define this without a custom macro:

  (defclass category ()
      ((name :type :text :size 25)
       (date :type :date))
    (:metaclass mapped-to-table)
    (:tree t)
    (:has-many products))
From: CrazyPit
Subject: Re: Common Lisp ORM
Date: 
Message-ID: <1145282209.882238.213790@i39g2000cwa.googlegroups.com>
Thanks for remarks.
From: sross
Subject: Re: Common Lisp ORM
Date: 
Message-ID: <1145361875.103690.128860@t31g2000cwb.googlegroups.com>
I've got an almost working additional metaclass for clsql called
active-db-class which does the active record thing of automatically
adding slots and handling various join options eg.

(defclass category ()
  ()
  (:metaclass active-db-class))

Eventually it should migrate to something like

(defclass category ()
  ((:has-many products)) ;; and other slots
  (:metaclass active-db-class))

It's not quite finished yet but if anyone wants to see its
current state then drop me a line and I'll mail it to you.
From: CrazyPit
Subject: Re: Common Lisp ORM
Date: 
Message-ID: <1145439798.026485.165280@j33g2000cwa.googlegroups.com>
This is cool! Can you mail me(crazypit13 ((AT)) gmail ((dot)) com) you
source, also if you interested in it we can start project on
common-lisp.net .
From: Bill Atkins
Subject: Re: Common Lisp ORM
Date: 
Message-ID: <87lku42v2h.fsf@rpi.edu>
···············@gmail.com" <··············@gmail.com> writes:

> I knew about this, and I using CL-SQL, but i want somthing like this:
> (defORM category ()
>   (tree)
>   (has-many :products)
>   (scheme
>    (text-field :name "name" :size 25)
>    (date)
>    (clsql
>     ;; CL-SQL additional scheme
>     )))
>
> I am started to write  wrapper around CL-SQL to achiev this. But i want
> to know is someone already written somthing like this.

Are you also aware of the join features of CLSQL?  You can get the
equivalent of (tree) by just joining CATEGORY to itself, if (tree)
means what I think it means.  And has-many simply involves joining
CATEGORY to products with the :set option turned on.  If the interface
to DEF-VIEW-CLASS truly bothers you, you can make your custom macro
just expand into a DEF-VIEW-CLASS form with the appropriate joins.  It
shouldn't have to be very complicated at all.
From: CrazyPit
Subject: Re: Common Lisp ORM
Date: 
Message-ID: <1145282491.464084.122920@e56g2000cwe.googlegroups.com>
>  If the interface to DEF-VIEW-CLASS truly bothers you, you can make your custom macro
just expand into a DEF-VIEW-CLASS form with the appropriate joins.  It
shouldn't have to be very complicated at all.

Yes i will do it in that way.

 (defORM category ()
  (tree)
  (has_many :products)
  (scheme
   (text-field :name "name" :size 25)
   (date)))

expands  to
(clsql:def-view-class category (cl-true-orm:tree) ;; (tree)
  (;;; STANDART
   (id
    :accessor id
    :db-kind :key
    :db-constraints (:not-null :auto-increment) ;; for mysql
    :type integer
    :initarg :id)
   ;; (tree)
   (parent-id
    :accessor parent-id
    :type integer
    :initarg :parent-id)
   (parent
    :accessor parent
    :db-kind :join
    :db-info (:join-class category
                  :home-key parent-id
	          :foreign-key id
	          :set nil))
   (children
    :accessor children
    :db-kind :join
    :db-info (:join-class category
	      :home-key id
	      :foreign-key parent-id
	      :set t))
   ;; (has_many :products)
   (products
    :accessor products
    :db-kind :join
    :db-info (:join-class product
	      :home-key id
	      :foreign-key category-id))