[Rt-commit] rt branch, master, updated. rt-4.1.13-205-ge5943f6

Thomas Sibley trs at bestpractical.com
Wed Jul 3 22:06:54 EDT 2013


The branch, master has been updated
       via  e5943f653df8c758b04cb3f010cd724283c3db81 (commit)
       via  005f3a280119b7fe99082fd28fa7d72bea9bad53 (commit)
       via  dd88aead7846fcc5ca9fdd36870117e5ed1d7809 (commit)
       via  e1538530daebfae89bae81234943997c01c9c713 (commit)
       via  f4fefd1c2141c0b6d1edb947f0ef4c04662e7221 (commit)
       via  390fb60c1d7c63c6dbf691bf4f7605b0563d6ab4 (commit)
       via  71a5e134b987302bc5e63ad161dc7ede1b6bd25a (commit)
       via  3ee4909ca08accd3ff6a3751f694acf258e6aea7 (commit)
       via  af1b6bf7a446f45e335a4f09633b7dd5584e386d (commit)
       via  f487fd06bb9326f8feaf4cfaeb687e0c8790a557 (commit)
       via  15ffd62c9807f6454c2f068bc0d41358bce5cae7 (commit)
       via  63da75bd9659ef0e8da9be26a4b79f965fcd4181 (commit)
       via  a5c768cc9a441e3e60d9b796f846087dbaf267db (commit)
       via  f642844c5adb271344ab018a8e465d13e236bd9d (commit)
       via  84a913a13124970ec107851fd3585c8bb179192b (commit)
       via  ed8b7781912f6d7db47c06b1797e132a634b160b (commit)
       via  f3b33e9bfb221ba8bd25eaaccdc769c7928a5969 (commit)
       via  b9ba8c77ae18d036fca4e9c712d45796b91760b1 (commit)
       via  655573291cc7f07de71045576b2b9804e1dd7ea8 (commit)
       via  5d1a7e632c1e2c68ef3a2a3a860601ce977ffbde (commit)
       via  9170af4debc2cfb89d1aa64d0062e47e4d4f5835 (commit)
       via  c4154e468dac5f402a9603a6d3a5effcd909e8ea (commit)
       via  319e8ad2c9ff029a53e71a0ba4fe004afa1894c5 (commit)
       via  885a64637c3e704b1961a562ebd1c44105ac767c (commit)
       via  bd23ffb9d47d20a3c7ce54bd815347b4d9b8e3cb (commit)
       via  f25f2d9c24f7d0426bfa5b1b078e955935975fe1 (commit)
       via  9002a0cd4d8d408cba524f9208f8743a130598ef (commit)
       via  26aff0330d61d037f01e7c4056155ea579183fbd (commit)
       via  479935d3716ca9625d2bc242be737d771d81fc4b (commit)
       via  1a30e4fe25543d0e331f74948d8b1cc58c40eeec (commit)
       via  96da8956b3a01a5d431bf8b73dba7e5f5ce42771 (commit)
       via  b184ecbcd520715597225061a6c51c704e32f233 (commit)
       via  d68f64a76b20828ca63ce64186a34826b2f91f50 (commit)
       via  a4d38fb57d7e6350625b10cfe8131fb49ddd0fc7 (commit)
       via  78a20e70a88429a5b6686a3d9c2bf26dc708b1c9 (commit)
       via  a251473e8d190580dd7d2f5b82ac28d140f1e598 (commit)
       via  a98515b4a9ede8645cbf399cc778166bd22d8df7 (commit)
       via  865b37eaefffcfc656269291511ea42a54e8e6f4 (commit)
       via  a4436d0dc6d8d94caabb28aec05055e4c6768065 (commit)
       via  5de477093121ab90f4720b040ce9e532095aa73c (commit)
       via  a1127c88653527f1f16f4705067b987e3598c62b (commit)
       via  ec101790ee2f0f1f9f302d23a708b749653c3875 (commit)
       via  77cb586346cd63262e0d198dee740dd8504f1a02 (commit)
       via  fa5178a2a27365cdace20aed65ae66346cd7eea1 (commit)
       via  c6bfe58fd4ca447901b4f0542bdbdba0e9fabf5d (commit)
       via  e936ea928eb9cd89c7458389adeae5224b327ca7 (commit)
       via  68b4ac2ddf90442117aacc264e595389cb577272 (commit)
       via  b2d0d67be60c09a1d29881892b9b3e3b6de85c53 (commit)
       via  c0b94a16264a0e996475eb63090a3adfeafb8ae3 (commit)
       via  eff03c293e603ee6366ff051f7ea4d78ec8e398a (commit)
       via  738c076359536a180f55b9dda85a0d160184a53b (commit)
       via  4fa2481ba84980b2715550951016f131257cdc0f (commit)
       via  86d7b4d2fb4c2d9e989ecd4fd5149fd0e6528774 (commit)
       via  153d7b8f4e232d4a44de51abf554735cb14dc8c2 (commit)
       via  42059c2b0a4bc316bc88802d65ea6ab986290199 (commit)
       via  7256b2b5064439c6935b3e6bc2959b8a3ae3b946 (commit)
       via  ea68c171ff90b3bd5ac362080ae96655a5c3affa (commit)
       via  2ef014f419c2f7b52d056ed11e7f2b6f35eacb8b (commit)
       via  717aa384c9ad66f51e944c0a06ebf60a5e978650 (commit)
       via  c8bdf1ffcfd81c7920370e04f2f7cfc0e1566f36 (commit)
       via  d81a4fa7a533128e7724e661b25f622c2a5854be (commit)
       via  4cf816d416df911e9acb99337c7c473848d4d51d (commit)
       via  6ec5437c01c0d062399038dd667e101896e30cc2 (commit)
       via  2e1b70c47921e739ab871bb5c00859c16df7746d (commit)
       via  8b1d371b41979d9ffaa290194b23691978bacd40 (commit)
       via  5ffd77f2f6bf1eda093aaa1693ab1fcdc01491b3 (commit)
       via  83d5bd6d0ef55ee814fe4dce3350bd8d714b651c (commit)
       via  7cf22661971aeb598ec0062bc5c25f9f77c0be8f (commit)
       via  1ef4c5e9616c6a1c5e22d05e91b65806a7764c2f (commit)
       via  d386ec08432483555196554defa70b12719feb3a (commit)
       via  9f7736f6d105020f76e0e9972e9215c6f54481ea (commit)
       via  f3737d2c6f25e9c14a45b75653d509361a4aeec0 (commit)
       via  b9660bea6e145091612e77194cdf603d879f2776 (commit)
       via  a9e8bb8127620cb43acc2b238a521960b99f87fa (commit)
       via  a16828dd2b7cb5a076d28179b21cb00853d8c7cb (commit)
       via  9f0521176943f23435b968ee18313359280dc74a (commit)
       via  74eb701ab450625da462d8063ee59427c9d12f4f (commit)
       via  59ec3a43fe99016fade26ca567b0738677700e83 (commit)
       via  3b1b3f2ae247c5b8d5d2c7e370a8a745a5c8529e (commit)
       via  87559a8f86d3f66f656930dbfc93cd6071718999 (commit)
       via  696a5d935a59bb5ee95dcfced8f82f4698ec58af (commit)
       via  bdb225a77f2cbecc38ebd37ee95fd9cf32aa8f7b (commit)
       via  c59d4eeb001d3b2f30a2140e9ddeec4ffd2ce023 (commit)
       via  c556fba6d352352f28da4031592844742e2129b8 (commit)
       via  0e0f6359e5ffd5f909d9df922998feeb1f222c80 (commit)
       via  50ab54fddd8ffca1f85fc6053a105425818f6050 (commit)
       via  115f373f5c874a7418fd8c98dab440166ec2055d (commit)
       via  c492ac54707c6e53c49a5884949f22f4c51b945e (commit)
       via  7bd405b96c1bc3f57f476e6c5143179ee40e1e59 (commit)
       via  0e830cdb5b10f00f27f85a8a1db34d8f7b4ff07b (commit)
       via  b8f6c68c282e0b6604533139cdeaa5a28715bfb6 (commit)
       via  3370c9150ebac71e54e0b804ec0db548e7d16961 (commit)
       via  2012462b0303ea050e9b8bb9999bab9b9ad40238 (commit)
       via  1846886d40310d6e69108364500bc6007fbcdc16 (commit)
       via  52ac9803e5966a7438b68788aba9d80abfbca41f (commit)
       via  60069cea2c20a5f85977c3b726841a68521a1a20 (commit)
       via  7e4b83ca7e0f2c03f49a43e1c0ed310d15bf5ea3 (commit)
       via  3c6fede42a35638b8951a29255edea5888b8f3be (commit)
       via  704fa93ff796ba72b7254a368a3bf2492234150c (commit)
       via  fc6a42d2fbd4916602816a443489d5fb83608eee (commit)
       via  5fbdd35222dc241eb24ad0c191f17516dad0160f (commit)
       via  50ee65f01526ba9840e4a3eae411426822f232a8 (commit)
       via  5532b316ac29707a25429ce2e665531adcbffbe2 (commit)
       via  15c07226f3d15e444ce4f69dc21458678ca162f0 (commit)
       via  658a3b827913c0630ec67bb00f72c662d77e1066 (commit)
       via  0fc3e2a1d6fd24e50e528223ee4895186d2427e6 (commit)
       via  0a6fca96562b4ddcdeceee3f74fa99113f856343 (commit)
       via  59370443dcf60489429e0994697067f4be9a4f3b (commit)
       via  945624601c283e7f2f35941cef2e3f606cc0ee9d (commit)
       via  b0bb95b33021bf0361f595a0d843f58a4e2b9b1d (commit)
       via  f43442871fa53cac4301043ae6ba5620b7786d96 (commit)
       via  88b80480163b19546eb8aae51bbf6d22bec46eaf (commit)
       via  eaf36218f6014a3d5d69d93f94a5e0543d914113 (commit)
       via  a3bae3d2d707713ee4604a0cae2da678c59cc65c (commit)
       via  cd5fda36475464fd9e49610e21ed37cbd5733067 (commit)
       via  a41f71068ace70ad62ed280eb0b03273140cec91 (commit)
       via  d3654e25c097d9015a9a689a997721000a2ea3d6 (commit)
       via  e8cce975142faa0e2eff325d10bd603a2c1678a0 (commit)
       via  6157ebcf349f8c0e0f4b788ed308b6c129f2bce6 (commit)
       via  abcc3ca8d436e0e07158741d9d36456e1a447ce7 (commit)
       via  54dfec479f3eb2930e2967ecd7c9c36b8e66c7b6 (commit)
       via  25e35201ead1975db3f7e25a5287739520e40208 (commit)
       via  02d7a7b01d6360d52a8cd4d2bd22f983a0ff1083 (commit)
       via  1e85def7fbb617fc7545fe3f1586383f6c0ffdd8 (commit)
       via  aa1362992eb49465442ad52686ce66ab0d1376b0 (commit)
       via  a09f21ca64086bd5ed7359f3a8cbd0f4f6241413 (commit)
       via  78e524d3fe7cbffcda328391dc830e51d1d62b09 (commit)
       via  68c3906e4e322b87523dfa342180ebf810ebcea0 (commit)
       via  e60885aa24c5009e801b23c9bdac148fbe2a6276 (commit)
       via  eedce1294a5768a80a23ed8bb129040dab0d00b8 (commit)
       via  1ff64458d8a18ebfda6020b024897cec5443c397 (commit)
       via  3d143b76d8940419bd702b16152ea6e6ee08be86 (commit)
       via  0670126702e64b1217a015bebf9ee098edbcc6eb (commit)
       via  49a0d6217e08d6773e2d31cd311291a55ca5babe (commit)
      from  a4d522b6676eb4af12daacbb24f4977f39c4ebbe (commit)

