1 ------------------------------------------------------------------------------
4 -- Copyright (C) 2006-2008 --
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
);
54 (DB
: in Handle
; SQL
: in String; Result
: out Sqlite3
.Return_Value
);
55 -- Execute an SQL statement
58 (DB
: in Handle
; Name
: in String; Result
: out Sqlite3
.Return_Value
);
61 procedure Prepare_Select
63 Iter
: in out Standard
.DB
.Iterator
'Class;
65 -- Prepare a select statement
68 -----------------------
69 -- Begin_Transaction --
70 -----------------------
72 overriding
procedure Begin_Transaction
(DB
: in Handle
) is
74 Logs
.Write
(Module
, "begin");
75 Execute
(DB
, "begin");
76 end Begin_Transaction
;
82 procedure Check_Result
84 Result
: in SQLite3
.Return_Value
)
86 use type SQLite3
.Return_Value
;
88 if Result
/= SQLite3
.SQLITE_OK
then
93 ("Return_Value", SQLite3
.Return_Value
'Image (Result
))
94 & ", " & Logs
.NV
("routine", Routine
));
96 with "SQLite: Error " & SQLite3
.Return_Value
'Image (Result
) &
105 overriding
procedure Close
(DB
: in out Handle
) is
106 Result
: Sqlite3
.Return_Value
;
108 Logs
.Write
(Module
, "close");
109 SQLite_Safe
.Close
(DB
, Result
);
110 Check_Result
("close", Result
);
111 Unchecked_Free
(DB
.H
);
118 overriding
procedure Commit
(DB
: in Handle
) is
120 Logs
.Write
(Module
, "commit");
121 Execute
(DB
, "commit");
128 overriding
procedure Connect
131 User
: in String := "";
132 Password
: in String := "")
134 pragma Unreferenced
(User
, Password
);
135 use type GNU
.DB
.SQLite3
.Handle
;
137 Result
: Sqlite3
.Return_Value
;
140 (Module
, "connect " & Logs
.NV
("Name", Name
));
141 if Name
= In_Memory_Database
then
142 if Unique_Handle
= null then
144 -- Open only one database connection !
146 Unique_Handle
:= new GNU
.DB
.SQLite3
.Object
;
147 DB
.H
:= Unique_Handle
;
148 SQLite_Safe
.Open
(DB
, Name
, Result
);
149 Check_Result
("connect", Result
);
151 elsif DB
.H
= null then
152 -- Get the open database connection
153 DB
.H
:= Unique_Handle
;
157 DB
.H
:= new GNU
.DB
.SQLite3
.Object
;
160 SQLite_Safe
.Open
(DB
, Name
, Result
);
161 Check_Result
("connect", Result
);
169 overriding
procedure End_Select
(Iter
: in out Iterator
) is
171 Logs
.Write
(Module
, "end_select");
172 Check_Result
("end_select", SQLite3
.finalize
(Iter
.S
'Unchecked_Access));
179 overriding
procedure Execute
(DB
: in Handle
; SQL
: in String) is
180 Result
: SQLite3
.Return_Value
;
183 (Module
, "execute : " & Logs
.NV
("SQL", SQL
));
184 SQLite_Safe
.Exec
(DB
, SQL
, Result
);
185 Check_Result
("execute", Result
);
188 raise DB_Error
with "DB_Error on Execute " & SQL
;
195 overriding
procedure Get_Line
196 (Iter
: in out Iterator
;
197 Result
: out String_Vectors
.Vector
)
199 use type SQLite3
.Return_Value
;
201 for K
in 0 .. Iter
.Col
- 1 loop
202 String_Vectors
.Append
203 (Result
, SQLite3
.column_text
(Iter
.S
'Unchecked_Access, K
));
206 Step_Internal
(Iter
);
209 -----------------------
210 -- Last_Insert_Rowid --
211 -----------------------
213 overriding
function Last_Insert_Rowid
(DB
: in Handle
) return String is
214 Rowid
: constant String :=
215 SQLite3
.uint64
'Image (SQLite3
.Last_Insert_Rowid
(DB
.H
));
217 -- Skip first whitespace returned by 'Image
218 return Rowid
(Rowid
'First + 1 .. Rowid
'Last);
219 end Last_Insert_Rowid
;
225 overriding
function More
(Iter
: in Iterator
) return Boolean is
234 overriding
procedure Prepare_Select
236 Iter
: in out Standard
.DB
.Iterator
'Class;
239 use type SQLite3
.Statement_Reference
;
241 SQLite_Safe
.Prepare_Select
(DB
, Iter
, SQL
);
248 overriding
procedure Rollback
(DB
: in Handle
) is
250 Logs
.Write
(Module
, "rollback");
251 Execute
(DB
, "rollback");
258 protected body SQLite_Safe
is
265 (DB
: in Handle
; Result
: out Sqlite3
.Return_Value
) is
267 Result
:= SQLite3
.Close
(DB
.H
);
275 (DB
: in Handle
; SQL
: in String; Result
: out Sqlite3
.Return_Value
) is
277 Result
:= SQLite3
.Exec
(DB
.H
, SQL
);
285 (DB
: in Handle
; Name
: in String; Result
: out Sqlite3
.Return_Value
) is
287 Result
:= SQLite3
.Open
(DB
.H
, Name
);
294 procedure Prepare_Select
296 Iter
: in out Standard
.DB
.Iterator
'Class;
299 use type SQLite3
.Statement_Reference
;
301 pragma Assert
(Iter
in Iterator
);
303 (Module
, "prepare select : " & Logs
.NV
("SQL", SQL
));
305 Iterator
(Iter
).H
:= DB
;
306 Iterator
(Iter
).More
:= False;
310 SQLite3
.prepare
(DB
.H
, SQL
, Iterator
(Iter
).S
'Unchecked_Access));
312 Iterator
(Iter
).Col
:=
313 SQLite3
.column_count
(Iterator
(Iter
).S
'Unchecked_Access);
315 Step_Internal
(Iterator
(Iter
));
323 procedure Step_Internal
(Iter
: in out Iterator
) is
324 use type SQLite3
.Return_Value
;
325 R
: SQLite3
.Return_Value
;
327 R
:= SQLite3
.step
(Iter
.S
'Unchecked_Access);
329 if R
= SQLite3
.SQLITE_DONE
then
331 elsif R
= SQLite3
.SQLITE_ROW
then
334 Check_Result
("step_internal", R
);