From: fireblade
Subject: How to handle database errors via condition system?
Date: 
Message-ID: <1181550807.477725.308160@p47g2000hsd.googlegroups.com>
How would you  implement account-exists-p with condition system
included that should return:
1. values t & nil   if  account exists
2. values nil & nil if account doesn't exists and finally
3. values "Database error."  & t  if *any-kind* od database error
occured.
The program execution should continue, no crushing into  debugger.

Naive version looks like this:
(defun account-exists-p (account)
  (if   (query [SELECT [*]  :FROM [chart_of_accounts]
                                           :WHERE [= [account]
account]])
        t))

Slobodan Blazeski

From: Richard M Kreuter
Subject: Re: How to handle database errors via condition system?
Date: 
Message-ID: <87ps42fv59.fsf@tan-ru.localdomain>
fireblade <·················@gmail.com> writes:

> How would you  implement account-exists-p with condition system
> included that should return:
> 1. values t & nil   if  account exists
> 2. values nil & nil if account doesn't exists and finally
> 3. values "Database error."  & t  if *any-kind* od database error
> occured.
> The program execution should continue, no crushing into  debugger.

Hiding the condition system isn't the right way to avoid getting into
the debugger. If you want to avoid the debugger, see *DEBUGGER-HOOK*.

> Naive version looks like this:
> (defun account-exists-p (account)
>   (if   (query [SELECT [*]  :FROM [chart_of_accounts]
>                                            :WHERE [= [account]
> account]])
>         t))

In the limit case, you can wrap the database query in an IGNORE-ERRORS
and then investigate the values returned:

(multiple-value-bind (tuples error)
    (ignore-errors (query ...))
  (cond ((typep error error) ;Some kind of db error
	 (values "Database error." t))
	((not (null tuples)) ;There's a tuple satisfying the query
	 (values t nil))
	(t                   ;No tuple, no error
	 (values nil nil))))

However, I would recommend changing your specifiation so that it does
just what IGNORE-ERRORS does: return the values and NIL for normal
calls, NIL and a condition for exceptions.  This way, if a caller does
eventually want to know what kind of error transpired, the information
will be available.

--
RmK
From: fireblade
Subject: Re: How to handle database errors via condition system?
Date: 
Message-ID: <1181636057.124411.155950@z28g2000prd.googlegroups.com>
On Jun 11, 4:00 pm, Richard M Kreuter <·······@progn.net> wrote:
> fireblade<·················@gmail.com> writes:
> > How would you  implement account-exists-p with condition system
> > included that should return:
> > 1. values t & nil   if  account exists
> > 2. values nil & nil if account doesn't exists and finally
> > 3. values "Database error."  & t  if *any-kind* od database error
> > occured.
> > The program execution should continue, no crushing into  debugger.
>
> Hiding the condition system isn't the right way to avoid getting into
> the debugger. If you want to avoid the debugger, see *DEBUGGER-HOOK*.
>
> > Naive version looks like this:
> > (defun account-exists-p (account)
> >   (if   (query [SELECT [*]  :FROM [chart_of_accounts]
> >                                            :WHERE [= [account]
> > account]])
> >         t))
>
> In the limit case, you can wrap the database query in an IGNORE-ERRORS
> and then investigate the values returned:
>
> (multiple-value-bind (tuples error)
>     (ignore-errors (query ...))
>   (cond ((typep error error) ;Some kind of db error
>          (values "Database error." t))
>         ((not (null tuples)) ;There's a tuple satisfying the query
>          (values t nil))
>         (t                   ;No tuple, no error
>          (values nil nil))))
>
> However, I would recommend changing your specifiation so that it does
> just what IGNORE-ERRORS does: return the values and NIL for normal
> calls, NIL and a condition for exceptions.  This way, if a caller does
> eventually want to know what kind of error transpired, the information
> will be available.
>
> --
> RmK

I took your advice and implemented like this :

