From: Frank Brehm Date: Tue, 2 Mar 2010 21:22:37 +0000 (+0000) Subject: weiter Umbau auf Transaktionen X-Git-Url: https://git.uhu-banane.org/?a=commitdiff_plain;h=5fddf38d48edbd67d1eabfe004ab5b64dc7faf6f;p=books.git weiter Umbau auf Transaktionen --- diff --git a/db/changes-01.sql b/db/changes-01.sql new file mode 100644 index 0000000..ceac7ea --- /dev/null +++ b/db/changes-01.sql @@ -0,0 +1,66 @@ +-- +-- Änderungen an der Datenstruktur +-- + +-- +-- $Id$ +-- $URL$ +-- + +-- ---------------------------------------------------------------------------------- +-- Tabelle `kategorien` aufmotzen. + +ALTER TABLE `kategorien` + ADD `created_at` datetime, + ADD `created_by` int(10) unsigned, + ADD `changed_at` datetime, + ADD `changed_by` int(10) unsigned, + ADD KEY `created_by` (`created_by`), + ADD KEY `changed_by` (`changed_by`), + ADD CONSTRAINT `kategorien_ibfk_1` FOREIGN KEY (`created_by`) REFERENCES `users` (`user_id`), + ADD CONSTRAINT `kategorien_ibfk_2` FOREIGN KEY (`changed_by`) REFERENCES `users` (`user_id`); + +UPDATE `kategorien` SET + `created_at` = NOW(), + `created_by` = 1, + `changed_at` = NOW(), + `changed_by` = 1; + +COMMIT; + +ALTER TABLE `kategorien` + MODIFY `created_at` datetime NOT NULL COMMENT 'Wann erstellt', + MODIFY `created_by` int(10) unsigned NOT NULL COMMENT 'Von welcher User-Id erstellt', + MODIFY `changed_at` datetime NOT NULL COMMENT 'Wann geändert', + MODIFY `changed_by` int(10) unsigned NOT NULL COMMENT 'Von welcher User-Id geändert'; + +-- ---------------------------------------------------------------------------------- +-- Tabelle `orte` aufmotzen. + +ALTER TABLE `orte` + ADD `created_at` datetime, + ADD `created_by` int(10) unsigned, + ADD `changed_at` datetime, + ADD `changed_by` int(10) unsigned, + ADD KEY `created_by` (`created_by`), + ADD KEY `changed_by` (`changed_by`), + ADD CONSTRAINT `orte_ibfk_1` FOREIGN KEY (`created_by`) REFERENCES `users` (`user_id`), + ADD CONSTRAINT `orte_ibfk_2` FOREIGN KEY (`changed_by`) REFERENCES `users` (`user_id`); + +UPDATE `orte` SET + `created_at` = NOW(), + `created_by` = 1, + `changed_at` = NOW(), + `changed_by` = 1; + +COMMIT; + +ALTER TABLE `orte` + MODIFY `created_at` datetime NOT NULL COMMENT 'Wann erstellt', + MODIFY `created_by` int(10) unsigned NOT NULL COMMENT 'Von welcher User-Id erstellt', + MODIFY `changed_at` datetime NOT NULL COMMENT 'Wann geändert', + MODIFY `changed_by` int(10) unsigned NOT NULL COMMENT 'Von welcher User-Id geändert'; + +-- ---------------------------------------------------------------------------------- + +-- vim: noai : ts=4 fenc=utf-8 filetype=sql expandtab : diff --git a/lib/FrBr/Books/Db/Result/Kategorien.pm b/lib/FrBr/Books/Db/Result/Kategorien.pm index afb4e8d..7a5e080 100644 --- a/lib/FrBr/Books/Db/Result/Kategorien.pm +++ b/lib/FrBr/Books/Db/Result/Kategorien.pm @@ -11,13 +11,20 @@ use base 'DBIx::Class'; __PACKAGE__->load_components("Core"); __PACKAGE__->table("kategorien"); __PACKAGE__->add_columns( - "id" => { data_type => "INT", default_value => undef, is_nullable => 0, size => 10 }, - "kategorie_name" => { data_type => "VARCHAR", default_value => undef, is_nullable => 0, size => 100, }, + "id" => { data_type => "INT", default_value => undef, is_nullable => 0, size => 10 }, + "kategorie_name" => { data_type => "VARCHAR", default_value => undef, is_nullable => 0, size => 100, }, + "created_at" => { data_type => "DATETIME", default_value => undef, is_nullable => 0, size => 19, }, + "created_by" => { data_type => "INT", default_value => undef, is_nullable => 0, size => 10 }, + "changed_at" => { data_type => "DATETIME", default_value => undef, is_nullable => 0, size => 19, }, + "changed_by" => { data_type => "INT", default_value => undef, is_nullable => 0, size => 10 }, ); __PACKAGE__->set_primary_key("id"); __PACKAGE__->add_unique_constraint("kategorie_name", ["kategorie_name"]); +__PACKAGE__->belongs_to( "created_by", "FrBr::Books::Db::Result::Users", { 'foreign.user_id' => "self.created_by" },); +__PACKAGE__->belongs_to( "changed_by", "FrBr::Books::Db::Result::Users", { 'foreign.user_id' => "self.changed_by" },); + __PACKAGE__->has_many( 'buch_kategorie' => 'FrBr::Books::Db::Result::Buch2kategorie', { 'foreign.kategorie_id' => 'self.id' } ); __PACKAGE__->many_to_many( 'buecher' => 'buch_kategorie', 'buch' ); diff --git a/lib/FrBr/Books/Db/Result/Orte.pm b/lib/FrBr/Books/Db/Result/Orte.pm index 349bf96..54e9025 100644 --- a/lib/FrBr/Books/Db/Result/Orte.pm +++ b/lib/FrBr/Books/Db/Result/Orte.pm @@ -11,14 +11,20 @@ use base 'DBIx::Class'; __PACKAGE__->load_components("Core"); __PACKAGE__->table("orte"); __PACKAGE__->add_columns( - "id" => { data_type => "INT", default_value => undef, is_nullable => 0, size => 10 }, - "name" => { data_type => "VARCHAR", default_value => undef, is_nullable => 0, size => 100, }, - "descr" => { data_type => "TEXT", default_value => undef, is_nullable => 0, size => 65535, }, - "statisch" => { data_type => "ENUM", default_value => "n", is_nullable => 0, size => 1 }, + "id" => { data_type => "INT", default_value => undef, is_nullable => 0, size => 10 }, + "name" => { data_type => "VARCHAR", default_value => undef, is_nullable => 0, size => 100, }, + "descr" => { data_type => "TEXT", default_value => undef, is_nullable => 0, size => 65535, }, + "statisch" => { data_type => "ENUM", default_value => "n", is_nullable => 0, size => 1 }, + "created_at" => { data_type => "DATETIME", default_value => undef, is_nullable => 0, size => 19, }, + "created_by" => { data_type => "INT", default_value => undef, is_nullable => 0, size => 10 }, + "changed_at" => { data_type => "DATETIME", default_value => undef, is_nullable => 0, size => 19, }, + "changed_by" => { data_type => "INT", default_value => undef, is_nullable => 0, size => 10 }, ); __PACKAGE__->set_primary_key("id"); __PACKAGE__->add_unique_constraint("name", ["name"]); +__PACKAGE__->belongs_to( "created_by", "FrBr::Books::Db::Result::Users", { 'foreign.user_id' => "self.created_by" },); +__PACKAGE__->belongs_to( "changed_by", "FrBr::Books::Db::Result::Users", { 'foreign.user_id' => "self.changed_by" },); __PACKAGE__->has_many( 'buecher' => 'FrBr::Books::Db::Result::Buecher', { 'foreign.orts_id' => 'self.id' } ); diff --git a/lib/FrBr/Books/Plugin/Category.pm b/lib/FrBr/Books/Plugin/Category.pm index f2157e5..656b444 100644 --- a/lib/FrBr/Books/Plugin/Category.pm +++ b/lib/FrBr/Books/Plugin/Category.pm @@ -53,9 +53,15 @@ Listenlänge einer Seite (wenn seitenweise gewünscht wird). Rueckgabe: Im skalaren Kontext eine Array-Ref von Hash-Refs mit allen Kategorien, die den uebergebenen Suchkriterien entsprechen: $res = [ - { 'id' => 1, - 'name' => 'Science Fiction', - 'count_books' => 22, + { 'id' => 1, + 'name' => 'Science Fiction', + 'count_books' => 22, + 'created_at' => '2010-02-22 12:13:14', + 'id_created_by' => 1, + 'name_created_by' => 'Frank Brehm', + 'changed_at' => '2010-02-29 13:14:15', + 'id_changed_by' => 2, + 'name_changed_by' => 'Doris Hennig', }, { 'id' => 2, ... @@ -105,18 +111,38 @@ sub b_get_category_list { $c->log->debug( get_output_string( $K, "Anzahl gefundene Kategorien: ", $anzahl_kategorien ) ) if $c->stash->{'debug_level'} >= 2; my $other_params = {}; - $other_params->{'order_by'} = [ 'kategorie_name' ]; + $other_params->{'join'} = [ + 'buch_kategorie', + 'created_by', + 'changed_by', + ]; + $other_params->{'order_by'} = [ 'me.kategorie_name' ]; $other_params->{'select'} = [ 'me.id', 'me.kategorie_name', - { 'count' => 'buch_kategorie.id' } + 'me.created_by', + 'created_by.vorname', + 'created_by.nachname', + 'me.created_at', + 'me.changed_by', + 'changed_by.vorname', + 'changed_by.nachname', + 'me.changed_at', + { 'count' => 'buch_kategorie.id' }, ]; $other_params->{'as'} = [ 'id', 'kategorie_name', + 'created_by', + 'created_by_vorname', + 'created_by_nachname', + 'created_at', + 'changed_by', + 'changed_by_vorname', + 'changed_by_nachname', + 'changed_at', 'count_books', ]; - $other_params->{'join'} = [ 'buch_kategorie']; $other_params->{'group_by'} = [ 'me.id' ]; if ( $page ) { @@ -125,11 +151,28 @@ sub b_get_category_list { } for my $cat_rs ( $c->model('Schema::Kategorien')->search( $search_params, $other_params )->all() ) { + + my $vorname = ''; my $cat = {}; + $cat->{'id'} = $cat_rs->id(); $cat->{'name'} = $cat_rs->kategorie_name(); $cat->{'count_books'} = $cat_rs->get_column('count_books'); + + $cat->{'id_created_by'} = $cat_rs->get_column('created_by'); + $cat->{'created_at'} = $cat_rs->get_column('created_at'); + $cat->{'name_created_by'} = $cat_rs->get_column('created_by_nachname'); + $vorname = $cat_rs->get_column('created_by_vorname'); + $cat->{'name_created_by'} = $vorname . ' ' . $cat->{'name_created_by'} if $vorname; + + $cat->{'id_changed_by'} = $cat_rs->get_column('changed_by'); + $cat->{'changed_at'} = $cat_rs->get_column('changed_at'); + $cat->{'name_changed_by'} = $cat_rs->get_column('changed_by_nachname'); + $vorname = $cat_rs->get_column('changed_by_vorname'); + $cat->{'name_changed_by'} = $vorname . ' ' . $cat->{'name_changed_by'} if $vorname; + push @$list, $cat; + } return ( wantarray ? ( $list, 0 ) : $list ) unless scalar @$list; @@ -284,33 +327,84 @@ sub b_save_category { $c->log->debug( $K . "aufgerufen." ) if $c->stash->{'debug_level'} > 2; + my $schema = $c->model('Schema')->{'schema'}; my $storage = $c->model('Schema')->storage; - my $save_func = sub { - my ( $storage, $dbh, $category_id, $cat_name ) = @_; - my $sql = <debug() ) { - my $text = $sql; - $text =~ s/\s+$//; - $text .= ": " . join( ", ", map { $dbh->quote($_) } ( $category_id, $cat_name, $cat_name ) ) . "\n"; - warn $text; + my $row = {}; + my $search_params = {}; + + my $tmp = $cat->{'name'}; + $tmp = '' unless defined $tmp; + $tmp =~ s/^\s+//; + $tmp =~ s/\s+$//; + $row->{'kategorie_name'} = $tmp; + + if ( $cat->{'id'} ) { + $search_params->{'kategorie_name'} = $row->{'kategorie_name'}; + $search_params->{'id'} = { '!=' => $cat->{'id'} }; + $c->log->debug( get_output_string( $K, "Suche nach doppelter Kategorie mit: ", $search_params ) ); + if ( $c->model('Schema::Kategorien')->count( $search_params ) ) { + die sprintf( "Die Kategorie '%s' existiert bereits.\n", $row->{'kategorie_name'} ); } + $row->{'id'} = $cat->{'id'}; + } + + my $user_id = $c->stash->{'current_user_id'} || 1; + $row->{'changed_at'} = \'NOW()'; + $row->{'changed_by'} = $user_id; + + $c->log->debug( get_output_string( $K, "Zu speichernde Kategorie: ", $row ) ) if $c->stash->{'debug_level'} >= 3; + my $id = undef; + + # Der Transaktionscode ... + my $txn_code = sub { + + my $key_hash = {}; + $key_hash->{'key'} = $row->{'id'} ? 'primary' : 'kategorie_name'; + + my $rs = $c->model('Schema::Kategorien')->update_or_new( $row, $key_hash ); - my $sth = $dbh->prepare($sql); - $sth->execute( $category_id, $cat_name, $cat_name ); + if ( $rs->in_storage() ) { + + $c->log->debug( $K . "Die Kategorie gibt es schon ..." ); + + $rs->set_column( 'id' => \'LAST_INSERT_ID(`id`)' ); + my $spalten = {}; + %$spalten = $rs->get_columns(); + $c->log->debug( get_output_string( $K, "Die Spalten der Kategorie: ", $spalten ) ); + undef $spalten; + + $rs->update(); + + } + else { + $c->log->debug( $K . "Neue Kategorie ..." ); + $rs->set_column( 'created_by' => $user_id ); + $rs->set_column( 'created_at' => \'NOW()' ); + my $spalten = {}; + %$spalten = $rs->get_columns(); + $c->log->debug( get_output_string( $K, "Die Spalten der Kategorie: ", $spalten ) ); + undef $spalten; + + $rs->insert(); + } + + $id = $storage->last_insert_id(); + + }; + + # Und ab ... + eval { + $schema->txn_do($txn_code); }; - $storage->dbh_do( $save_func, $cat->{'id'}, $cat->{'name'} ); + if ($@) { # Transaction failed + my $msg = $@ =~ /Rollback failed/i ? "Rollback nicht erfolgreich!" : $@; + die $msg . "\n"; + return undef; + } - return $storage->last_insert_id(); + return $id; } diff --git a/lib/FrBr/Books/Plugin/Ort.pm b/lib/FrBr/Books/Plugin/Ort.pm index bb4366a..4ba1092 100644 --- a/lib/FrBr/Books/Plugin/Ort.pm +++ b/lib/FrBr/Books/Plugin/Ort.pm @@ -53,12 +53,18 @@ Rueckgabe: Eine Array-Ref von Hash-Refs mit allen Aufbewahrungsorten, die den ue $res = [ { - 'id' => 1, - 'name' => 'Ausgeliehen', - 'descr' => '', - 'statisch' => 'y', - 'count_books' => 16, - 'books' => [ + 'id' => 1, + 'name' => 'Ausgeliehen', + 'descr' => '', + 'statisch' => 'y', + 'count_books' => 16, + 'created_at' => '2010-02-22 12:13:14', + 'id_created_by' => 1, + 'name_created_by' => 'Frank Brehm', + 'changed_at' => '2010-02-29 13:14:15', + 'id_changed_by' => 2, + 'name_changed_by' => 'Doris Hennig', + 'books' => [ { 'id' => 8, 'title' => 'Die Elfen', @@ -136,22 +142,42 @@ sub b_get_ortsliste { $c->log->debug( get_output_string( $K, "Anzahl gefundene Orte: ", $anzahl_orte ) ) if $c->stash->{'debug_level'} >= 2; my $other_params = {}; - $other_params->{'order_by'} = [ 'name' ]; + $other_params->{'join'} = [ + 'buecher', + 'created_by', + 'changed_by', + ]; + $other_params->{'order_by'} = [ 'me.name' ]; $other_params->{'select'} = [ 'me.id', 'me.name', 'me.descr', 'me.statisch', - { 'count' => 'buecher.id' } + 'me.created_by', + 'created_by.vorname', + 'created_by.nachname', + 'me.created_at', + 'me.changed_by', + 'changed_by.vorname', + 'changed_by.nachname', + 'me.changed_at', + { 'count' => 'buecher.id' }, ]; $other_params->{'as'} = [ 'id', 'name', 'descr', 'statisch', + 'created_by', + 'created_by_vorname', + 'created_by_nachname', + 'created_at', + 'changed_by', + 'changed_by_vorname', + 'changed_by_nachname', + 'changed_at', 'count_books', ]; - $other_params->{'join'} = [ 'buecher']; $other_params->{'group_by'} = [ 'me.id' ]; if ( $page ) { @@ -160,19 +186,35 @@ sub b_get_ortsliste { } for my $ort_rs ( $c->model('Schema::Orte')->search( $search_params, $other_params )->all() ) { + + my $vorname = ''; my $ort = {}; + $ort->{'id'} = $ort_rs->id(); $ort->{'name'} = $ort_rs->name(); $ort->{'descr'} = $ort_rs->descr(); $ort->{'statisch'} = $ort_rs->statisch(); $ort->{'count_books'} = $ort_rs->get_column('count_books'); + + $ort->{'id_created_by'} = $ort_rs->get_column('created_by'); + $ort->{'created_at'} = $ort_rs->get_column('created_at'); + $ort->{'name_created_by'} = $ort_rs->get_column('created_by_nachname'); + $vorname = $ort_rs->get_column('created_by_vorname'); + $ort->{'name_created_by'} = $vorname . ' ' . $ort->{'name_created_by'} if $vorname; + + $ort->{'id_changed_by'} = $ort_rs->get_column('changed_by'); + $ort->{'changed_at'} = $ort_rs->get_column('changed_at'); + $ort->{'name_changed_by'} = $ort_rs->get_column('changed_by_nachname'); + $vorname = $ort_rs->get_column('changed_by_vorname'); + $ort->{'name_changed_by'} = $vorname . ' ' . $ort->{'name_changed_by'} if $vorname; + push @$list, $ort; + } return ( wantarray ? ( $list, 0 ) : $list ) unless scalar @$list; return ( wantarray ? ( $list, $anzahl_orte ) : $list ) unless $params->{'get_books'}; - for my $ort ( @$list ) { $ort->{'books'} = []; @@ -310,8 +352,95 @@ sub b_save_ort { $c->log->debug( $K . "aufgerufen." ) if $c->stash->{'debug_level'} > 2; + my $schema = $c->model('Schema')->{'schema'}; my $storage = $c->model('Schema')->storage; + my $row = {}; + my $search_params = {}; + + my $tmp = $ort->{'name'}; + $tmp = '' unless defined $tmp; + $tmp =~ s/^\s+//; + $tmp =~ s/\s+$//; + $row->{'name'} = $tmp; + + if ( $ort->{'id'} ) { + $search_params->{'name'} = $row->{'name'}; + $search_params->{'id'} = { '!=' => $ort->{'id'} }; + $c->log->debug( get_output_string( $K, "Suche nach doppeltem Aufbewahrungsort mit: ", $search_params ) ); + if ( $c->model('Schema::Orte')->count( $search_params ) ) { + die sprintf( "Der Aufbewahrungsort '%s' existiert bereits.\n", $row->{'name'} ); + } + $row->{'id'} = $ort->{'id'}; + } + + $tmp = $ort->{'descr'}; + $tmp = '' unless defined $tmp; + $tmp =~ s/^\s+//; + $tmp =~ s/\s+$//; + $row->{'descr'} = defined $tmp ? $tmp : undef; + + $row->{'statisch'} = to_bool( $ort->{'statisch'} ) ? 'y' : 'n'; + + my $user_id = $c->stash->{'current_user_id'} || 1; + $row->{'changed_at'} = \'NOW()'; + $row->{'changed_by'} = $user_id; + + $c->log->debug( get_output_string( $K, "Zu speichernder Aufbewahrungsort: ", $row ) ) if $c->stash->{'debug_level'} >= 3; + my $id = undef; + + # Der Transaktionscode ... + my $txn_code = sub { + + my $key_hash = {}; + $key_hash->{'key'} = $row->{'id'} ? 'primary' : 'name'; + + my $rs = $c->model('Schema::Orte')->update_or_new( $row, $key_hash ); + + if ( $rs->in_storage() ) { + + $c->log->debug( $K . "Den Aufbewahrungsort gibt es schon ..." ); + + $rs->set_column( 'id' => \'LAST_INSERT_ID(`id`)' ); + my $spalten = {}; + %$spalten = $rs->get_columns(); + $c->log->debug( get_output_string( $K, "Die Spalten des Aufbewahrungsorts: ", $spalten ) ); + undef $spalten; + + $rs->update(); + + } + else { + $c->log->debug( $K . "Neuer Aufbewahrungsort ..." ); + $rs->set_column( 'created_by' => $user_id ); + $rs->set_column( 'created_at' => \'NOW()' ); + my $spalten = {}; + %$spalten = $rs->get_columns(); + $c->log->debug( get_output_string( $K, "Die Spalten des Aufbewahrungsorts: ", $spalten ) ); + undef $spalten; + + $rs->insert(); + } + + $id = $storage->last_insert_id(); + + }; + + # Und ab ... + eval { + $schema->txn_do($txn_code); + }; + + if ($@) { # Transaction failed + my $msg = $@ =~ /Rollback failed/i ? "Rollback nicht erfolgreich!" : $@; + die $msg . "\n"; + return undef; + } + + return $id; + +=pod + my $save_func = sub { my ( $storage, $dbh, $orts_id, $orts_name, $orts_desc, $statisch ) = @_; my $sql = <last_insert_id(); +=cut + } #-----------------------------------------------------------------------------------