Summary of changes:
 etc/RT_Config.pm.in                                |   13 +
 etc/upgrade/4.1.17/content                         |   26 +
 lib/RT/Config.pm                                   |    3 +
 lib/RT/Date.pm                                     |  126 ++-
 lib/RT/I18N/cs.pm                                  |    5 +-
 lib/RT/I18N/ru.pm                                  |    2 +-
 lib/RT/Interface/Web.pm                            |    1 +
 lib/RT/Record.pm                                   |    1 +
 lib/RT/Report/Tickets.pm                           | 1049 ++++++++++++++++----
 lib/RT/Report/Tickets/Entry.pm                     |   73 +-
 lib/RT/SearchBuilder.pm                            |   28 +-
 lib/RT/Tickets.pm                                  |   67 +-
 lib/RT/User.pm                                     |    4 +-
 sbin/rt-test-dependencies.in                       |    4 +-
 share/html/Elements/EditCustomFieldSelect          |    8 +-
 share/html/Elements/QueryString                    |    3 +-
 share/html/Search/Chart                            |  460 +++++++--
 share/html/Search/Chart.html                       |   88 +-
 share/html/Search/Elements/Chart                   |   99 +-
 share/html/Search/Elements/ChartTable              |  117 +++
 .../Elements/SelectChartFunction}                  |   37 +-
 share/html/Search/Elements/SelectGroupBy           |   26 +-
 share/static/css/base/charts.css                   |   21 +
 share/static/css/base/main.css                     |    1 +
 share/static/js/cascaded.js                        |   11 +-
 share/static/js/event-registration.js              |   40 +
 t/api/date.t                                       |   22 +-
 t/charts/basics.t                                  |   90 ++
 t/charts/compound-sql-function.t                   |  120 +++
 t/web/charting.t                                   |   38 +-
 t/web/saved_search_chart.t                         |    8 +-
 31 files changed, 2112 insertions(+), 479 deletions(-)
 create mode 100644 etc/upgrade/4.1.17/content
 create mode 100644 share/html/Search/Elements/ChartTable
 copy share/html/{Articles/Article/Elements/SelectSearchPrivacy => Search/Elements/SelectChartFunction} (72%)
 create mode 100644 share/static/css/base/charts.css
 create mode 100644 t/charts/basics.t
 create mode 100644 t/charts/compound-sql-function.t

