1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42 """
43 This module defines those datatypes that are specific for FireBird.
44
45 @author: Diedrich Vorberg <diedrich@tux4web.de>, May 2006
46 """
47
48
49
50 import sys
51 from types import *
52 from string import *
53
54
55 from orm2 import sql
56 from orm2.datatypes import *
57
59 """
60 Datatype for automatically gernerated ids.
61
62 From U{The FireBird FAQ <http://firebird.sourceforge.net/index.php?op=faq#q0011.dat>}
63
64 How can i make an auto-incrementing primary key column? and is the NOT NULL constraint mandatory for a primary key?
65 ===================================================================================================================
66 In Firebird, you achieve an auto-incrementing PK using a generator
67 and a BEFORE INSERT trigger::
68
69 CREATE GENERATOR GEN_PK_ATABLE;
70 COMMIT;
71
72 Define the column, e.g., ATABLE_ID, as BIGINT or INTEGER and yes,
73 the NOT NULL constraint is mandatory for a primary key.
74
75 The trigger for automatic population of the key is this::
76
77 CREATE TRIGGER BI_ATABLE FOR ATABLE
78 ACTIVE BEFORE INSERT
79 AS
80 BEGIN
81 IF(NEW.ATABLE_ID IS NULL) THEN
82 NEW.ATABLE_ID = GEN_ID(GEN_PK_ATABLE, 1);
83 END
84
85 I{This is B{NOT} what orm does! It does...}
86
87 How can I get the value of my generated primary key after an insert ?
88 =====================================================================
89 Firebird doesn't currently return values from insert statements
90 and, in multi-user, it isn't safe to query the generator
91 afterwards (GEN_ID(Generator_name, 0) because you have no way
92 to know whether the current 'latest' value was yours or someone
93 else's. The trick is to get the generator value into your
94 application as a variable before you post your insert. This
95 way, you make it available not just for your insert but for any
96 dependent rows you need to create for it inside the same
97 transaction::
98
99 SELECT GEN_ID(Generator_name, 1) AS MyVar FROM RDB$DATABASE;
100
101 Some data access interfaces and drivers provide ways to do this
102 automatically for you. For example, IB Objects implements the
103 GeneratorLinks property for statement classes.
104
105
106 How it is handeld by orm
107 ========================
108 orm is the kind of interface that does this automatically for
109 you. For any serial (and in fact L{common_serial
110 <orm2.datatypes.common_serial>}, see above) column it will query
111 the corresponding sequence and store the resulting value in the
112 right attribute to be used in the INSERT statement. If you use
113 a serial as your primary key, the select_after_insert()
114 mechanism (see L{orm2.datasource.datasource}) will work
115 correctly.
116
117 """
118
119 - def __init__(self, column=None, sequence=None, title=None,
120 validators=(), widget_specs=()):
121 """
122 @param sequence: Either a string or a sql.identifyer instance,
123 naming the sequence to be used by this serial column. Defaults
124 to GEN_PK_<relation name>
125 """
126 integer.__init__(self, column, title, validators, widget_specs,
127 has_default=True)
128
129 self.sequence = sequence
130
139
141 if self.isset(dbobj):
142 raise ORMException( "A auto_increment property is not mutable, "+\
143 "once it is on object creation" )
144 else:
145 integer.__set__(self, dbobj, value)
146
147
148
149
150
151
152
153
154
155
156