summaryrefslogtreecommitdiffstats
path: root/config-db/OpenSLX/MetaDB/CSV.pm
diff options
context:
space:
mode:
Diffstat (limited to 'config-db/OpenSLX/MetaDB/CSV.pm')
-rw-r--r--config-db/OpenSLX/MetaDB/CSV.pm127
1 files changed, 127 insertions, 0 deletions
diff --git a/config-db/OpenSLX/MetaDB/CSV.pm b/config-db/OpenSLX/MetaDB/CSV.pm
new file mode 100644
index 00000000..b291e33d
--- /dev/null
+++ b/config-db/OpenSLX/MetaDB/CSV.pm
@@ -0,0 +1,127 @@
+package OpenSLX::MetaDB::CSV;
+
+use vars qw(@ISA $VERSION);
+@ISA = ('OpenSLX::MetaDB::DBI');
+$VERSION = 1.01; # API-version . implementation-version
+
+################################################################################
+### This class provides a MetaDB backend for CSV files (CSV = comma separated
+### files).
+### - each table will be stored into a CSV file.
+### - by default all files will be created inside a 'openslxdata-csv' directory.
+################################################################################
+use strict;
+use Carp;
+use Fcntl qw(:DEFAULT :flock);
+use OpenSLX::Basics;
+use OpenSLX::MetaDB::DBI $VERSION;
+
+my $superVersion = $OpenSLX::MetaDB::DBI::VERSION;
+if ($superVersion < $VERSION) {
+ confess _tr('Unable to load module <%s> (Version <%s> required, but <%s> found)',
+ 'OpenSLX::MetaDB::DBI', $VERSION, $superVersion);
+}
+################################################################################
+### implementation
+################################################################################
+sub new
+{
+ my $class = shift;
+ my $self = {};
+ return bless $self, $class;
+}
+
+sub connectConfigDB
+{
+ my $self = shift;
+
+ my $dbSpec = $openslxConfig{'db-spec'};
+ if (!defined $dbSpec) {
+ # build $dbSpec from individual parameters:
+ my $dbBasepath = $openslxConfig{'db-basepath'};
+ my $dbDatadir = $openslxConfig{'db-datadir'} || 'openslxdata-csv';
+ my $dbPath = "$dbBasepath/$dbDatadir";
+ mkdir $dbPath unless -e $dbPath;
+ $dbSpec = "f_dir=$dbPath";
+ }
+ vlog 1, "trying to connect to CSV-database <$dbSpec>";
+ $self->{'dbh'} = DBI->connect("dbi:CSV:$dbSpec", undef, undef,
+ {PrintError => 0})
+ or confess _tr("Cannot connect to database <%s> (%s)"),
+ $dbSpec, $DBI::errstr;
+}
+
+sub quote
+{ # DBD::CSV has a buggy quoting mechanism which can't cope with backslashes
+ # so we reimplement the quoting ourselves...
+ my $self = shift;
+ my $val = shift;
+
+ $val =~ s[(['])][\\$1]go;
+ return "'$val'";
+}
+
+sub generateNextIdForTable
+{ # CSV doesn't provide any mechanism to generate IDs, we just...
+ my $self = shift;
+ my $table = shift;
+
+ return 1 unless defined $table;
+
+ # now fetch the next ID from a table-specific file:
+ my $dbh = $self->{'dbh'};
+ my $idFile = "$dbh->{'f_dir'}/id-$table";
+ sysopen(IDFILE, $idFile, O_RDWR|O_CREAT)
+ or confess _tr(q[Can't open ID-file <%s> (%s)], $idFile, $!);
+ flock(IDFILE, LOCK_EX)
+ or confess _tr(q[Can't lock ID-file <%s> (%s)], $idFile, $!);
+ my $nextID = <IDFILE>;
+ if (!$nextID) {
+ # no ID information available, we protect against users having
+ # deleted the ID-file by fetching the highest ID from the DB:
+ $nextID = 1+$self->_doSelect("SELECT max(id) AS id FROM $table", 'id');
+ }
+ seek(IDFILE, 0, 0)
+ or confess _tr(q[Can't to seek ID-file <%s> (%s)], $idFile, $!);
+ truncate(IDFILE, 0)
+ or confess _tr(q[Can't truncate ID-file <%s> (%s)], $idFile, $!);
+ print IDFILE $nextID+1
+ or confess _tr(q[Can't update ID-file <%s> (%s)], $idFile, $!);
+ close(IDFILE);
+
+ return $nextID;
+}
+
+sub schemaDeclareTable
+{ # explicitly set file name for each table such that it makes
+ # use of '.csv'-extension
+ my $self = shift;
+ my $table = shift;
+
+ my $dbh = $self->{'dbh'};
+ $dbh->{'csv_tables'}->{"$table"} = { 'file' => "${table}.csv"};
+}
+
+sub schemaRenameTable
+{ # renames corresponding id-file after renaming the table
+ my $self = shift;
+ my $oldTable = shift;
+ my $newTable = shift;
+
+ $self->schemaDeclareTable($newTable);
+ $self->SUPER::schemaRenameTable($oldTable, $newTable, @_);
+ my $dbh = $self->{'dbh'};
+ rename "$dbh->{'f_dir'}/id-$oldTable", "$dbh->{'f_dir'}/id-$newTable";
+}
+
+sub schemaDropTable
+{ # removes corresponding id-file after dropping the table
+ my $self = shift;
+ my $table = shift;
+
+ $self->SUPER::schemaDropTable($table, @_);
+ my $dbh = $self->{'dbh'};
+ unlink "$dbh->{'f_dir'}/id-$table";
+}
+
+1; \ No newline at end of file