summaryrefslogtreecommitdiff
path: root/LedgerSMB/DBObject.pm
blob: 0a79590e5cf480ed297abbb3589d190e01fea2f4 (plain)
  1. =head1 NAME
  2. LedgerSMB::DBObject - LedgerSMB class for building objects from db relations
  3. =head1 SYOPSIS
  4. This module creates object instances based on LedgerSMB's in-database ORM.
  5. =head1 METHODS
  6. =item find_method ($hashref, $function_name, @args)
  7. =item merge ($hashref, @attrs)
  8. copies @attrs from $hashref to $self.
  9. =head1 Copyright (C) 2007, The LedgerSMB core team.
  10. This file is licensed under the Gnu General Public License version 2, or at your
  11. option any later version. A copy of the license should have been included with
  12. your software.
  13. =back
  14. =cut
  15. package LedgerSMB::DBObject;
  16. use Scalar::Util;
  17. use base qw(LedgerSMB);
  18. use strict;
  19. use warnings;
  20. our $AUTOLOAD;
  21. sub AUTOLOAD {
  22. my ($self) = shift;
  23. my $type = (Scalar::Util::reftype $self) =~ m/::(.*?)$/;
  24. print "Type: $type\n";
  25. $type =~ m/::(.*?)$/;
  26. $type = lc $1;
  27. $self->exec_method("$type" . "_" . $AUTOLOAD, @_);
  28. }
  29. sub new {
  30. my $self = shift @_;
  31. my $lsmb = shift @_;
  32. if (! $lsmb->isa('LedgerSMB')){
  33. $self->error("Constructor called without LedgerSMB object arg");
  34. }
  35. $self = {};
  36. my $attr;
  37. for $attr (keys %{$lsmb}){
  38. $self->{$attr} = $lsmb->{$attr};
  39. }
  40. bless $self;
  41. }
  42. sub exec_method {
  43. my ($self) = shift @_;
  44. my %args = @_;
  45. my $funcname = $args{funcname};
  46. my @in_args = @{$args{args}};
  47. my @call_args;
  48. my $query =
  49. "SELECT proname, proargnames FROM pg_proc WHERE proname = ?";
  50. my $sth = $self->{dbh}->prepare($query);
  51. $sth->execute($funcname);
  52. my $ref;
  53. $ref = $sth->fetchrow_hashref('NAME_lc');
  54. my $args = $ref->{proargnames};
  55. $args =~ s/\{(.*)\}/$1/;
  56. my @proc_args = split /,/, $args;
  57. if (!$ref){ # no such function
  58. $self->error("No such function: ", $funcname);
  59. die;
  60. }
  61. my $m_name = $ref->{proname};
  62. if ($args){
  63. for my $arg (@proc_args){
  64. if ($arg =~ s/^in_//){
  65. push @call_args, $self->{$arg};
  66. }
  67. }
  68. }
  69. else {
  70. @call_args = @_;
  71. }
  72. $self->callproc($funcname, @call_args);
  73. }
  74. sub run_custom_queries {
  75. my ($self, $tablename, $query_type, $linenum) = @_;
  76. my $dbh = $self->{dbh};
  77. if ($query_type !~ /^(select|insert|update)$/i){
  78. # Commenting out this next bit until we figure out how the locale object
  79. # will operate. Chris
  80. #$self->error($locale->text(
  81. # "Passed incorrect query type to run_custom_queries."
  82. #));
  83. }
  84. my @rc;
  85. my %temphash;
  86. my @templist;
  87. my $did_insert;
  88. my @elements;
  89. my $query;
  90. my $ins_values;
  91. if ($linenum){
  92. $linenum = "_$linenum";
  93. }
  94. $query_type = uc($query_type);
  95. for (@{$self->{custom_db_fields}{$tablename}}){
  96. @elements = split (/:/, $_);
  97. push @{$temphash{$elements[0]}}, $elements[1];
  98. }
  99. for (keys %temphash){
  100. my @data;
  101. my $ins_values;
  102. $query = "$query_type ";
  103. if ($query_type eq 'UPDATE'){
  104. $query = "DELETE FROM $_ WHERE row_id = ?";
  105. my $sth = $dbh->prepare($query);
  106. $sth->execute->($self->{"id"."$linenum"})
  107. || $self->dberror($query);
  108. } elsif ($query_type eq 'INSERT'){
  109. $query .= " INTO $_ (";
  110. }
  111. my $first = 1;
  112. for (@{$temphash{$_}}){
  113. $query .= "$_";
  114. if ($query_type eq 'UPDATE'){
  115. $query .= '= ?';
  116. }
  117. $ins_values .= "?, ";
  118. $query .= ", ";
  119. $first = 0;
  120. if ($query_type eq 'UPDATE' or $query_type eq 'INSERT'){
  121. push @data, $self->{"$_$linenum"};
  122. }
  123. }
  124. if ($query_type ne 'INSERT'){
  125. $query =~ s/, $//;
  126. }
  127. if ($query_type eq 'SELECT'){
  128. $query .= " FROM $_";
  129. }
  130. if ($query_type eq 'SELECT' or $query_type eq 'UPDATE'){
  131. $query .= " WHERE row_id = ?";
  132. }
  133. if ($query_type eq 'INSERT'){
  134. $query .= " row_id) VALUES ($ins_values ?)";
  135. }
  136. if ($query_type eq 'SELECT'){
  137. push @rc, [ $query ];
  138. } else {
  139. unshift (@data, $query);
  140. push @rc, [ @data ];
  141. }
  142. }
  143. if ($query_type eq 'INSERT'){
  144. for (@rc){
  145. $query = shift (@{$_});
  146. my $sth = $dbh->prepare($query)
  147. || $self->db_error($query);
  148. $sth->execute(@{$_}, $self->{id})
  149. || $self->dberror($query);;
  150. $sth->finish;
  151. $did_insert = 1;
  152. }
  153. } elsif ($query_type eq 'UPDATE'){
  154. @rc = $self->run_custom_queries(
  155. $tablename, 'INSERT', $linenum);
  156. } elsif ($query_type eq 'SELECT'){
  157. for (@rc){
  158. $query = shift @{$_};
  159. my $sth = $self->{dbh}->prepare($query);
  160. $sth->execute($self->{id});
  161. my $ref = $sth->fetchrow_hashref('NAME_lc');
  162. $self->merge($ref, keys(%$ref));
  163. }
  164. }
  165. @rc;
  166. }
  167. 1;