1 ------------------------------------------------------------------------------
4 -- Copyright (C) 2006-2007 --
5 -- Pascal Obry - Olivier Ramonat --
7 -- This library is free software; you can redistribute it and/or modify --
8 -- it under the terms of the GNU General Public License as published by --
9 -- the Free Software Foundation; either version 2 of the License, or (at --
10 -- your option) any later version. --
12 -- This library is distributed in the hope that it will be useful, but --
13 -- WITHOUT ANY WARRANTY; without even the implied warranty of --
14 -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU --
15 -- General Public License for more details. --
17 -- You should have received a copy of the GNU General Public License --
18 -- along with this library; if not, write to the Free Software Foundation, --
19 -- Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. --
20 ------------------------------------------------------------------------------
22 with Ada
.Unchecked_Deallocation
;
26 package body DB
.SQLite
is
31 Module
: constant Logs
.Module_Name
:= "DB_SQLITE";
33 Unique_Handle
: SQLite3
.Handle
:= null;
34 -- Unique handle to use when we want to use in memory connection
36 procedure Unchecked_Free
is new Unchecked_Deallocation
37 (Object
=> SQLite3
.Object
, Name
=> SQLite3
.Handle
);
39 procedure Check_Result
41 Result
: in SQLite3
.Return_Value
);
42 pragma Inline
(Check_Result
);
43 -- Check result, raises and exception if it is an error code
45 procedure Step_Internal
(Iter
: in out Iterator
);
46 -- Advance to the next row and set Iter.More
48 protected SQLite_Safe
is
50 (DB
: in Handle
; Result
: out Sqlite3
.Return_Value
);
53 (DB
: in Handle
; SQL
: in String; Result
: out Sqlite3
.Return_Value
);
54 -- Execute an SQL statement
57 (DB
: in Handle
; Name
: in String; Result
: out Sqlite3
.Return_Value
);
58 -- Open an SQL statement
60 procedure Prepare_Select
62 Iter
: in out Standard
.DB
.Iterator
'Class;
66 -----------------------
67 -- Begin_Transaction --
68 -----------------------
70 overriding
procedure Begin_Transaction
(DB
: in Handle
) is
72 Logs
.Write
(Module
, "begin");
73 Execute
(DB
, "begin");
74 end Begin_Transaction
;
80 procedure Check_Result
82 Result
: in SQLite3
.Return_Value
)
84 use type SQLite3
.Return_Value
;
86 if Result
/= SQLite3
.SQLITE_OK
then
91 ("Return_Value", SQLite3
.Return_Value
'Image (Result
))
92 & ", " & Logs
.NV
("routine", Routine
));
94 with "SQLite: Error " & SQLite3
.Return_Value
'Image (Result
) &
103 overriding
procedure Close
(DB
: in out Handle
) is
104 Result
: Sqlite3
.Return_Value
;
106 Logs
.Write
(Module
, "close");
107 SQLite_Safe
.Close
(DB
, Result
);
108 Check_Result
("close", Result
);
109 Unchecked_Free
(DB
.H
);
116 overriding
procedure Commit
(DB
: in Handle
) is
118 Logs
.Write
(Module
, "commit");
119 Execute
(DB
, "commit");
126 overriding
procedure Connect
129 User
: in String := "";
130 Password
: in String := "")
132 pragma Unreferenced
(User
, Password
);
133 use type GNU
.DB
.SQLite3
.Handle
;
135 Result
: Sqlite3
.Return_Value
;
138 (Module
, "connect " & Logs
.NV
("Name", Name
));
139 if Name
= In_Memory_Database
then
140 if Unique_Handle
= null then
142 -- Open only one database connection !
144 Unique_Handle
:= new GNU
.DB
.SQLite3
.Object
;
145 DB
.H
:= Unique_Handle
;
146 SQLite_Safe
.Open
(DB
, Name
, Result
);
147 Check_Result
("connect", Result
);
149 elsif DB
.H
= null then
150 -- Get the open database connection
151 DB
.H
:= Unique_Handle
;
155 DB
.H
:= new GNU
.DB
.SQLite3
.Object
;
158 SQLite_Safe
.Open
(DB
, Name
, Result
);
159 Check_Result
("connect", Result
);
167 overriding
procedure End_Select
(Iter
: in out Iterator
) is
169 Logs
.Write
(Module
, "end_select");
170 Check_Result
("end_select", SQLite3
.finalize
(Iter
.S
'Unchecked_Access));
177 overriding
procedure Execute
(DB
: in Handle
; SQL
: in String) is
178 Result
: SQLite3
.Return_Value
;
181 (Module
, "execute : " & Logs
.NV
("SQL", SQL
));
182 SQLite_Safe
.Exec
(DB
, SQL
, Result
);
183 Check_Result
("execute", Result
);
186 raise DB_Error
with "DB_Error on Execute " & SQL
;
193 overriding
procedure Get_Line
194 (Iter
: in out Iterator
;
195 Result
: out String_Vectors
.Vector
)
197 use type SQLite3
.Return_Value
;
199 for K
in 0 .. Iter
.Col
- 1 loop
200 String_Vectors
.Append
201 (Result
, SQLite3
.column_text
(Iter
.S
'Unchecked_Access, K
));
204 Step_Internal
(Iter
);
207 -----------------------
208 -- Last_Insert_Rowid --
209 -----------------------
211 overriding
function Last_Insert_Rowid
(DB
: in Handle
) return String is
212 Rowid
: constant String :=
213 SQLite3
.uint64
'Image (SQLite3
.Last_Insert_Rowid
(DB
.H
));
215 -- Skip first whitespace returned by 'Image
216 return Rowid
(Rowid
'First + 1 .. Rowid
'Last);
217 end Last_Insert_Rowid
;
223 overriding
function More
(Iter
: in Iterator
) return Boolean is
232 overriding
procedure Prepare_Select
234 Iter
: in out Standard
.DB
.Iterator
'Class;
237 use type SQLite3
.Statement_Reference
;
239 SQLite_Safe
.Prepare_Select
(DB
, Iter
, SQL
);
246 overriding
procedure Rollback
(DB
: in Handle
) is
248 Logs
.Write
(Module
, "rollback");
249 Execute
(DB
, "rollback");
252 protected body SQLite_Safe
is
254 (DB
: in Handle
; Result
: out Sqlite3
.Return_Value
) is
256 Result
:= SQLite3
.Close
(DB
.H
);
260 (DB
: in Handle
; SQL
: in String; Result
: out Sqlite3
.Return_Value
) is
262 Result
:= SQLite3
.Exec
(DB
.H
, SQL
);
266 (DB
: in Handle
; Name
: in String; Result
: out Sqlite3
.Return_Value
) is
268 Result
:= SQLite3
.Open
(DB
.H
, Name
);
271 procedure Prepare_Select
273 Iter
: in out Standard
.DB
.Iterator
'Class;
276 use type SQLite3
.Statement_Reference
;
278 pragma Assert
(Iter
in Iterator
);
280 (Module
, "prepare select : " & Logs
.NV
("SQL", SQL
));
282 Iterator
(Iter
).H
:= DB
;
283 Iterator
(Iter
).More
:= False;
287 SQLite3
.prepare
(DB
.H
, SQL
, Iterator
(Iter
).S
'Unchecked_Access));
289 Iterator
(Iter
).Col
:=
290 SQLite3
.column_count
(Iterator
(Iter
).S
'Unchecked_Access);
292 Step_Internal
(Iterator
(Iter
));
300 procedure Step_Internal
(Iter
: in out Iterator
) is
301 use type SQLite3
.Return_Value
;
302 R
: SQLite3
.Return_Value
;
304 R
:= SQLite3
.step
(Iter
.S
'Unchecked_Access);
306 if R
= SQLite3
.SQLITE_DONE
then
308 elsif R
= SQLite3
.SQLITE_ROW
then
311 Check_Result
("step_internal", R
);