- Log -----------------------------------------------------------------
commit e5943f653df8c758b04cb3f010cd724283c3db81
Merge: a4d522b 005f3a2
Author: Thomas Sibley <trs at bestpractical.com>
Date:   Wed Jul 3 17:57:13 2013 -0700

    Merge branch '4.2/charts'
    
    Conflicts:
    	lib/RT/Report/Tickets.pm
    	lib/RT/SearchBuilder.pm

diff --cc lib/RT/Report/Tickets.pm
index 02217f3,16b48eb..3042ff7
--- a/lib/RT/Report/Tickets.pm
+++ b/lib/RT/Report/Tickets.pm
@@@ -190,88 -582,170 +582,171 @@@ sub _FieldToFunction 
      my $self = shift;
      my %args = (@_);
  
-     my $field = $args{'FIELD'};
+     $args{'FIELD'} ||= $args{'KEY'};
  
-     if ($field =~ /^(.*)(Hourly|Daily|Monthly|Annually)$/) {
-         my ($field, $grouping) = ($1, $2);
-         my $alias = $args{'ALIAS'} || 'main';
+     my $meta = $GROUPINGS_META{ $GROUPINGS{ $args{'KEY'} } };
+     return ('FUNCTION' => 'NULL') unless $meta;
  
-         my $func = "$alias.$field";
+     return %args unless $meta->{'Function'};
  
-         my $db_type = RT->Config->Get('DatabaseType');
-         if ( RT->Config->Get('ChartsTimezonesInDB') ) {
-             my $tz = $self->CurrentUser->UserObj->Timezone
-                 || RT->Config->Get('Timezone')
-                 || 'UTC';
-             if ( lc $tz eq 'utc' ) {
-                 # do nothing
-             }
-             elsif ( $db_type eq 'Pg' ) {
-                 $func = "timezone('UTC', $func)";
-                 $func = "timezone(". $self->_Handle->dbh->quote($tz) .", $func)";
-             }
-             elsif ( $db_type eq 'mysql' ) {
-                 $func = "CONVERT_TZ($func, 'UTC', "
-                     . $self->_Handle->dbh->quote($tz)
-                     .")";
-             }
-             else {
-                 $RT::Logger->warning(
-                     "ChartsTimezonesInDB config option"
-                     ." is not supported on $db_type."
-                 );
-             }
-         }
+     my $code = $self->FindImplementationCode( $meta->{'Function'} );
+     return ('FUNCTION' => 'NULL') unless $code;
+ 
+     return $code->( $self, %args );
+ }
+ 
+ 
+ # Gotta skip over RT::Tickets->Next, since it does all sorts of crazy magic we 
+ # don't want.
+ sub Next {
+     my $self = shift;
+     $self->RT::SearchBuilder::Next(@_);
+ 
+ }
+ 
+ sub NewItem {
+     my $self = shift;
+     my $res = RT::Report::Tickets::Entry->new($self->CurrentUser);
+     $res->{'report'} = $self;
+     weaken $res->{'report'};
+     return $res;
+ }
+ 
+ # This is necessary since normally NewItem (above) is used to intuit the
+ # correct class.  However, since we're abusing a subclass, it's incorrect.
+ sub _RoleGroupClass { "RT::Ticket" }
++sub _SingularClass { "RT::Report::Tickets::Entry" }
+ 
+ sub SortEntries {
+     my $self = shift;
+ 
+     $self->_DoSearch if $self->{'must_redo_search'};
+     return unless $self->{'items'} && @{ $self->{'items'} };
  
-         # Pg 8.3 requires explicit casting
-         $func .= '::text' if $db_type eq 'Pg';
+     my @groups =
+         grep $_->{'TYPE'} eq 'grouping',
+         map $self->ColumnInfo($_),
+         $self->ColumnsList;
+     return unless @groups;
  
-         if ( $grouping eq 'Hourly' ) {
-             $func = "SUBSTR($func,1,13)";
+     my @SORT_OPS;
+     my $by_multiple = sub ($$) {
+         for my $f ( @SORT_OPS ) {
+             my $r = $f->($_[0], $_[1]);
+             return $r if $r;
          }
-         if ( $grouping eq 'Daily' ) {
-             $func = "SUBSTR($func,1,10)";
+     };
+     my @data = map [$_], @{ $self->{'items'} };
+ 
+     for ( my $i = 0; $i < @groups; $i++ ) {
+         my $group_by = $groups[$i];
+         my $idx = $i+1;
+         my $method;
+ 
+         my $order = $group_by->{'META'}{Sort} || 'label';
+         if ( $order eq 'label' ) {
+             push @SORT_OPS, sub { $_[0][$idx] cmp $_[1][$idx] };
+             $method = 'LabelValue';
          }
-         elsif ( $grouping eq 'Monthly' ) {
-             $func = "SUBSTR($func,1,7)";
+         elsif ( $order eq 'numeric label' ) {
+             push @SORT_OPS, sub { $_[0][$idx] <=> $_[1][$idx] };
+             $method = 'LabelValue';
          }
-         elsif ( $grouping eq 'Annually' ) {
-             $func = "SUBSTR($func,1,4)";
+         elsif ( $order eq 'raw' ) {
+             push @SORT_OPS, sub { $_[0][$idx] cmp $_[1][$idx] };
+             $method = 'RawValue';
          }
-         $args{'FUNCTION'} = $func;
-     } elsif ( $field =~ /^(?:CF|CustomField)\.{(.*)}$/ ) { #XXX: use CFDecipher method
-         my $cf_name = $1;
-         my $cf = RT::CustomField->new( $self->CurrentUser );
-         $cf->Load($cf_name);
-         unless ( $cf->id ) {
-             $RT::Logger->error("Couldn't load CustomField #$cf_name");
+         elsif ( $order eq 'numeric raw' ) {
+             push @SORT_OPS, sub { $_[0][$idx] <=> $_[1][$idx] };
+             $method = 'RawValue';
          } else {
-             my ($ticket_cf_alias, $cf_alias) = $self->_CustomFieldJoin($cf->id, $cf);
-             @args{qw(ALIAS FIELD)} = ($ticket_cf_alias, 'Content');
+             $RT::Logger->error("Unknown sorting function '$order'");
+             next;
          }
-     } elsif ( $field =~ /^(?:(Owner|Creator|LastUpdatedBy))(?:\.(.*))?$/ ) {
-         my $type = $1 || '';
-         my $column = $2 || 'Name';
-         my $u_alias = $self->{"_sql_report_${type}_users_${column}"}
-             ||= $self->Join(
-                 TYPE   => 'LEFT',
-                 ALIAS1 => 'main',
-                 FIELD1 => $type,
-                 TABLE2 => 'Users',
-                 FIELD2 => 'id',
-             );
-         @args{qw(ALIAS FIELD)} = ($u_alias, $column);
-     } elsif ( $field =~ /^(?:Watcher|(Requestor|Cc|AdminCc))(?:\.(.*))?$/ ) {
-         my $type = $1 || '';
-         my $column = $2 || 'Name';
-         my $u_alias = $self->{"_sql_report_watcher_users_alias_$type"};
-         unless ( $u_alias ) {
-             my ($g_alias, $gm_alias);
-             ($g_alias, $gm_alias, $u_alias) = $self->_WatcherJoin( Name => $type );
-             $self->{"_sql_report_watcher_users_alias_$type"} = $u_alias;
+         $_->[$idx] = $_->[0]->$method( $group_by->{'NAME'} ) for @data;
+     }
+     $self->{'items'} = [
+         map $_->[0],
+         sort $by_multiple @data
+     ];
+ }
+ 
+ sub PostProcessRecords {
+     my $self = shift;
+ 
+     my $info = $self->{'column_info'};
+     foreach my $column ( values %$info ) {
+         next unless $column->{'TYPE'} eq 'statistic';
+         if ( $column->{'META'}{'Calculate'} ) {
+             $self->CalculatePostFunction( $column );
+         }
+         elsif ( $column->{'META'}{'SubValues'} ) {
+             $self->MapSubValues( $column );
+         }
+     }
+ }
+ 
+ sub CalculatePostFunction {
+     my $self = shift;
+     my $info = shift;
+ 
+     my $code = $self->FindImplementationCode( $info->{'META'}{'Calculate'} );
+     unless ( $code ) {
+         # TODO: fill in undefs
+         return;
+     }
+ 
+     my $column = $info->{'NAME'};
+ 
+     my $base_query = $self->Query;
+     foreach my $item ( @{ $self->{'items'} } ) {
+         $item->{'values'}{ lc $column } = $code->(
+             $self,
+             Query => join(
+                 ' AND ', map "($_)", grep defined && length, $base_query, $item->Query,
+             ),
+         );
+         $item->{'fetched'}{ lc $column } = 1;
+     }
+ }
+ 
+ sub MapSubValues {
+     my $self = shift;
+     my $info = shift;
+ 
+     my $to = $info->{'NAME'};
+     my $map = $info->{'MAP'};
+ 
+     foreach my $item ( @{ $self->{'items'} } ) {
+         my $dst = $item->{'values'}{ lc $to } = { };
+         while (my ($k, $v) = each %{ $map } ) {
+             $dst->{ $k } = delete $item->{'values'}{ lc $v->{'NAME'} };
+             utf8::decode( $dst->{ $k } )
+                 if defined $dst->{ $k }
+                and not utf8::is_utf8( $dst->{ $k } );
+             delete $item->{'fetched'}{ lc $v->{'NAME'} };
          }
-         @args{qw(ALIAS FIELD)} = ($u_alias, $column);
+         $item->{'fetched'}{ lc $to } = 1;
+     }
+ }
+ 
+ sub GenerateDateFunction {
+     my $self = shift;
+     my %args = @_;
+ 
+     my $tz;
+     if ( RT->Config->Get('ChartsTimezonesInDB') ) {
+         my $to = $self->CurrentUser->UserObj->Timezone
+             || RT->Config->Get('Timezone');
+         $tz = { From => 'UTC', To => $to }
+             if $to && lc $to ne 'utc';
      }
+ 
+     $args{'FUNCTION'} = $RT::Handle->DateTimeFunction(
+         Type     => $args{'SUBKEY'},
+         Field    => $self->NotSetDateToNullFunction,
+         Timezone => $tz,
+     );
      return %args;
  }
  
diff --cc lib/RT/SearchBuilder.pm
index 75e3ed7,e1993c9..7ac964b
--- a/lib/RT/SearchBuilder.pm
+++ b/lib/RT/SearchBuilder.pm
@@@ -922,17 -908,30 +920,41 @@@ sub ColumnMapClassName 
      return $Class;
  }
  
 +=head2 NewItem
 +
 +Returns a new item based on L</RecordClass> using the current user.
 +
 +=cut
 +
 +sub NewItem {
 +    my $self = shift;
 +    return $self->RecordClass->new($self->CurrentUser);
 +}
 +
+ =head2 NotSetDateToNullFunction
+ 
+ Takes a paramhash with an optional FIELD key whose value is the name of a date
+ column.  If no FIELD is provided, a literal C<?> placeholder is used so the
+ caller can fill in the field later.
+ 
+ Returns a SQL function which evaluates to C<NULL> if the FIELD is set to the
+ Unix epoch; otherwise it evaluates to FIELD.  This is useful because RT
+ currently stores unset dates as a Unix epoch timestamp instead of NULL, but
+ NULLs are often more desireable.
+ 
+ =cut
+ 
+ sub NotSetDateToNullFunction {
+     my $self = shift;
+     my %args = ( FIELD => undef, @_ );
+ 
+     my $res = "CASE WHEN ? BETWEEN '1969-12-31 11:59:59' AND '1970-01-01 12:00:01' THEN NULL ELSE ? END";
+     if ( $args{FIELD} ) {
+         $res = $self->CombineFunctionWithField( %args, FUNCTION => $res );
+     }
+     return $res;
+ }
+ 
  RT::Base->_ImportOverlays();
  
  1;

-----------------------------------------------------------------------


More information about the Rt-commit mailing list