source: main/trunk/greenstone2/perllib/dbutil/sqlite.pm@ 21872

Last change on this file since 21872 was 21872, checked in by davidb, 14 years ago

sqlite3 can take an sql statement as an extra parameter. Better to do this than use echo and pipe it through, as more cross-platform independent.

File size: 7.2 KB
Line 
1###########################################################################
2#
3# dbutil::sqlite -- utility functions for writing to sqlite databases
4#
5# A component of the Greenstone digital library software
6# from the New Zealand Digital Library Project at the
7# University of Waikato, New Zealand.
8#
9# Copyright (C) 2009
10#
11# This program is free software; you can redistribute it and/or modify
12# it under the terms of the GNU General Public License as published by
13# the Free Software Foundation; either version 2 of the License, or
14# (at your option) any later version.
15#
16# This program is distributed in the hope that it will be useful,
17# but WITHOUT ANY WARRANTY; without even the implied warranty of
18# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19# GNU General Public License for more details.
20#
21# You should have received a copy of the GNU General Public License
22# along with this program; if not, write to the Free Software
23# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24#
25###########################################################################
26
27package dbutil::sqlite;
28
29use strict;
30
31
32# -----------------------------------------------------------------------------
33# SQLITE IMPLEMENTATION
34# -----------------------------------------------------------------------------
35
36sub open_infodb_write_handle
37{
38 my $infodb_file_path = shift(@_);
39
40 my $sqlite3_exe = &util::filename_cat($ENV{'GSDLHOME'},"bin",$ENV{'GSDLOS'}, "sqlite3" . &util::get_os_exe());
41 my $infodb_handle = undef;
42 if (!-e "$sqlite3_exe" || !open($infodb_handle, "| \"$sqlite3_exe\" \"$infodb_file_path\""))
43 {
44 return undef;
45 }
46
47 print $infodb_handle "CREATE TABLE IF NOT EXISTS data (key TEXT PRIMARY KEY, value TEXT);\n";
48 print $infodb_handle "CREATE TABLE IF NOT EXISTS document_metadata (id INTEGER PRIMARY KEY, docOID TEXT, element TEXT, value TEXT);\n";
49
50 # This is crucial for efficiency when importing large amounts of data
51 print $infodb_handle "CREATE INDEX IF NOT EXISTS dmd ON document_metadata(docOID);\n";
52
53 # This is very important for efficiency, otherwise each command will be actioned one at a time
54 print $infodb_handle "BEGIN TRANSACTION;\n";
55
56 return $infodb_handle;
57}
58
59
60sub close_infodb_write_handle
61{
62 my $infodb_handle = shift(@_);
63
64 # Close the transaction we began after opening the file
65 print $infodb_handle "END TRANSACTION;\n";
66
67 # This is crucial for efficient queries on the database!
68 print $infodb_handle "CREATE INDEX IF NOT EXISTS dme ON document_metadata(element);\n";
69
70 close($infodb_handle);
71}
72
73
74sub read_infodb_cmd
75{
76 my $infodb_file_path = shift(@_);
77 my $sqlcmd = shift(@_);
78
79 my $result = "";
80
81 my $sqlite3_exe = &util::filename_cat($ENV{'GSDLHOME'},"bin",$ENV{'GSDLOS'}, "sqlite3" . &util::get_os_exe());
82 my $infodb_handle = undef;
83 my $cmd = "\"$sqlite3_exe\" \"$infodb_file_path\" \"$sqlcmd\"";
84
85 if (!-e "$sqlite3_exe" || !open($infodb_handle, "$cmd |"))
86 {
87 print STDERR "Unable to execute: $cmd\n";
88 print STDERR "$!\n";
89 }
90 else {
91
92 my $line;
93 while (defined($line=<$infodb_handle>)) {
94 $result .= $line;
95 }
96
97 close($infodb_handle);
98 }
99
100 return $result;
101}
102
103sub get_infodb_file_path
104{
105 my $collection_name = shift(@_);
106 my $infodb_directory_path = shift(@_);
107
108 my $infodb_file_extension = ".db";
109 my $infodb_file_name = &util::get_dirsep_tail($collection_name) . $infodb_file_extension;
110 return &util::filename_cat($infodb_directory_path, $infodb_file_name);
111}
112
113
114sub read_infodb_file
115{
116 my $infodb_file_path = shift(@_);
117 my $infodb_map = shift(@_);
118
119
120 my $keys_str = read_infodb_cmd($infodb_file_path,"SELECT key FROM data;");
121
122 my @keys = split(/\n/,$keys_str);
123
124 foreach my $k (@keys) {
125
126 my $k_safe = &sqlite_safe($k);
127 my $select_val_cmd = "SELECT value FROM data WHERE key='$k_safe';";
128
129 my $val_str = read_infodb_cmd($infodb_file_path,$select_val_cmd);
130
131 $infodb_map->{$k} = $val_str;
132 }
133
134}
135
136
137sub write_infodb_entry
138{
139 my $infodb_handle = shift(@_);
140 my $infodb_key = shift(@_);
141 my $infodb_map = shift(@_);
142
143 # Add the key -> value mapping into the "data" table
144 my $infodb_entry_value = "";
145 foreach my $infodb_value_key (keys(%$infodb_map))
146 {
147 foreach my $infodb_value (@{$infodb_map->{$infodb_value_key}})
148 {
149 $infodb_entry_value .= "<$infodb_value_key>" . $infodb_value . "\n";
150 }
151 }
152
153 my $safe_infodb_key = &sqlite_safe($infodb_key);
154 print $infodb_handle "INSERT OR REPLACE INTO data (key, value) VALUES ('" . $safe_infodb_key . "', '" . &sqlite_safe($infodb_entry_value) . "');\n";
155
156 # If this infodb entry is for a document, add all the interesting document metadata to the
157 # "document_metadata" table (for use by the dynamic classifiers)
158 if ($infodb_key !~ /\./ && $infodb_entry_value =~ /\<doctype\>doc\n/)
159 {
160 print $infodb_handle "DELETE FROM document_metadata WHERE docOID='" . $safe_infodb_key . "';\n";
161
162 foreach my $infodb_value_key (keys(%$infodb_map))
163 {
164 # We're not interested in most of the automatically added document metadata
165 next if ($infodb_value_key eq "archivedir" ||
166 $infodb_value_key eq "assocfilepath" ||
167 $infodb_value_key eq "childtype" ||
168 $infodb_value_key eq "contains" ||
169 $infodb_value_key eq "docnum" ||
170 $infodb_value_key eq "doctype" ||
171 $infodb_value_key eq "Encoding" ||
172 $infodb_value_key eq "FileSize" ||
173 $infodb_value_key eq "hascover" ||
174 $infodb_value_key eq "hastxt" ||
175 $infodb_value_key eq "lastmodified" ||
176 $infodb_value_key eq "metadataset" ||
177 $infodb_value_key eq "thistype" ||
178 $infodb_value_key =~ /^metadatafreq\-/ ||
179 $infodb_value_key =~ /^metadatalist\-/);
180
181 foreach my $infodb_value (@{$infodb_map->{$infodb_value_key}})
182 {
183 print $infodb_handle "INSERT INTO document_metadata (docOID, element, value) VALUES ('" . $safe_infodb_key . "', '" . &sqlite_safe($infodb_value_key) . "', '" . &sqlite_safe($infodb_value) . "');\n";
184 }
185 }
186 }
187}
188
189
190
191sub write_infodb_rawentry
192{
193 my $infodb_handle = shift(@_);
194 my $infodb_key = shift(@_);
195 my $infodb_val = shift(@_);
196
197 my $safe_infodb_key = &sqlite_safe($infodb_key);
198 print $infodb_handle "INSERT OR REPLACE INTO data (key, value) VALUES ('" . $safe_infodb_key . "', '" . &sqlite_safe($infodb_val) . "');\n";
199}
200
201
202
203sub delete_infodb_entry
204{
205 my $infodb_handle = shift(@_);
206 my $infodb_key = shift(@_);
207
208 # Delete the key from the "data" table
209
210 my $safe_infodb_key = &sqlite_safe($infodb_key);
211
212 print $infodb_handle "DELETE FROM data WHERE key='" . $safe_infodb_key . "';\n";
213
214 # If this infodb entry is for a document, delete the
215 # "document_metadata" table entry also (for use by the dynamic classifiers)
216 if ($infodb_key !~ /\./)
217 {
218 # Possible for there not to be a docOID matching this infodb_key
219 # (entries are only made when <doctype> == doc
220 # Attempt to delete it, and don't complain if one isn't found
221
222 print $infodb_handle "DELETE FROM document_metadata WHERE docOID='" . $safe_infodb_key . "';\n";
223
224 }
225}
226
227
228sub sqlite_safe
229{
230 my $value = shift(@_);
231
232 # Escape any single quotes in the value
233 $value =~ s/\'/\'\'/g;
234
235 return $value;
236}
237
238
2391;
Note: See TracBrowser for help on using the repository browser.