source: main/trunk/greenstone2/perllib/dbutil/mssql.pm@ 22485

Last change on this file since 22485 was 22485, checked in by ak19, 14 years ago
  1. Dr Bainbridge fixed the database perl modules to all have the method read_info_keys (which reads the keys from the database into a map), so that dbutil.pm can have the same as a generic method. 2. buildConfigxml.pm only writes out the defaultIndex if it is set (to prevent an Uninitialised Variable warning message from Perl).
File size: 10.6 KB
Line 
1###########################################################################
2#
3# dbutil::mssql -- utility functions for writing to mssql 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::mssql;
28
29use Encode;
30use strict;
31
32
33
34# -----------------------------------------------------------------------------
35# MSSQL IMPLEMENTATION
36# -----------------------------------------------------------------------------
37
38my $mssql_collection_name = "";
39my $mssql_data_table_name = "";
40my $mssql_document_metadata_table_name = "";
41
42
43sub open_infodb_write_handle
44{
45 my $infodb_file_path = shift(@_);
46
47 # You might have to install the DBD::ADO module from CPAN
48 #================================================================#
49 # Uncomment this if you want to use MSSQL!!!
50 # By the way, MSSQL only works on a Windows machine...
51 #================================================================#
52 #use DBI;
53 #use DBD::ADO;
54 #Win32::OLE->Option(CP => Win32::OLE::CP_UTF8);
55
56 # The hard coded server connection thingy which should be placed
57 # in some configuration file.
58 # If you have problem connecting to your MS SQL server:
59 # 1. Check if your MSSQL server has been started.
60 # 2. Check if the TCP/IP connection has been enabled.
61 # 3. Use telnet to the server
62 # (don't forget to specify the port, which can be found in the configuration manager)
63 # If none of the above helped, the you need to start googling then.
64 my $host = "localhost,1660"; # Need to look up your SQL server and see what port is it using.
65 my $user = "sa";
66 my $pwd = "[When installing the MSSQL, you will be asked to input a password for the sa user, use that password]";
67 my $database = "[Create a database in MSSQL and use it here]";
68
69 # Create the unique name for the table
70 # We do not want to change the database for the current running index
71 # Therefore we use timestamp and collection short name to create an unqiue name
72 my $cur_time = time();
73 my $unique_key = $mssql_collection_name . "_" . $cur_time;
74 $mssql_data_table_name = "data_" . $unique_key;
75 $mssql_document_metadata_table_name = "document_metadata_" . $unique_key;
76 print STDERR "MSSQL: Creating unique table name. Unique ID:[" . $unique_key . "]\n";
77
78 # Store these information into the infodbfile
79 open(FH, ">" . $infodb_file_path);
80 print FH "mss-host\t" . $host . "\n";
81 print FH "username\t" . $user . "\n";
82 print FH "password\t" . $pwd . "\n";
83 print FH "database\t" . $database . "\n";
84 print FH "tableid\t" . $unique_key . "\n";
85 close(FH);
86 print STDERR "MSSQL: Saving db info into :[" . $infodb_file_path . "]\n";
87
88 # Make the connection
89 my $dsn = "Provider=SQLNCLI;Server=$host;Database=$database";
90 my $infodb_handle = DBI->connect("dbi:ADO:$dsn", $user, $pwd, { RaiseError => 1, AutoCommit => 1}) || return undef;
91 print STDERR "MSSQL: Connect to MS SQL database. DSN:[" . $dsn . "]\n";
92
93 # Make sure the data table has been created.
94 my $data_table_checker_array = dbgetarray($infodb_handle, "SELECT name FROM sysobjects WHERE name = '" . $mssql_data_table_name . "' AND OBJECTPROPERTY(id,'IsUserTable') = 1");
95 if (scalar(@{$data_table_checker_array}) == 0)
96 {
97 dbquery($infodb_handle, "CREATE TABLE " . $mssql_data_table_name . " (one_key NVARCHAR(50) UNIQUE, one_value NVARCHAR(MAX))");
98 }
99 print STDERR "MSSQL: Making sure the data table(" . $mssql_data_table_name . ") exists\n";
100
101 # Make sure the document_metadata table has been created.
102 my $document_metadata_table_checker_array = dbgetarray($infodb_handle, "SELECT name FROM sysobjects WHERE name = '" . $mssql_document_metadata_table_name . "' AND OBJECTPROPERTY(id,'IsUserTable') = 1");
103 if (scalar(@{$document_metadata_table_checker_array}) == 0)
104 {
105 dbquery($infodb_handle, "CREATE TABLE " . $mssql_document_metadata_table_name . " (id INTEGER IDENTITY(1,1) PRIMARY KEY, docOID NVARCHAR(50), element NVARCHAR(MAX), value NVARCHAR(MAX))");
106 dbquery($infodb_handle, "CREATE INDEX dmd ON " . $mssql_document_metadata_table_name . "(docOID)");
107 }
108 print STDERR "MSSQL: Making sure the document_metadata table(" . $mssql_data_table_name . ") exists.\n";
109
110 return $infodb_handle;
111}
112
113
114sub close_infodb_write_handle
115{
116 my $infodb_handle = shift(@_);
117
118 $infodb_handle->disconnect();
119}
120
121
122sub get_infodb_file_path
123{
124 my $collection_name = shift(@_);
125 my $infodb_directory_path = shift(@_);
126
127 my $infodb_file_extension = ".mssqldbinfo";
128 my $infodb_file_name = &util::get_dirsep_tail($collection_name) . $infodb_file_extension;
129
130 # This will be used in the open_infodb_write_handle function
131 $mssql_collection_name = $collection_name;
132
133 return &util::filename_cat($infodb_directory_path, $infodb_file_name);
134}
135
136
137sub read_infodb_file
138{
139 my $infodb_file_path = shift(@_);
140 my $infodb_map = shift(@_);
141
142 print STDERR "******* mssql::read_infodb_file() TO BE IMPLEMENTED!\n";
143 print STDERR "******* See sqlite.pm for comparable implementation that has been coded up!\n";
144}
145
146sub read_infodb_keys
147{
148 my $infodb_file_path = shift(@_);
149 my $infodb_map = shift(@_);
150
151 print STDERR "******* mssql::read_infodb_keys() TO BE IMPLEMENTED!\n";
152 print STDERR "******* See sqlite.pm for comparable implementation that has been coded up!\n";
153}
154
155
156sub write_infodb_entry
157{
158 my $infodb_handle = shift(@_);
159 my $infodb_key = shift(@_);
160 my $infodb_map = shift(@_);
161
162 # Add the key -> value mapping into the "data" table
163 my $infodb_entry_value = "";
164 foreach my $infodb_value_key (keys(%$infodb_map))
165 {
166 foreach my $infodb_value (@{$infodb_map->{$infodb_value_key}})
167 {
168 $infodb_entry_value .= "<$infodb_value_key>" . &Encode::decode_utf8($infodb_value) . "\n";
169 }
170 }
171
172 # Prepare the query
173 my $safe_infodb_key = &mssql_safe($infodb_key);
174 my $query = "INSERT INTO " . $mssql_data_table_name . " (one_key, one_value) VALUES (N'" . $safe_infodb_key . "', N'" . &mssql_safe($infodb_entry_value) . "')";
175 dbquery($infodb_handle, $query);
176
177 # If this infodb entry is for a document, add all the interesting document metadata to the
178 # "document_metadata" table (for use by the dynamic classifiers)
179 if ($infodb_key !~ /\./ && $infodb_entry_value =~ /\<doctype\>doc\n/)
180 {
181 dbquery($infodb_handle, "DELETE FROM " . $mssql_document_metadata_table_name . " WHERE docOID=N'" . $safe_infodb_key . "'");
182
183 foreach my $infodb_value_key (keys(%$infodb_map))
184 {
185 # We're not interested in most of the automatically added document metadata
186 next if ($infodb_value_key eq "archivedir" ||
187 $infodb_value_key eq "assocfilepath" ||
188 $infodb_value_key eq "childtype" ||
189 $infodb_value_key eq "contains" ||
190 $infodb_value_key eq "docnum" ||
191 $infodb_value_key eq "doctype" ||
192 $infodb_value_key eq "Encoding" ||
193 $infodb_value_key eq "FileSize" ||
194 $infodb_value_key eq "hascover" ||
195 $infodb_value_key eq "hastxt" ||
196 $infodb_value_key eq "lastmodified" ||
197 $infodb_value_key eq "metadataset" ||
198 $infodb_value_key eq "thistype" ||
199 $infodb_value_key =~ /^metadatafreq\-/ ||
200 $infodb_value_key =~ /^metadatalist\-/);
201 foreach my $infodb_value (@{$infodb_map->{$infodb_value_key}})
202 {
203 $infodb_handle->{LongReadLen} = 65535; # Added for the encoding issue
204 my $query = "INSERT INTO " . $mssql_document_metadata_table_name . " (docOID, element, value) VALUES (N'" . $safe_infodb_key . "', N'" . &mssql_safe(&Encode::decode_utf8($infodb_value_key)) . "', N'" . &mssql_safe(&Encode::decode_utf8($infodb_value)) . "')";
205 dbquery($infodb_handle, $query);
206 }
207 }
208 }
209}
210
211
212sub write_infodb_rawentry
213{
214 my $infodb_handle = shift(@_);
215 my $infodb_key = shift(@_);
216 my $infodb_val = shift(@_);
217
218 # Prepare the query
219 my $safe_infodb_key = &mssql_safe($infodb_key);
220 my $query = "INSERT INTO " . $mssql_data_table_name . " (one_key, one_value) VALUES (N'" . $safe_infodb_key . "', N'" . &mssql_safe($infodb_val) . "')";
221 dbquery($infodb_handle, $query);
222}
223
224sub delete_infodb_entry
225{
226 my $infodb_handle = shift(@_);
227 my $infodb_key = shift(@_);
228
229 # Delete the key from the "data" table
230
231
232 # Prepare the query
233 my $safe_infodb_key = &mssql_safe($infodb_key);
234 my $query = "DELETE FROM " . $mssql_data_table_name . " WHERE one_key=N'" . $safe_infodb_key . "'";
235 dbquery($infodb_handle, $query);
236
237 # If this infodb entry is for a document, add all the interesting document metadata to the
238 # "document_metadata" table (for use by the dynamic classifiers)
239 if ($infodb_key !~ /\./)
240 {
241 # Possible for there not to be a docOID matching this infodb_key
242 # (entries are only made when <doctype> == doc
243 # Attempt to delete it, and don't complain if one isn't found
244
245 dbquery($infodb_handle, "DELETE FROM " . $mssql_document_metadata_table_name . " WHERE docOID=N'" . $safe_infodb_key . "'");
246
247 }
248}
249
250
251
252sub mssql_safe
253{
254 my $value = shift(@_);
255
256 # Escape any single quotes in the value
257 $value =~ s/\'/\'\'/g;
258
259 return $value;
260}
261
262
263sub dbquery
264{
265 my $infodb_handle = shift(@_);
266 my $sql_query = shift(@_);
267
268 # Execute the SQL statement
269 my $statement_handle = $infodb_handle->prepare($sql_query);
270 $statement_handle->execute();
271 if ($statement_handle->err)
272 {
273 print STDERR "Error:" . $statement_handle->errstr . "\n";
274 return undef;
275 }
276
277 return $statement_handle;
278}
279
280
281sub dbgetarray
282{
283 my $infodb_handle = shift(@_);
284 my $sql_query = shift(@_);
285
286 my $statement_handle = dbquery($infodb_handle, $sql_query);
287 my $return_array = [];
288
289 # Iterate through the results and push them into an array
290 if (!defined($statement_handle))
291 {
292 return [];
293 }
294
295 while ((my $temp_hash = $statement_handle->fetchrow_hashref()))
296 {
297 push(@$return_array, $temp_hash);
298 }
299
300 return $return_array;
301}
302
303
3041;
Note: See TracBrowser for help on using the repository browser.