/[vdw]/trunk/Obj_Srvr.pm
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /trunk/Obj_Srvr.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1 - (show annotations)
Sun Feb 6 05:28:38 2005 UTC (19 years, 2 months ago) by dpavlin
File size: 24059 byte(s)
initial import into svn

1 package Obj_Srvr;
2
3 # ===========================================================================
4 # Obj_Srvr.pm
5 #
6 # Serves live high-level data from a low level DB, using code instead of a
7 # Data Warehouse. Will run embedded in obj_srvr sql parser. obj_srvr
8 # passes the parsed sql to sub get_data() in Obj_Srvr.pm, which returns
9 # the data in delimited character format. This data may be passed to
10 # oracle_obj_srvr.pl which translates it into Net8 packets for the BI-
11 # Query desktop client.
12 #
13 # obj_srvr.pm makes use of various Student Information System (SIS) perl
14 # modules located on the wouprd server (currently Spruce).
15 #
16 # obj_srvr source is generated from obj_srvr.l and obj_srvr.y using lex and
17 # yacc, then compiled and linked with exec_sql.o to produce the obj_srvr
18 # executable (see Makefile).
19 #
20 # obj_srvr and Obj_Srvr.pm will be installed on the same server as the
21 # wouprd database (currently Spruce).
22 #
23 # Jeremy Hickerson, 5/8/2002
24 #
25 # ===========================================================================
26
27 use strict;
28
29 BEGIN {
30 use Exporter ();
31 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
32
33 # set the version for version checking
34 $VERSION = 1.00;
35 @ISA = qw(Exporter);
36 @EXPORT = qw(&obj_srvr_connect &get_data &get_yyin &send_yyout
37 &connect2client &like2re &tr_op);
38 %EXPORT_TAGS = ( ); # eg: TAG => [ qw!name1 name2! ],
39 our @EXPORT_OK = qw($FH_OUT);
40
41 if ($^O eq "VMS") {
42 # jhjh ( grep /gen\$com/i, @INC ) || unshift @INC, "gen\$com";
43 ( grep /woup:\[wou_sis_mods.com\]/i, @INC ) || unshift @INC, "woup:[wou_sis_mods.com]"; # jhjh
44 }
45 # default to Unix
46 else {
47 ( grep /\/usr\/local\/bin/, @INC ) || unshift @INC, "/\/usr\/local\/bin";
48 }
49
50 $DBI::drh->{debug} = 1;
51
52 }
53
54 our @EXPORT_OK;
55
56 use subs qw(obj_srvr_connect get_data get_yyin send_yyout connect2client like2re
57 tr_op);
58
59 use DBI;
60 use WOU_Admit;
61 use WOU_Person;
62 use WOU_Student;
63 use WOU_AR;
64 use WOU_SIS_Util;
65 use WOU_Util;
66 use Socket;
67 use Safe;
68
69
70 # ============================================================================
71 # Package-Level Stuff
72 # ============================================================================
73
74 my $DBH; # needs to be package level (this package's sub's assume this)
75 our $FH_OUT; # let obj_srvr.pl see this
76 my $FH_IN;
77
78 my (%table_objs, %obj_accessor, %methods); # these are populated in
79 # obj_srvr.tables
80
81 # jhjh !! make sure obj_srvr.tables is readonly; it contains perl code to be eval'ed
82
83 if ($^O eq "VMS") {
84 eval `type obj_srvr.tables`; # table layout file
85 }
86 # default to Unix
87 else {
88 eval `cat obj_srvr.tables`;
89 }
90
91 my $compartment = new Safe;
92
93 $compartment->permit(qw( entereval )); # need for stuff like date_compare()
94
95 #$compartment->permit_only(qw()); # nothing! jhjh - need to see what to put
96 # in here to allow what we need but nothing
97 # else. Even without this it seems to stop
98 # things like system().
99
100 $compartment->share_from('WOU_Util', [ 'date_compare' ] );
101
102
103 # ============================================================================
104 # routines
105 # (will be embedded in a C Program)
106 # ============================================================================
107
108 sub obj_srvr_connect {
109 my ($uid, $passwd) = @_;
110
111 print STDERR "before DBI->connect...\n"; # jhjh
112 $DBH = DBI->connect('dbi:Oracle:', qq{$uid/$passwd\@(DESCRIPTION=
113 (ADDRESS_LIST =
114 (ADDRESS =
115 (COMMUNITY = tcp.cedar.osshe.edu)
116 (PROTOCOL = TCP)
117 (HOST = 140.211.10.26)
118 (PORT = 1541)
119 )
120 )
121 (CONNECT_DATA =
122 (SID = wouprd)
123 (SRVR = DEDICATED)
124 ) ) }, "", {debug => 1} )
125 or die "$!: Can't connect to DB";
126
127 print STDERR "after DBI->connect...\n"; # jhjh
128
129 # help performance of select with join on remote spriden table
130 $DBH->do("alter session set optimizer_goal = ALL_ROWS");
131
132 # defaults - will be redirected if connected to oracle_obj_srvr
133 $FH_IN = \*STDIN;
134 $FH_OUT = \*STDOUT;
135
136 }
137
138 sub connect2client {
139 my ($remote, $port) = @_;
140
141 print STDERR "host = $remote, port = $port\n"; # jhjh
142
143 my ($iaddr, $paddr, $proto, $line, $pid, $cnt);
144
145 $| = 1;
146
147 if ($port =~ /\D/) { $port = getservbyname($port, 'tcp') }
148 die "No port" unless $port;
149
150 $iaddr = inet_aton($remote) || die "no host: $remote";
151 $paddr = sockaddr_in($port, $iaddr);
152
153 $proto = getprotobyname('tcp');
154 socket(SOCK, PF_INET, SOCK_STREAM, $proto) || die "socket: $!";
155
156 $cnt = 0;
157 CONNECT_LOOP:
158 while ($cnt++ < 10 ) {
159 sleep(2);
160
161 if (connect(SOCK, $paddr) ) {
162 print STDERR "Connected\n";
163 last CONNECT_LOOP;
164 }
165 else { print STDERR "$!: problem with connect\n" } # jhjh
166
167 ( die "can't connect to lsnr") if $cnt == 10;
168 }
169
170 select(SOCK); $| = 1; # make unbuffered
171 select(STDERR); $| = 1; # make unbuffered
172
173 $FH_IN = \*SOCK;
174 $FH_OUT = \*SOCK;
175
176 select($FH_OUT); $| = 1; # make unbuffered
177 select(STDOUT);
178
179 return 1;
180
181 }
182
183 sub get_yyin {
184
185 my $size = shift;
186
187 my $yychars;
188
189 sysread($FH_IN, $yychars, $size);
190 print STDERR "read $yychars\n"; # jhjh
191
192 return $yychars;
193 }
194
195 sub send_yyout {
196
197 my $str = shift;
198
199 print $FH_OUT $str;
200
201 return 1;
202 }
203
204 sub get_data {
205
206 my ($cols, $tab, $where, $order) = @_;
207
208 $cols = lc($cols);
209 $tab = lc($tab);
210 $order = lc($order);
211 # handle "where" separately; it may have upper-case scalars that we
212 # need to preserve
213
214 # oracle_obj_srvr may have broken query up into 254 byte chunks separated by \n
215 $cols =~ s/\n//g;
216 $tab =~ s/\n//g;
217 $where =~ s/\n//g;
218 $order =~ s/\n//g;
219
220
221 my ($rh_driver_objs, $ra_results, $ra_support_results, $rh_result, $rh_data,
222 $rh_join_obj, $ra_join_objs, $col, $table, $subname, @field_order, $rh_stu,
223 $rh_support_objs, $parm, $ref_key, @subst_parms, @save_parms,
224 %filtered_results, $cnt, @save_where, $word, $subst_where, $col_info,
225 @converted_order, $special_sort, %special_sort);
226
227 if (!defined($cols) ) { $cols = "" }
228 if (!defined($tab) ) { $tab = "" }
229 if (!defined($where) ) { $where = "" }
230 if (!defined($order) ) { $order = "" }
231
232 my %query = ( "columns" => [ ],
233 "table" => [ ],
234 "where" => [ ],
235 "order" => [ ] );
236
237 $special_sort = 0;
238 print STDERR "cols = $cols\n"; # jhjh
239 print STDERR "tab = $tab\n"; # jhjh
240 print STDERR "where = $where\n"; # jhjh
241
242 @{$query{"columns"} } = split(/,/, $cols);
243 ($query{"table"} ) = split(/,/, $tab);
244
245 $where =~ s/([^\\]),/$1\|/g; # save escaped comma's
246 @{$query{"where"} } = split(/\|/, $where);
247 @{$query{"order"} } = split(/,/, $order);
248
249 # convert numeric col refs to names
250 if ( defined($query{order}->[0] ) ) {
251 if ( $query{order}->[0] =~ /^\d+$/ ) {
252 print STDERR "converting numeric col refs\n"; # jhjh
253 while ( $col = shift @{ $query{order} } ) {
254 push @converted_order, $query{columns}->[$col - 1];
255 print STDERR "$col: ", $query{columns}->[$col - 1], "\n"; # jhjh
256 }
257 push @{ $query{order} }, @converted_order;
258 }
259
260 # see if special sorts are needed
261 foreach $col ( @{ $query{order} } ) {
262
263 if (exists($obj_accessor{ $query{table} }->{$col}->{datatype}) ) {
264 if ($obj_accessor{ $query{table} }->{$col}->{datatype}
265 eq "numeric" ) {
266
267 $special_sort = 1;
268 $special_sort{$col} = \&num_sort; # defined in WOU_Util.pm
269 }
270 if ($obj_accessor{ $query{table} }->{$col}->{datatype}
271 eq "date" ) {
272
273 $special_sort = 1;
274 $special_sort{$col} = \&date_sort; # defined in WOU_Util.pm
275 }
276 }
277
278 # can add check for descending sort, etc. below if needed
279 }
280 }
281
282 print STDERR "order = $order :", @{ $query{order} }, "\n"; # jhjh
283
284 $rh_driver_objs = get_driver_objs(\%query); # rh_driver_objs now has
285 # one or more sub refs as
286 # hash keys and a hash ref
287 # holding the sub ref in key
288 # "sub" and an array ref of
289 # args for the sub in key
290 # "parms"
291 $rh_support_objs = get_support_objs(\%query);
292
293 # add any field_maps for all columns returned by supporting subs, even
294 # if columns are not in "select" statement (they might be in "where" clause)
295 add_field_maps($rh_support_objs, $query{table} );
296
297 # run the driver sub (Only allow 1 driver table)
298 push @{$ra_results}, @{ &{ $rh_driver_objs->{"subref"} }(
299 @{ $rh_driver_objs->{"parms"} })
300 };
301
302 # run the supporting subs
303 foreach $rh_stu ( @{$ra_results} ) {
304
305 foreach $subname (keys %{$rh_support_objs} ) {
306
307 while ( shift @subst_parms ) { } # empty each time
308
309 # substitute driver table column values for referential parms
310 while ( $parm = shift @{ $rh_support_objs->{$subname}->{"parms"} } ) {
311
312 push @save_parms, $parm;
313
314 if ($parm =~ /^\$/ ) {
315
316 $ref_key = $parm;
317 $ref_key =~ s/^\$//;
318
319 if (exists($rh_stu->{ $ref_key } ) ) {
320 push @subst_parms, $rh_stu->{$ref_key};
321 }
322 else { # error (can't find as driver field): leave "$pidm"
323 # or whatever as parm
324 push @subst_parms, $parm;
325 }
326 }
327 else {
328 push @subst_parms, $parm;
329 }
330 }
331
332 # restore parms, including "$" parms
333 while ( $parm = shift @save_parms ) {
334
335 push @{ $rh_support_objs->{$subname}->{"parms"} }, $parm;
336
337 }
338
339 add2hash($rh_stu,
340 \%{ &{ $rh_support_objs->{$subname}->{"subref"} }(
341 @subst_parms) },
342 $rh_support_objs->{$subname}->{"field_map"} );
343 }
344
345 }
346
347
348 # Explanation:
349 # 1. Will translate where-clause into perl expression, then use reval
350 # to check for TRUE after all column values have been plugged in.
351 # This will involve implementing all SQL predicate operators
352 # (comparison, between, like, in, etc.) in (or for) obj_srvr.pl.
353 # Some of these need no translation (most of the comparison operators
354 # mean the same thing in perl, for instance.)
355
356 # 3 passes through entire population so far...
357 $cnt = 0;
358 # we have substituted some words in $query{where} while we were getting params;
359 # copy @{ $query{where} } onto $where putting spaces between words
360 $where = ""; push @save_where, @{ $query{where} };
361 while ( defined($word = shift @{ $query{where} } ) ) { $where .= $word . " " }
362 $where =~ s/\s*$//;
363 push @{ $query{where} }, @save_where;
364
365 $where =~ s/([^\\])'/$1"/g; # allow escaped single quotes to stay
366 $where =~ s/\\//g; # remove escape char's, now that we're done w/ them
367 $where =~ s/^/ /; # put space at beginning, makes substitution below
368 # work for first word
369 print STDERR "WHERE = ", $where, "\n"; # jhjh
370 while ( $rh_stu = shift @{$ra_results} ) {
371
372 $subst_where = $where; # reset
373
374 # substitute column vals into where expression in order to evaluate
375 # (only subst if word is delimited by spaces or reg. exp. slashes)
376 foreach $col (keys %{$rh_stu} ) {
377 $col = lc($col); # all hash column names are lower case, so
378 # need this to make sure substitution references
379 # the actual column name and not the capitalized
380 # hash column name. Still need to do case-insensitive
381 # substitution below because the query column name
382 # may be upper case.
383
384 # turn nulls into null strings
385 if (!defined($rh_stu->{$col} ) ) {
386 if (exists($obj_accessor{ $query{table} }->{$col}->{datatype}) and
387 $obj_accessor{ $query{table} }->{$col}->{datatype}
388 eq "numeric" ) {
389 $rh_stu->{$col} = 0;
390 }
391 else { $rh_stu->{$col} = "" }
392 }
393 $subst_where =~ s/ $col / "$rh_stu->{$col}" /ig; # /i handles upper-
394 # case query col names
395 $subst_where =~ s/\/\^$col\$\//\/\^$rh_stu->{$col}\$\//ig;
396 }
397
398 if (where_clause_true($subst_where) ) {
399 $filtered_results{++$cnt} = $rh_stu;
400 }
401
402 }
403
404 # jhjh push @field_order, @{$query{columns} };
405
406 if ($order) {
407 if ($special_sort) {
408 $ra_results = compound_sort(\%filtered_results, $query{"order"},
409 \%special_sort );
410 }
411 else {
412 $ra_results = compound_sort(\%filtered_results, $query{"order"} );
413 }
414 }
415 else { push @{ $ra_results }, values %filtered_results }
416
417
418 foreach $col ( @{ $query{columns} } ) {
419 $col_info .=
420 $col . ":" . $obj_accessor{ $query{table} }->{$col}->{size} . "|";
421 }
422 $col_info =~ s/\|$//;
423
424 print $FH_OUT "$col_info\n";
425
426 output_delimited($FH_OUT, $ra_results, $query{columns}, "", "");
427
428 print $FH_OUT "\n$cnt rows returned\n";
429
430 return 1;
431
432 }
433
434
435 sub get_driver_objs {
436
437 my $rh_query = shift;
438 my %driver_objs =
439 ( "subname" => $table_objs{ $rh_query->{table} }->{subname},
440 "subref" => $table_objs{ $rh_query->{table} }->{subref},
441 "parms" => get_parms(0, $table_objs{ $rh_query->{table} }->{subname},
442 $rh_query) );
443
444 return \%driver_objs;
445 }
446
447
448 sub get_support_objs {
449
450 my $rh_query = shift;
451
452 my ($subname, %support_objs, $col);
453
454
455 foreach $col (@{$rh_query->{columns} } ) {
456
457 # next if column is a driver sub column
458 next if $obj_accessor{$rh_query->{table} }->{$col}->{subname} eq "SELF";
459
460 print STDERR "support_objs: col = $col\n"; # jhjh
461 print STDERR "support_objs->subname = ", $obj_accessor{ $rh_query->{table} }->{$col}->{subname}, "\n"; # jhjh
462
463 # these get populated the same way multiple times if several fields share
464 # a subname
465 # Data looks like this:
466 # $support_objs{"get_addr_lo"}->{"subref"} = \&get_addr, for example
467
468 $support_objs{ $obj_accessor{ $rh_query->{table} }->{
469 $col}->{subname} }->{"subref"} =
470 $obj_accessor{ $rh_query->{table} }->{$col}->{subref};
471
472 $support_objs{ $obj_accessor{ $rh_query->{table} }->{
473 $col}->{subname} }->{"parms"} =
474 get_parms(1,
475 $obj_accessor{$rh_query->{table} }->{$col}->{subname},
476 $rh_query);
477
478 # jhjh - don't need this, done elsewhere now
479 # This adds a new field_map pair each time.
480 # Data looks like this:
481 # $support_objs{"get_addr_lo"}->{"field_map}->{"city"} = "city_lo",
482 # for example, where "city is the fieldname returned by the subref and
483 # "city_lo" is the fieldname to be used in the virtual table being created.
484 # $support_objs{
485 # $obj_accessor{ $rh_query->{table} }->{$col}->{subname}
486 # }->{"field_map"}->{
487 # $obj_accessor{$rh_query->{table} }->{$col}->{field}
488 # } = $col;
489
490 }
491
492 # maybe there's a column in the "where" clause but not in the select column
493 # list, and it's sub is not shared with any of the select list columns
494 foreach $col (keys %{ $obj_accessor{ $rh_query->{table} } } ) {
495
496 if ( grep /^$col$/i, @{ $rh_query->{where} } and
497 $obj_accessor{ $rh_query->{table} }->{$col}->{subname} ne "SELF" ) {
498
499 # Data looks like this:
500 # $support_objs{"get_addr_lo"}->{"subref"} = \&get_addr, for example
501
502 $support_objs{ $obj_accessor{ $rh_query->{table} }->{
503 $col}->{subname} }->{"subref"} =
504 $obj_accessor{ $rh_query->{table} }->{$col}->{subref};
505
506 $support_objs{ $obj_accessor{ $rh_query->{table} }->{
507 $col}->{subname} }->{"parms"} =
508 get_parms(1,
509 $obj_accessor{$rh_query->{table} }->{$col}->{subname},
510 $rh_query);
511 }
512
513 }
514
515 return \%support_objs;
516
517 }
518
519
520 sub get_parms {
521
522 my ($rec_key, $subname, $rh_query) = @_;
523
524 my ($parm, @parms);
525
526 foreach $parm (@{$methods{$subname}->{parms} } ) {
527 push @parms, get_parm_val($rec_key, $parm, $rh_query);
528 }
529
530 return \@parms;
531 }
532
533
534 sub get_parm_val {
535
536 my ($rec_key, $parm, $rh_query) = @_;
537
538 my ($word, $got_word, @subst_where);
539
540 if ($parm eq "dbh") { return $DBH } # package var
541
542 if ($rec_key == 0 ) { # i.e. sub is the driver ("table"), so we require
543 # params to be scalar predicates in where-clause.
544
545 # for drivers ("tables") we require single-valued, "=" params.
546 # we will handle "!=", "in", "like" values at a higher level and
547 # simply run the sub multiple times (maybe?).
548
549 $got_word = 0;
550 while ( $word = shift @{$rh_query->{where} } ) {
551 if ($got_word) { $got_word++ }
552
553
554 if (lc($word) eq $parm) { # so any future parms must also be lc
555 $got_word = 1;
556 $word = "TRUE"; # replace driver parms with true statements;
557 # reval of where clause doesn't need to
558 # look at these again, and any "%" values
559 # will wrongly fail the revel
560
561 # jhjh ! May want to rethink TRUE = TRUE
562 # idea: need to handle conditions other than
563 # "=" on driver parm columns (like "in", "!=").
564 # Would be good to pass this to the eval like
565 # everything else. Have to think of another
566 # way to get around parms that accept "=%".
567 }
568
569 if ($got_word == 3) {
570
571 push @subst_where, "TRUE";
572 unshift @{ $rh_query->{where} }, @subst_where;
573 $word =~ s/'//g; # don't want single quotes as part of # the string
574
575 return $word;
576
577 } # 2 is "="
578
579 push @subst_where, $word;
580 }
581 # won't be reached unless parm not in where clause
582 unshift @{ $rh_query->{where} }, @subst_where;
583 }
584
585
586 else { # Params are referential: they come from the driver object.
587 # (We are representing a single table to the user, but pulling
588 # the data from a driver object and whatever supporting
589 # subroutines we need.) If a supporting subroutine requires
590 # a parameter that is not referential (like gpa_type for all_gpa),
591 # we will create additional columns for the possible values. I.e.,
592 # column cgpa_o is gpa_type 'O' (overall), column cgpa_t is
593 # gpa_type 'T' (transfer), etc.
594
595 return $parm; # substitute after getting driver records
596
597 # jhjh - still need to handle scalar where-clause conditions for
598 # support obj columns - i.e. a required param for a support object
599 # cannot be figured out referentially. Handle these with higher
600 # level wrapper subs.
601
602 # fall-through
603 return;
604 }
605
606 }
607
608
609 sub add_field_maps {
610
611 my ($rh_support_objs, $table) = @_;
612
613 my ($col, $subname);
614
615 COL_LOOP:
616 foreach $col (keys %{ $obj_accessor{$table} } ) {
617 next COL_LOOP if $obj_accessor{$table}->{$col}->{"subname"} eq "SELF";
618
619 # fall-through
620 foreach $subname ( keys %{ $rh_support_objs } ) {
621
622 # only put it in if we used it
623 if ($obj_accessor{$table}->{$col}->{"subname"} eq $subname ) {
624
625 if ( exists( $obj_accessor{$table}->{$col}->{"field"} ) ) {
626
627 # Data looks like this:
628 # $support_objs{"get_addr_lo"}->{"field_map}->{
629 # "city"} = "city_lo", for example
630 $rh_support_objs->{$subname}->{"field_map"}->{
631 $obj_accessor{$table}->{$col}->{"field"} } = $col;
632
633 }
634 }
635 }
636 }
637 }
638
639
640 sub where_clause_true {
641
642 my $where = shift;
643
644 # note: we are guaranteed white space between operands and operators
645 # because of how we processed the where clause earlier
646 # (may come in handy to know this)
647
648 # need to think about how to skip these substitutions if character is inside
649 # a string (maybe in parser translate these chars to something else if they're
650 # in a string, then translate them back further below
651
652 # Need to use safe eval, or build in some checking for system() and
653 # backticks, etc. (i.e. "where lname = `<dangerous os command>` " for
654 # where clause... ). Safe->reval should do it.
655
656 # print STDERR "EVAL where = $where\n"; # jhjh
657
658 # use reval to see if substituted where clause is true;
659 $compartment->reval( qq{
660 if ($where) { return 1 }
661
662 # fall-through
663 return 0;
664 } );
665 }
666
667
668 sub like2re {
669
670 my ($str, $word, $negative);
671 $negative = 0;
672
673 # stop on LIKE for LIKE/NOT LIKE
674 while ( ($word = shift) !~ /^like$/i ) {
675 if ($word =~ /^not$/i) {
676 $negative = 1;
677 }
678 else { $str .= $word . "," } # replace whitespace w/ comma's just like the
679 # parser does
680 }
681 $str .= $word . ","; # add LIKE to $str
682
683 $word = shift; # $word now holds the SQL LIKE expression
684
685
686 # if LIKE expr contains SQL % wildcard, then turn into perl reg exp
687 if ( $word =~ /'(.*%.*)'/i ) {
688
689 $word = $1;
690 $str =~ s/like,$/=~,/i;
691
692 $negative && ( $str =~ s/=~/!~/ );
693
694 $word =~ s/^([^%])/\^$1/;
695 $word =~ s/([^%])$/$1\$/;
696 $word =~ s/%/\.\*/g;
697 $word = "/" . $word . "/";
698
699 }
700
701 # otherwise turn like into "=" ( we will turn "=" into "eq" in get_data(),
702 # this sub is used by the yacc parser)
703 else {
704 $str =~ s/like,$/=,/i;
705 }
706
707 $str .= $word;
708
709 return $str;
710
711 }
712
713
714 sub tr_op {
715 my ($table, $lval, $op, $rval) = @_;
716 print STDERR "\$lval = $lval, \$op = $op, \$rval = $rval\n"; # jhjh
717 if ( $op eq '<>') { $op = "!=" }
718
719 # translate $op for strings
720 if ( $lval =~ /^'.*'$/ or
721 $rval =~ /^'.*'$/ ) {
722
723 $op = $op eq '=' ? 'eq' :
724 $op eq '!=' ? 'ne' :
725 $op eq '<' ? 'lt' :
726 $op eq '<=' ? 'le' :
727 $op eq '>' ? 'gt' :
728 $op eq '>=' ? 'ge' : $op;
729 }
730 else {
731 $op = $op eq '=' ? '==' : $op;
732 }
733
734 # translate $op for dates
735 if (exists($obj_accessor{lc($table) }->{lc($lval) }->{datatype}) and
736 $obj_accessor{lc($table) }->{lc($lval) }->{datatype}
737 eq "date" ) {
738
739 $op = "date_compare_$op";
740 }
741
742 return $op;
743 }
744
745 return 1;

  ViewVC Help
Powered by ViewVC 1.1.26