Skip to content

Instantly share code, notes, and snippets.

@rponte
Last active January 19, 2022 16:21
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rponte/a6631de006f3613facb0427409bf9b73 to your computer and use it in GitHub Desktop.
Save rponte/a6631de006f3613facb0427409bf9b73 to your computer and use it in GitHub Desktop.
PL/SQL: exemplo de Objeto com estado e comportamentos no Oracle - Intervalo (Date Range)
set serveroutput on
declare
p1 Intervalo_t;
p2 Intervalo_t;
p3 Intervalo_t;
begin
p1 := new Intervalo_t(inicio => Date'2019-05-01'
,fim => Date'2019-06-15');
p2 := new Intervalo_t(inicio => Date'2019-06-01'
,fim => Date'2019-06-30');
if p1.conflita_com(p2) then
p3 := p1.intervalo_conflitante_com(p2);
Dbms_Output.put_line('conflito=' || p3.to_string);
end if;
end;
--------------------------------------------------------
-- Representa um Intervalo de datas (Date Range)
-- https://docs.oracle.com/cd/B10501_01/appdev.920/a96624/10_objs.htm
--------------------------------------------------------
create or replace type Intervalo_t FORCE as Object (
inicio Date
,fim Date
-- Construtores
,Constructor Function Intervalo_t(inicio Date, fim Date) Return Self as Result
-- Metodos
,Member Function is_valido Return Boolean
,Member Function conflita_com(outro_intervalo Intervalo_t) Return Boolean
,Member Function intervalo_conflitante_com(outro_intervalo Intervalo_t) Return Intervalo_t
,Member Function to_string Return Varchar2
);
/
create or replace type BODY Intervalo_t as
/**
* Construtor default que se responsabiliza de truncar as datas, mas
* NAO valida integridade das datas informadas
*/
Constructor Function Intervalo_t(inicio Date, fim Date) Return Self as Result as
begin
self.inicio := trunc(inicio);
self.fim := trunc(fim);
RETURN;
end;
/**
* Verifica se eh um intervalo valido
*/
Member Function is_valido Return Boolean is
begin
if (self.inicio is null OR self.fim is null) then
return false;
end if;
return self.inicio <= self.fim;
end;
/**
* Verifica se ha intersecao (overlap) entre os intervalos
* http://wiki.c2.com/?TestIfDateRangesOverlap
*/
Member Function conflita_com(outro_intervalo Intervalo_t) Return Boolean is
begin
if NOT (self.is_valido() AND outro_intervalo.is_valido()) then
return false;
end if;
return (self.inicio <= outro_intervalo.fim
AND outro_intervalo.inicio <= self.fim);
end;
/**
* Encontra intervalo conflitante (overlap) entre os intervalos ou retorna
* NULL caso nao exista conflito
*/
Member Function intervalo_conflitante_com(outro_intervalo Intervalo_t) Return Intervalo_t is
l_inicio Date;
l_fim Date;
begin
if NOT self.conflita_com(outro_intervalo) then
return null;
end if;
l_inicio := greatest(self.inicio, outro_intervalo.inicio);
l_fim := least (self.fim , outro_intervalo.fim);
return new Intervalo_t(l_inicio, l_fim);
end;
/**
* Retorna objeto representado como string
*/
Member Function to_string Return Varchar2 is
begin
return Utl_lms.format_message('Intervalo_t(inicio=%s, fim=%s)'
, to_char(self.inicio, 'yyyy-mm-dd')
, to_char(self.fim , 'yyyy-mm-dd')
);
end;
end;
/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment