
=head1 check_overlap

überprüfe, ob ein bestimmtes Anfangs- und/oder Enddatum bei einem Objekt in die
Datenbank eingetragen werden darf, oder ob sich dadurch unzulässig Zeiträume
überschneiden würden.

=head2 Argumente

=over 4

=item $tabelle

Name der Datenbank-Tabelle

=item $indexfeld

Spaltenname, in dem der Indexwert steht, anhand dessen das Objekt
eindeutig erkennbar ist.

=item $indexwert

Nr. des Objekts laut diesem Indexfeld; C<undef>, falls neues Objekt

=item $selektorfeld

Name des Tabellenfeldes, anhand dessen die Objekte ausgewählt werden sollen,
mit denen verglichen werden muss, ggf. mehrere durch Kommata getrennt.

=item $beginn

gewünschtes Start-Datum für das neue Objekt als Unix-Timestamp, ggf. C<undef>.
("0" wird als Synonym für "schon immer" verstanden.)

=item $ende

gewünschtes Ende-Datum für das neue Objekt als Unix-Timestamp, ggf. C<undef>.
("0" wird als Synonym für "endet nicht" verstanden.)

=item @keys (optional)

Schlüsselwerte für das/die zu vergleichenden Selektor-Feld(er);
ohne dieses Argument weden die anhand von C<$indexfeld>/C<$indexwert> ermittelt.

=back

=head2 Beispiel

    check_overlap(domainkunde=>id=>2260,'domain',undef,1059489990)

=head2 Ergebnis

I<Falsch>, falls die Eintragung so möglich ist,
sonst die ID (also der Indexwert) des ersten Objekts,
mit dem sich eine Überschneidung ergeben würde.

=back

=cut

use utf8;
use warnings; no warnings "redefine";
use strict;
use Dbase::Help qw(DoFn DoSelect qquote);
use Fehler qw(problem);

sub check_overlap($$$$$$;@) {
	my ( $tabelle, $id_feld, $id, $sel_feld, $beginn, $ende, @keys ) = @_;
	@keys = DoFn "SELECT $sel_feld FROM $tabelle WHERE $id_feld = $id"
	  or return problem
	  "In der Tabelle $tabelle gibt es keinen Eintrag mit $id_feld=$id."
	  unless @keys;
	return if grep !defined, @keys;    # s. RT#422142

	my $sel;
	{
		my @sel = split /\s*,\s*/, $sel_feld;
		return problem 'Interner Fehler: '
		               . @sel  . ' Selektor-Feld' . (@sel  != 1 && 'er') . ' (' . join('|',@sel ) . ') vs. '
		               . @keys . ' Schlüsselwert' . (@keys != 1 && 'e' ) . ' (' . join('|',@keys) . ').'
		  if @sel != @keys;
		@keys = map { (defined $_) ? "= ${\qquote $_}" : "is NULL" } @keys;
		$sel = join ' AND ', map "$_ ${\ shift @keys}", @sel;
	}
	my $return_value = '';

	# Entweder das erste Objekt endet, bevor das zweite beginnt,
	# oder umgekehrt, oder wir haben eine Überschneidung.
	$ende = $ende ? "OR beginn >= $ende" : "";
	return DoFn <<_;
		SELECT   $id_feld
		FROM     $tabelle
		WHERE    $sel AND $id_feld != $id
		  AND NOT ((ende is not null and ende <= $beginn) $ende )
		ORDER BY $id_feld
		LIMIT 1
_
}

1