(defun tuple-exist-p ( table key-name key-value quoted)
  (multiple-value-bind (tuples error)
      (ignore-errors
        (query
         (string+
          "select " key-name  " from " table
          " where " key-name " = " (need-qt quoted key-
value))))
    (cond ((typep error 'error) ;Some kind of db error
         (values nil "Database error occured"))
        ((null tuples) ;No  tuple satisfying the query
         (values nil nil))
        (t                   ;There's a tuple, no error
         (values t nil)))))

And all verifiers are build using above function like:

(defun account-exist-p (account)
  (tuple-exist-p "chart_of_accounts" "account" account t))
....

Thank you

Slobodan Blazeski
From: sross
Subject: Re: How to handle database errors via condition system?
Date: 
Message-ID: <1181642701.547424.159520@x35g2000prf.googlegroups.com>
On Jun 12, 9:14 am, fireblade <·················@gmail.com> wrote:
> On Jun 11, 4:00 pm, Richard M Kreuter <·······@progn.net> wrote:
>
>
>
> > fireblade<·················@gmail.com> writes:
> > > How would you  implement account-exists-p with condition system
> > > included that should return:
> > > 1. values t & nil   if  account exists
> > > 2. values nil & nil if account doesn't exists and finally
> > > 3. values "Database error."  & t  if *any-kind* od database error
> > > occured.
> > > The program execution should continue, no crushing into  debugger.
>
> > Hiding the condition system isn't the right way to avoid getting into
> > the debugger. If you want to avoid the debugger, see *DEBUGGER-HOOK*.
>
> > > Naive version looks like this:
> > > (defun account-exists-p (account)
> > >   (if   (query [SELECT [*]  :FROM [chart_of_accounts]
> > >                                            :WHERE [= [account]
> > > account]])
> > >         t))
>
> > In the limit case, you can wrap the database query in an IGNORE-ERRORS
> > and then investigate the values returned:
>
> > (multiple-value-bind (tuples error)
> >     (ignore-errors (query ...))
> >   (cond ((typep error error) ;Some kind of db error
> >          (values "Database error." t))
> >         ((not (null tuples)) ;There's a tuple satisfying the query
> >          (values t nil))
> >         (t                   ;No tuple, no error
> >          (values nil nil))))
>
> > However, I would recommend changing your specifiation so that it does
> > just what IGNORE-ERRORS does: return the values and NIL for normal
> > calls, NIL and a condition for exceptions.  This way, if a caller does
> > eventually want to know what kind of error transpired, the information
> > will be available.
>
> > --
> > RmK
>
> I took your advice and implemented like this :
>
> (defun tuple-exist-p ( table key-name key-value quoted)
>   (multiple-value-bind (tuples error)
>       (ignore-errors
>         (query
>          (string+
>           "select " key-name  " from " table
>           " where " key-name " = " (need-qt quoted key-
> value))))
>     (cond ((typep error 'error) ;Some kind of db error
>          (values nil "Database error occured"))
>         ((null tuples) ;No  tuple satisfying the query
>          (values nil nil))
>         (t                   ;There's a tuple, no error
>          (values t nil)))))

I think it needs to be pointed out the body of this function is
effectively no different to :

(multiple-value-bind (tuples error)
    (ignore-errors (query <build-query>))
  (values tuples error))

well, no different  provided you are fine with returning the condition
rather than some string and the tuple instead of t (generalized
booleans are a good thing).
I'd would also recommend handling a particular condition rather
than using the rather heavy handed ignore-errors.

(defun tuple-exist-p (table key-name key-value quoted)
  (handler-case (values (query <build query>) nil)
    (db-error (c) (values nil c)))) ;change the error name to suit

Sean.
From: fireblade
Subject: Re: How to handle database errors via condition system?
Date: 
Message-ID: <1181653721.545583.241850@r19g2000prf.googlegroups.com>
On Jun 12, 12:05 pm, sross <······@gmail.com> wrote:
> On Jun 12, 9:14 am, fireblade <·················@gmail.com> wrote:
>
>
>
>
>
> > On Jun 11, 4:00 pm, Richard M Kreuter <·······@progn.net> wrote:
>
> > > fireblade<·················@gmail.com> writes:
> > > > How would you  implement account-exists-p with condition system
> > > > included that should return:
> > > > 1. values t & nil   if  account exists
> > > > 2. values nil & nil if account doesn't exists and finally
> > > > 3. values "Database error."  & t  if *any-kind* od database error
> > > > occured.
> > > > The program execution should continue, no crushing into  debugger.
>
> > > Hiding the condition system isn't the right way to avoid getting into
> > > the debugger. If you want to avoid the debugger, see *DEBUGGER-HOOK*.
>
> > > > Naive version looks like this:
> > > > (defun account-exists-p (account)
> > > >   (if   (query [SELECT [*]  :FROM [chart_of_accounts]
> > > >                                            :WHERE [= [account]
> > > > account]])
> > > >         t))
>
> > > In the limit case, you can wrap the database query in an IGNORE-ERRORS
> > > and then investigate the values returned:
>
> > > (multiple-value-bind (tuples error)
> > >     (ignore-errors (query ...))
> > >   (cond ((typep error error) ;Some kind of db error
> > >          (values "Database error." t))
> > >         ((not (null tuples)) ;There's a tuple satisfying the query
> > >          (values t nil))
> > >         (t                   ;No tuple, no error
> > >          (values nil nil))))
>
> > > However, I would recommend changing your specifiation so that it does
> > > just what IGNORE-ERRORS does: return the values and NIL for normal
> > > calls, NIL and a condition for exceptions.  This way, if a caller does
> > > eventually want to know what kind of error transpired, the information
> > > will be available.
>
> > > --
> > > RmK
>
> > I took your advice and implemented like this :
>
> > (defun tuple-exist-p ( table key-name key-value quoted)
> >   (multiple-value-bind (tuples error)
> >       (ignore-errors
> >         (query
> >          (string+
> >           "select " key-name  " from " table
> >           " where " key-name " = " (need-qt quoted key-
> > value))))
> >     (cond ((typep error 'error) ;Some kind of db error
> >          (values nil "Database error occured"))
> >         ((null tuples) ;No  tuple satisfying the query
> >          (values nil nil))
> >         (t                   ;There's a tuple, no error
> >          (values t nil)))))
>
> I think it needs to be pointed out the body of this function is
> effectively no different to :
>
> (multiple-value-bind (tuples error)
>     (ignore-errors (query <build-query>))
>   (values tuples error))
>
> well, no different  provided you are fine with returning the condition
> rather than some string and the tuple instead of t (generalized
> booleans are a good thing).
> I'd would also recommend handling a particular condition rather
> than using the rather heavy handed ignore-errors.
>
> (defun tuple-exist-p (table key-name key-value quoted)
>   (handler-case (values (query <build query>) nil)
>     (db-error (c) (values nil c)))) ;change the error name to suit
>
> Sean.- Hide quoted text -
>
> - Show quoted text -

The meaning why I use a simple return string is because that's the
only thing I want user to see when there's some database related
error. Probably the handler case would be better but I don't have  a
time nor energy to learn lisp condition system right now.