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

Last change on this file since 22076 was 22076, checked in by sjm84, 14 years ago

Added error messages to these files that are printed when a write handle cannot be opened

File size: 7.4 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
43 if (!-e "$sqlite3_exe")
44 {
45 print STDERR "Error: Unable to find $sqlite3_exe\n";
46 return undef;
47 }
48
49 if(!open($infodb_handle, "| \"$sqlite3_exe\" \"$infodb_file_path\""))
50 {
51 print STDERR "Error: Failed to open pipe to \"$sqlite3_exe\" \"$infodb_file_path\"\n";
52 print STDERR " $!\n";
53 return undef;
54 }
55
56 print $infodb_handle "CREATE TABLE IF NOT EXISTS data (key TEXT PRIMARY KEY, value TEXT);\n";
57 print $infodb_handle "CREATE TABLE IF NOT EXISTS document_metadata (id INTEGER PRIMARY KEY, docOID TEXT, element TEXT, value TEXT);\n";
58
59 # This is crucial for efficiency when importing large amounts of data
60 print $infodb_handle "CREATE INDEX IF NOT EXISTS dmd ON document_metadata(docOID);\n";
61
62 # This is very important for efficiency, otherwise each command will be actioned one at a time
63 print $infodb_handle "BEGIN TRANSACTION;\n";
64
65 return $infodb_handle;
66}
67
68
69sub close_infodb_write_handle
70{
71 my $infodb_handle = shift(@_);
72
73 # Close the transaction we began after opening the file
74 print $infodb_handle "END TRANSACTION;\n";
75
76 # This is crucial for efficient queries on the database!
77 print $infodb_handle "CREATE INDEX IF NOT EXISTS dme ON document_metadata(element);\n";
78
79 close($infodb_handle);
80}
81
82
83sub read_infodb_cmd
84{
85 my $infodb_file_path = shift(@_);
86 my $sqlcmd = shift(@_);
87
88 my $result = "";
89
90 my $sqlite3_exe = &util::filename_cat($ENV{'GSDLHOME'},"bin",$ENV{'GSDLOS'}, "sqlite3" . &util::get_os_exe());
91 my $infodb_handle = undef;
92 my $cmd = "\"$sqlite3_exe\" \"$infodb_file_path\" \"$sqlcmd\"";
93
94 if (!-e "$sqlite3_exe" || !open($infodb_handle, "$cmd |"))
95 {
96 print STDERR "Unable to execute: $cmd\n";
97 print STDERR "$!\n";
98 }
99 else {
100
101 my $line;
102 while (defined($line=<$infodb_handle>)) {
103 $result .= $line;
104 }
105
106 close($infodb_handle);
107 }
108
109 return $result;
110}
111
112sub get_infodb_file_path
113{
114 my $collection_name = shift(@_);
115 my $infodb_directory_path = shift(@_);
116
117 my $infodb_file_extension = ".db";
118 my $infodb_file_name = &util::get_dirsep_tail($collection_name) . $infodb_file_extension;
119 return &util::filename_cat($infodb_directory_path, $infodb_file_name);
120}
121
122
123sub read_infodb_file
124{
125 my $infodb_file_path = shift(@_);
126 my $infodb_map = shift(@_);
127
128
129 my $keys_str = read_infodb_cmd($infodb_file_path,"SELECT key FROM data;");
130
131 my @keys = split(/\n/,$keys_str);
132
133 foreach my $k (@keys) {
134
135 my $k_safe = &sqlite_safe($k);
136 my $select_val_cmd = "SELECT value FROM data WHERE key='$k_safe';";
137
138 my $val_str = read_infodb_cmd($infodb_file_path,$select_val_cmd);
139
140 $infodb_map->{$k} = $val_str;
141 }
142
143}
144
145
146sub write_infodb_entry
147{
148 my $infodb_handle = shift(@_);
149 my $infodb_key = shift(@_);
150 my $infodb_map = shift(@_);
151
152 # Add the key -> value mapping into the "data" table
153 my $infodb_entry_value = "";
154 foreach my $infodb_value_key (keys(%$infodb_map))
155 {
156 foreach my $infodb_value (@{$infodb_map->{$infodb_value_key}})
157 {
158 $infodb_entry_value .= "<$infodb_value_key>" . $infodb_value . "\n";
159 }
160 }
161
162 my $safe_infodb_key = &sqlite_safe($infodb_key);
163 print $infodb_handle "INSERT OR REPLACE INTO data (key, value) VALUES ('" . $safe_infodb_key . "', '" . &sqlite_safe($infodb_entry_value) . "');\n";
164
165 # If this infodb entry is for a document, add all the interesting document metadata to the
166 # "document_metadata" table (for use by the dynamic classifiers)
167 if ($infodb_key !~ /\./ && $infodb_entry_value =~ /\<doctype\>doc\n/)
168 {
169 print $infodb_handle "DELETE FROM document_metadata WHERE docOID='" . $safe_infodb_key . "';\n";
170
171 foreach my $infodb_value_key (keys(%$infodb_map))
172 {
173 # We're not interested in most of the automatically added document metadata
174 next if ($infodb_value_key eq "archivedir" ||
175 $infodb_value_key eq "assocfilepath" ||
176 $infodb_value_key eq "childtype" ||
177 $infodb_value_key eq "contains" ||
178 $infodb_value_key eq "docnum" ||
179 $infodb_value_key eq "doctype" ||
180 $infodb_value_key eq "Encoding" ||
181 $infodb_value_key eq "FileSize" ||
182 $infodb_value_key eq "hascover" ||
183 $infodb_value_key eq "hastxt" ||
184 $infodb_value_key eq "lastmodified" ||
185 $infodb_value_key eq "metadataset" ||
186 $infodb_value_key eq "thistype" ||
187 $infodb_value_key =~ /^metadatafreq\-/ ||
188 $infodb_value_key =~ /^metadatalist\-/);
189
190 foreach my $infodb_value (@{$infodb_map->{$infodb_value_key}})
191 {
192 print $infodb_handle "INSERT INTO document_metadata (docOID, element, value) VALUES ('" . $safe_infodb_key . "', '" . &sqlite_safe($infodb_value_key) . "', '" . &sqlite_safe($infodb_value) . "');\n";
193 }
194 }
195 }
196}
197
198
199
200sub write_infodb_rawentry
201{
202 my $infodb_handle = shift(@_);
203 my $infodb_key = shift(@_);
204 my $infodb_val = shift(@_);
205
206 my $safe_infodb_key = &sqlite_safe($infodb_key);
207 print $infodb_handle "INSERT OR REPLACE INTO data (key, value) VALUES ('" . $safe_infodb_key . "', '" . &sqlite_safe($infodb_val) . "');\n";
208}
209
210
211
212sub delete_infodb_entry
213{
214 my $infodb_handle = shift(@_);
215 my $infodb_key = shift(@_);
216
217 # Delete the key from the "data" table
218
219 my $safe_infodb_key = &sqlite_safe($infodb_key);
220
221 print $infodb_handle "DELETE FROM data WHERE key='" . $safe_infodb_key . "';\n";
222
223 # If this infodb entry is for a document, delete the
224 # "document_metadata" table entry also (for use by the dynamic classifiers)
225 if ($infodb_key !~ /\./)
226 {
227 # Possible for there not to be a docOID matching this infodb_key
228 # (entries are only made when <doctype> == doc
229 # Attempt to delete it, and don't complain if one isn't found
230
231 print $infodb_handle "DELETE FROM document_metadata WHERE docOID='" . $safe_infodb_key . "';\n";
232
233 }
234}
235
236
237sub sqlite_safe
238{
239 my $value = shift(@_);
240
241 # Escape any single quotes in the value
242 $value =~ s/\'/\'\'/g;
243
244 return $value;
245}
246
247
2481;
Note: See TracBrowser for help on using the repository browser.