Automated commit for debian release 6.7.2-1
[clsql.git] / sql / sequences.lisp
1 ;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*-
2 ;;;; *************************************************************************
3 ;;;;
4 ;;;; Generic sequence implementation. Backends should use native sequences if
5 ;;;; are available.
6 ;;;;
7 ;;;; This file is part of CLSQL.
8 ;;;;
9 ;;;; CLSQL users are granted the rights to distribute and use this software
10 ;;;; as governed by the terms of the Lisp Lesser GNU Public License
11 ;;;; (http://opensource.franz.com/preamble.html), also known as the LLGPL.
12 ;;;; *************************************************************************
13
14 (in-package #:clsql-sys)
15
16 (defclass generic-database (database)
17   ()
18   (:documentation "Encapsulate same behavior across backends."))
19
20
21 ;;; Sequence functions
22
23 (defvar *old-sequence-names* nil
24   "Should CLSQL use its old sequence naming scheme _CLSQL_SEQ_{table} instead
25    of the current scheme {table}_CLSQL_SEQ")
26
27 (defun %sequence-name-to-table (sequence-name database)
28   (escaped
29    (combine-database-identifiers
30     (if *old-sequence-names*
31         (list '_CLSQL_SEQ sequence-name)
32         (list sequence-name 'CLSQL_SEQ))
33     database)))
34
35 (defmethod database-create-sequence (sequence-name database)
36   (let ((table-name (%sequence-name-to-table sequence-name database)))
37     (database-execute-command
38      (concatenate 'string "CREATE TABLE " table-name
39                   " (last_value int NOT NULL PRIMARY KEY, increment_by int, min_value int, is_called char(1))")
40      database)
41     (database-execute-command
42      (concatenate 'string "INSERT INTO " table-name
43                   " VALUES (1,1,1,'f')")
44      database)))
45
46 (defmethod database-drop-sequence (sequence-name database)
47   (database-execute-command
48    (concatenate 'string "DROP TABLE " (%sequence-name-to-table sequence-name database))
49    database))
50
51 (defun %seq-name-key ()
52   (if *old-sequence-names*
53       "_CLSQL_SEQ_"
54       "_CLSQL_SEQ"))
55
56 (defun %table-name-to-sequence-name (table-name)
57   ;; if this was escaped it still should be,
58   ;; if it wasnt it still shouldnt-be
59   (check-type table-name string)
60   (replace-all table-name (%seq-name-key) ""))
61
62 (defmethod database-list-sequences (database &key (owner nil))
63   (declare (ignore owner))
64   (mapcan #'(lambda (s)
65               (and (search (%seq-name-key) s :test #'string-equal)
66                    (list (%table-name-to-sequence-name s))))
67           (database-list-tables-and-sequences database)))
68
69 (defmethod database-set-sequence-position (sequence-name position database)
70   (database-execute-command
71    (format nil "UPDATE ~A SET last_value=~A,is_called='t'"
72            (%sequence-name-to-table sequence-name database)
73            position)
74    database)
75   position)
76
77 (defmethod database-sequence-next (sequence-name database)
78   (without-interrupts
79    (let* ((table-name (%sequence-name-to-table sequence-name database))
80           (tuple
81            (car (database-query
82                  (concatenate 'string "SELECT last_value,is_called FROM "
83                               table-name)
84                  database :auto nil))))
85      (cond
86        ((char-equal (schar (second tuple) 0) #\f)
87         (database-execute-command
88          (format nil "UPDATE ~A SET is_called='t'" table-name)
89          database)
90         (car tuple))
91        (t
92         (let ((new-pos (1+ (car tuple))))
93          (database-execute-command
94           (format nil "UPDATE ~A SET last_value=~D" table-name new-pos)
95           database)
96          new-pos))))))
97
98 (defmethod database-sequence-last (sequence-name database)
99   (without-interrupts
100    (caar (database-query
101           (concatenate 'string "SELECT last_value FROM "
102                        (%sequence-name-to-table sequence-name database))
103           database :auto nil))))