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 -- Thread safe access to the SQLite database
50 protected SQLite_Safe
is
53 (DB
: in Handle
; Result
: out SQLite3
.Return_Value
);
57 (DB
: in Handle
; SQL
: in String; Result
: out SQLite3
.Return_Value
);
58 -- Execute an SQL statement
61 (DB
: in Handle
; Name
: in String; Result
: out SQLite3
.Return_Value
);
64 function Prepare_Select
66 Iter
: in Standard
.DB
.Iterator
'Class;
67 SQL
: in String) return Standard
.DB
.Iterator
'Class;
68 -- Prepare a select statement
72 -----------------------
73 -- Begin_Transaction --
74 -----------------------
76 overriding
procedure Begin_Transaction
(DB
: in Handle
) is
78 Logs
.Write
(Module
, "begin");
79 Execute
(DB
, "begin");
80 end Begin_Transaction
;
86 procedure Check_Result
88 Result
: in SQLite3
.Return_Value
)
90 use type SQLite3
.Return_Value
;
92 if Result
/= SQLite3
.SQLITE_OK
then
97 ("Return_Value", SQLite3
.Return_Value
'Image (Result
))
98 & ", " & Logs
.NV
("routine", Routine
));
100 with "SQLite: Error " & SQLite3
.Return_Value
'Image (Result
) &
109 overriding
procedure Close
(DB
: in out Handle
) is
110 Result
: SQLite3
.Return_Value
;
112 Logs
.Write
(Module
, "close");
113 SQLite_Safe
.Close
(DB
, Result
);
114 Check_Result
("close", Result
);
115 Unchecked_Free
(DB
.H
);
122 overriding
procedure Commit
(DB
: in Handle
) is
124 Logs
.Write
(Module
, "commit");
125 Execute
(DB
, "commit");
132 overriding
procedure Connect
135 User
: in String := "";
136 Password
: in String := "")
138 pragma Unreferenced
(User
, Password
);
139 use type GNU
.DB
.SQLite3
.Handle
;
141 Result
: SQLite3
.Return_Value
;
143 Logs
.Write
(Module
, "connect " & Logs
.NV
("Name", Name
));
145 if Name
= In_Memory_Database
then
146 if Unique_Handle
= null then
147 -- Open only one database connection !
149 Unique_Handle
:= new GNU
.DB
.SQLite3
.Object
;
150 DB
.H
:= Unique_Handle
;
151 SQLite_Safe
.Open
(DB
, Name
, Result
);
152 Check_Result
("connect", Result
);
154 elsif DB
.H
= null then
155 -- Get the open database connection
156 DB
.H
:= Unique_Handle
;
161 DB
.H
:= new GNU
.DB
.SQLite3
.Object
;
164 SQLite_Safe
.Open
(DB
, Name
, Result
);
165 Check_Result
("connect", Result
);
173 overriding
procedure End_Select
(Iter
: in out Iterator
) is
175 Logs
.Write
(Module
, "end_select");
176 Check_Result
("end_select", SQLite3
.finalize
(Iter
.S
'Unchecked_Access));
183 overriding
procedure Execute
(DB
: in Handle
; SQL
: in String) is
184 Result
: SQLite3
.Return_Value
;
186 Logs
.Write
(Module
, "execute : " & Logs
.NV
("SQL", SQL
));
187 SQLite_Safe
.Exec
(DB
, SQL
, Result
);
188 Check_Result
("execute", Result
);
191 raise DB_Error
with "DB_Error on Execute " & SQL
;
198 overriding
procedure Get_Line
199 (Iter
: in out Iterator
;
200 Result
: out String_Vectors
.Vector
)
202 use type SQLite3
.Return_Value
;
204 for K
in 0 .. Iter
.Col
- 1 loop
205 String_Vectors
.Append
206 (Result
, SQLite3
.column_text
(Iter
.S
'Unchecked_Access, K
));
209 Step_Internal
(Iter
);
212 -----------------------
213 -- Last_Insert_Rowid --
214 -----------------------
216 overriding
function Last_Insert_Rowid
(DB
: in Handle
) return String is
217 Rowid
: constant String :=
218 SQLite3
.uint64
'Image (SQLite3
.Last_Insert_Rowid
(DB
.H
));
220 -- Skip first whitespace returned by 'Image
221 return Rowid
(Rowid
'First + 1 .. Rowid
'Last);
222 end Last_Insert_Rowid
;
228 overriding
function More
(Iter
: in Iterator
) return Boolean is
237 overriding
procedure Prepare_Select
239 Iter
: in out Standard
.DB
.Iterator
'Class;
242 use type SQLite3
.Statement_Reference
;
244 Iter
:= SQLite_Safe
.Prepare_Select
(DB
, Iter
, SQL
);
251 overriding
procedure Rollback
(DB
: in Handle
) is
253 Logs
.Write
(Module
, "rollback");
254 Execute
(DB
, "rollback");
261 protected body SQLite_Safe
is
268 (DB
: in Handle
; Result
: out SQLite3
.Return_Value
) is
270 Result
:= SQLite3
.Close
(DB
.H
);
278 (DB
: in Handle
; SQL
: in String; Result
: out SQLite3
.Return_Value
) is
280 Result
:= SQLite3
.Exec
(DB
.H
, SQL
);
290 Result
: out SQLite3
.Return_Value
) is
292 Result
:= SQLite3
.Open
(DB
.H
, Name
);
299 function Prepare_Select
301 Iter
: in Standard
.DB
.Iterator
'Class;
302 SQL
: in String) return Standard
.DB
.Iterator
'Class
304 use type SQLite3
.Statement_Reference
;
305 Select_Iter
: Standard
.DB
.Iterator
'Class := Iter
;
307 pragma Assert
(Select_Iter
in Iterator
);
309 (Module
, "prepare select : " & Logs
.NV
("SQL", SQL
));
311 Iterator
(Select_Iter
).H
:= DB
;
312 Iterator
(Select_Iter
).More
:= False;
317 (DB
.H
, SQL
, Iterator
(Select_Iter
).S
'Unchecked_Access));
319 Iterator
(Select_Iter
).Col
:=
320 SQLite3
.column_count
(Iterator
(Select_Iter
).S
'Unchecked_Access);
322 Step_Internal
(Iterator
(Select_Iter
));
332 procedure Step_Internal
(Iter
: in out Iterator
) is
333 use type SQLite3
.Return_Value
;
334 R
: SQLite3
.Return_Value
;
336 R
:= SQLite3
.step
(Iter
.S
'Unchecked_Access);
338 if R
= SQLite3
.SQLITE_DONE
then
341 elsif R
= SQLite3
.SQLITE_ROW
then
345 Check_Result
("step_internal", R
);