summaryrefslogtreecommitdiff
path: root/LedgerSMB/DBObject.pm
blob: 5c07e15ea3147ea60727f375c7ac8fe0c87c0125 (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 LedgerSMB;
  17. use strict;
  18. use warnings;
  19. our @ISA = qw(LedgerSMB);
  20. our $AUTOLOAD;
  21. sub AUTOLOAD {
  22. my ($self) = shift;
  23. $self->exec_method($AUTOLOAD, @_);
  24. }
  25. sub new {
  26. my $self = shift @_;
  27. my $lsmb = shift @_;
  28. if (! $lsmb->isa('LedgerSMB')){
  29. $self->error("Constructor called without LedgerSMB object arg");
  30. }
  31. $self = {};
  32. my $attr;
  33. for $attr (keys %{$lsmb}){
  34. $self->{$attr} = $lsmb->{$attr};
  35. }
  36. bless $self;
  37. }
  38. sub exec_method {
  39. my ($self) = shift @_;
  40. my ($funcname) = shift @_;
  41. my $query =
  42. "SELECT proname, proargnames FROM pg_proc WHERE proname = ?";
  43. my $sth = $self->{dbh}->prepare($query);
  44. $sth->execute($funcname);
  45. my $ref;
  46. $ref = $sth->fetchrow_hashref('NAME_lc');
  47. my $args = $ref->{proargnames};
  48. $args =~ s/\{(.*)\}/$1/;
  49. my @proc_args = split /,/, $args;
  50. if (!$ref){ # no such function
  51. $self->error("No such function: ", $funcname);
  52. die;
  53. }
  54. my $m_name = $ref->{proname};
  55. my @call_args;
  56. if ($args){
  57. for my $arg (@proc_args){
  58. if ($arg =~ s/^in_//){
  59. push @call_args, $self->{$arg};
  60. }
  61. }
  62. }
  63. else {
  64. @call_args = @_;
  65. }
  66. $self->callproc($funcname, @call_args);
  67. }
  68. sub run_custom_queries {
  69. my ($self, $tablename, $query_type, $linenum) = @_;
  70. my $dbh = $self->{dbh};
  71. if ($query_type !~ /^(select|insert|update)$/i){
  72. # Commenting out this next bit until we figure out how the locale object
  73. # will operate. Chris
  74. #$self->error($locale->text(
  75. # "Passed incorrect query type to run_custom_queries."
  76. #));
  77. }
  78. my @rc;
  79. my %temphash;
  80. my @templist;
  81. my $did_insert;
  82. my @elements;
  83. my $query;
  84. my $ins_values;
  85. if ($linenum){
  86. $linenum = "_$linenum";
  87. }
  88. $query_type = uc($query_type);
  89. for (@{$self->{custom_db_fields}{$tablename}}){
  90. @elements = split (/:/, $_);
  91. push @{$temphash{$elements[0]}}, $elements[1];
  92. }
  93. for (keys %temphash){
  94. my @data;
  95. my $ins_values;
  96. $query = "$query_type ";
  97. if ($query_type eq 'UPDATE'){
  98. $query = "DELETE FROM $_ WHERE row_id = ?";
  99. my $sth = $dbh->prepare($query);
  100. $sth->execute->($self->{"id"."$linenum"})
  101. || $self->dberror($query);
  102. } elsif ($query_type eq 'INSERT'){
  103. $query .= " INTO $_ (";
  104. }
  105. my $first = 1;
  106. for (@{$temphash{$_}}){
  107. $query .= "$_";
  108. if ($query_type eq 'UPDATE'){
  109. $query .= '= ?';
  110. }
  111. $ins_values .= "?, ";
  112. $query .= ", ";
  113. $first = 0;
  114. if ($query_type eq 'UPDATE' or $query_type eq 'INSERT'){
  115. push @data, $self->{"$_$linenum"};
  116. }
  117. }
  118. if ($query_type ne 'INSERT'){
  119. $query =~ s/, $//;
  120. }
  121. if ($query_type eq 'SELECT'){
  122. $query .= " FROM $_";
  123. }
  124. if ($query_type eq 'SELECT' or $query_type eq 'UPDATE'){
  125. $query .= " WHERE row_id = ?";
  126. }
  127. if ($query_type eq 'INSERT'){
  128. $query .= " row_id) VALUES ($ins_values ?)";
  129. }
  130. if ($query_type eq 'SELECT'){
  131. push @rc, [ $query ];
  132. } else {
  133. unshift (@data, $query);
  134. push @rc, [ @data ];
  135. }
  136. }
  137. if ($query_type eq 'INSERT'){
  138. for (@rc){
  139. $query = shift (@{$_});
  140. my $sth = $dbh->prepare($query)
  141. || $self->db_error($query);
  142. $sth->execute(@{$_}, $self->{id})
  143. || $self->dberror($query);;
  144. $sth->finish;
  145. $did_insert = 1;
  146. }
  147. } elsif ($query_type eq 'UPDATE'){
  148. @rc = $self->run_custom_queries(
  149. $tablename, 'INSERT', $linenum);
  150. } elsif ($query_type eq 'SELECT'){
  151. for (@rc){
  152. $query = shift @{$_};
  153. my $sth = $self->{dbh}->prepare($query);
  154. $sth->execute($self->{id});
  155. my $ref = $sth->fetchrow_hashref('NAME_lc');
  156. $self->merge($ref, keys(%$ref));
  157. }
  158. }
  159. @rc;
  160. }
  161. 1;