From abb51797d8d5ebb274856e912e207a921ace478b Mon Sep 17 00:00:00 2001 From: Jonathan Druart Date: Thu, 18 Oct 2018 18:55:44 -0300 Subject: [PATCH] Bug 21610: Fix integers and dates values at Koha::Object->store level With strict SQL modes, we are facing several issues when objects are stored. The following errors can be raised by DBIx::Class when an object does not have a valid (as defined at DB level) value: - Incorrect integer value: '' for column COLUMN - Incorrect decimal value: '' for column COLUMN - Column 'COLUMN' cannot be null - Field 'COLUMN' doesn't have a default value - Incorrect date value: '' for column 'COLUMN' We already handled some of them for Koha::Patron. As we do not want to provide such changes for all Koha::* modules we are going to fix this at Koha::Object->store level in order to provide a global fix. This is related to bug 21599 (for item types) and bug 21596 (for patrons) Test plan: - Apply first patch, run the tests => Patch fail because of the previous error in Koha::ItemType->store, to make them pass you can replace $self->notforloan(0) unless $self->notforloan; with $self->notforloan(undef) unless $self->notforloan; - Apply second patch, run the tests => They fail because of dates and/or integers values - Apply third patch, run the tests => They now pass Deep code review wanted! Signed-off-by: Kyle M Hall Signed-off-by: Tomas Cohen Arazi Signed-off-by: Nick Clemens --- Koha/Object.pm | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/Koha/Object.pm b/Koha/Object.pm index 98867d29d0..65790eb411 100644 --- a/Koha/Object.pm +++ b/Koha/Object.pm @@ -121,6 +121,31 @@ Returns: sub store { my ($self) = @_; + my $columns_info = Koha::Database->new->schema->resultset( $self->_type ) + ->result_source->{_columns}; + + # Handle not null and default values for integers and dates + foreach my $col ( keys %{$columns_info} ) { + # Integers + if ( _numeric_column_type( $columns_info->{$col}->{data_type} ) ) { + # Has been passed but not a number, usually an empty string + if ( defined $self->$col and not looks_like_number( $self->$col ) ) { + if ( $columns_info->{$col}->{is_nullable} ) { + # If nullable, default to null + $self->$col(undef); + } else { + # If cannot be null, get the default value + # What if cannot be null and does not have a default value? Possible? + $self->$col($columns_info->{$col}->{default_value}); + } + } + } + elsif ( _date_or_datetime_column_type( $columns_info->{$col}->{data_type} ) ) { + # Set to null if an empty string (or == 0 but should not happen) + $self->$col(undef) unless $self->$col; + } + } + try { return $self->_result()->update_or_insert() ? $self : undef; } @@ -282,6 +307,17 @@ sub TO_JSON { return $unblessed; } +sub _date_or_datetime_column_type { + my ($column_type) = @_; + + my @dt_types = ( + 'timestamp', + 'date', + 'datetime' + ); + + return ( grep { $column_type eq $_ } @dt_types) ? 1 : 0; +} sub _datetime_column_type { my ($column_type) = @_; -- 2.39.5