package DBtank; # # SPDX-License-Identifier: AGPL-3.0-or-later # Copyright (c) Rainer Gümpelein, TeilRad GmbH # use strict; use warnings; use POSIX; use DBI; use DBI::Const::GetInfoType; use CGI ':standard'; use Lib::Config; use Mod::Basework; use Scalar::Util qw(looks_like_number); use Config::General; use Data::Dumper; my $cf = new Config; my $bw = new Basework; my $q = new CGI; $q->import_names('R'); my $debug = 1; sub new { my $class = shift; my $self = {}; my $globalconf_file = "/var/www/copri4/shareeconf/global.cfg"; my $conf = Config::General->new($globalconf_file); my %globalconf = $conf->getall; $self = \%globalconf; bless($self,$class); return $self; } my $today = strftime("%d.%m.%Y",localtime(time)); my $date_time = strftime("%d.%m.%Y %H:%M",localtime(time)); my %varenv = $cf->envonline(); #dbconnect_intern, on default $dbh_intern will be used my $dbh_intern = &dbconnect(""); sub dbconnect { my $self = shift; my $options =""; my $database = "dbi:Pg:dbname=$varenv{dbname};host=$varenv{dbhost};port=5432;options='$options'"; my $dbh = DBI->connect($database, $varenv{dbuser}, $varenv{dbpassw},{ RaiseError => 1, AutoCommit => 1 }) or die "Can't connect to $varenv{dbname}: $DBI::errstr"; #$bw->log("--> dbconnect_intern --> $varenv{syshost} ",$database,""); return $dbh if($dbh); } #dbconnect_extern for copri operator instance sub dbconnect_extern { my $self = shift; my $dbname = shift; my $client_encoding = shift || ""; my $instance_type = "operator"; $instance_type = "primary" if($dbname eq $self->{primary}->{sharee_primary}->{database}->{dbname}); my $globalconf_file = "/var/www/copri4/shareeconf/global.cfg"; my $conf = Config::General->new($globalconf_file); my %globalconf = $conf->getall; #$bw->log("dbconnect_extern call with instance_type:$instance_type and copri_instance:",$dbname,""); #keep in mind, only one DB can be returned by this way #while (my ($key, $value) = each %{ $self->{$instance_type} }) { while (my ($key, $value) = each %{ $globalconf{$instance_type} }) { if($key eq $dbname){ $bw->log("dbconnect_XX",$value->{database}->{dbname},""); my $database = "dbi:Pg:dbname=$value->{database}->{dbname};host=$value->{database}->{host};port=$value->{database}->{port};options='$value->{database}->{options}'"; $database .= ";sslmode=$value->{database}->{sslmode}" if($value->{database}->{sslmode} && $value->{database}->{host} ne "localhost"); my $dbh = DBI->connect($database, $value->{database}->{user}, $value->{database}->{passwd},{ RaiseError => 0, AutoCommit => 1 }); #$bw->log("--> dbconnect_extern success --> $database, $value->{database}->{user}, $value->{database}->{passwd}",$database,""); $dbh->do("set CLIENT_ENCODING TO 'iso-8859-1'") if($client_encoding && $client_encoding eq "iso-8859-1"); return $dbh if($dbh); } } $bw->log("ERROR, dbconnect_extern call with dbname: $dbname |instance_type:$instance_type","",""); return ""; } #get operator conf by oprefix sub get_operator_conf { my $self = shift; my $oprefix = shift || ""; my $globalconf_file = "/var/www/copri4/shareeconf/global.cfg"; my $conf = Config::General->new($globalconf_file); my %globalconf = $conf->getall; while (my ($key, $operator) = each %{ $globalconf{operator} }) { if($oprefix && $oprefix eq $operator->{oprefix}){ #$bw->log("get operator conf by oprefix: $oprefix",$operator->{oprefix},""); return $operator; } } $bw->log("Cannot get operator conf by oprefix: $oprefix","",""); return 0; } #get dbname because varenv{dbname} seems not stable sub get_dbname { my $self = shift; my $dbh = shift || $dbh_intern; my $source = $dbh->get_info( $GetInfoType{SQL_DATABASE_NAME} ); return $source; } #loop extern operator db's for specific tablefield sync sub update_operatorsloop { my $self = shift; my $dbname = shift || ""; my $adrc_id = shift || 0; my $todo = shift || "update"; my $authref = { table => "contentadr", fetch => "one", template_id => "202", c_id => "$adrc_id", }; my $dbh_primary = $self->dbconnect_extern($self->{primary}->{sharee_primary}->{database}->{dbname}); my $record_primary = { c_id => 0 }; $record_primary = $self->fetch_record($dbh_primary,$authref) if($adrc_id && $adrc_id > 0); $bw->log("update_operatorsloop by copri_instance-dbname: $dbname | owner: $record_primary->{owner}","",""); my $rows = 0; if($record_primary->{c_id}){ my %operator_hash = (); #keep in mind, shareedms-operators updates primary, that's because we have to also loop if($record_primary->{txt17}){ if($record_primary->{txt17} =~ /\w\s\w/){ %operator_hash = map { $_ => "$self->{operator}{$_}->{operatorApp}" } split(/\s+/,$record_primary->{txt17}); }else{ %operator_hash = ( "$record_primary->{txt17}" => "$self->{operator}{$record_primary->{txt17}}->{operatorApp}" ); } foreach my $sharee_operator (keys (%operator_hash)){ if($sharee_operator =~ /sharee_/){ $sharee_operator =~ s/\s//g; my $dbh_operator = $self->dbconnect_extern("$sharee_operator"); if($todo eq "update"){ delete $record_primary->{txt17};#operators delete $record_primary->{txt30};#tarifs delete $record_primary->{txt15};#Bonusnr delete $record_primary->{int07};#Rabatt delete $record_primary->{int09};#Service App staff delete $record_primary->{int16};#payone-cron-interval delete $record_primary->{int19};#Ilockit Admin #delete $record_primary->{int05};#Web-Login #delete $record_primary->{int12};#Vde (remove delete for global setting) delete $record_primary->{int23};#mini_answer count will be saved on operator delete $record_primary->{txt29};#Sonstiges delete $record_primary->{txt35};#Umfragelink my $update = { %$record_primary, table => "contentadr", }; $bw->log("--> save_account update_operatorsloop $sharee_operator",$update->{c_id},""); $bw->log("UPDATE adr from record_primary to operator on loop $sharee_operator",$record_primary->{c_id},""); $rows = $self->update_record($dbh_operator,$update,$record_primary); if($rows != 1 && $record_primary->{int04} && $record_primary->{int13} && $record_primary->{int14}){ $bw->log("INSERT adr from record_primary to operator on loop $sharee_operator",$record_primary->{c_id},""); my $insert = { %$record_primary, table => "contentadr", mtime => 'now()', }; my $c_id = $self->insert_contentoid($dbh_operator,$insert,""); $rows = 1 if($c_id); } }elsif($todo eq "delete"){ $bw->log("DELETE adr from operators and at last primary $sharee_operator",$record_primary,""); $rows += $self->delete_content($dbh_operator,"contentadr",$record_primary->{c_id}); } } } } } return $rows; }#end update_operatorsloop #CMS-Texte sync primary to operators sub operators_cms { my $self = shift; my $dbname = shift || ""; my $c_id = shift || 0; my $todo = shift || "update"; my $cmsref = { table => "contentuser", fetch => "one", template_id => "194", c_id => "$c_id", }; my $dbh_primary = $self->dbconnect_extern($self->{primary}->{sharee_primary}->{database}->{dbname}); my $record_primary = { c_id => 0 }; $record_primary = $self->fetch_record($dbh_primary,$cmsref) if($c_id && $c_id >= 1000); my $rows = 0; if($record_primary->{c_id}){ while (my ($key, $op_name) = each %{ $self->{operator} }) { if($op_name->{database}->{dbname}){ my $sharee_operator = $op_name->{database}->{dbname}; my $dbh_operator = $self->dbconnect_extern($sharee_operator); if($todo eq "update"){ $bw->log("UPDATE CMS operator $sharee_operator",$record_primary,""); my $update = { %$record_primary, table => "contentuser", }; $rows = $self->update_record($dbh_operator,$update,$record_primary); if($rows != 1){ my $insert = { %$record_primary, table => "contentuser", mtime => 'now()', }; my $c_id = $self->insert_contentoid($dbh_operator,$insert,""); $rows = 1 if($c_id); } }elsif($todo eq "delete"){ $bw->log("DELETE CMS operator $sharee_operator",$record_primary,""); $rows += $self->delete_content($dbh_operator,"contentuser",$record_primary->{c_id}); } } } } return $rows; }#end operators_cms #return system and contentadr username by c_id (owner last change) sub sys_username { my $self = shift; my $dbh = shift || $dbh_intern; my $owner = shift || ""; my $u_name = ""; if(looks_like_number($owner)){ my $channel_map = $self->channel_map(); foreach my $id (sort { $channel_map->{$a} cmp $channel_map->{$b} } keys (%$channel_map)){ if($id == $owner){ $u_name = $channel_map->{$id}; } } if(!$u_name){ my $users_pref = { table => "contentadr", fetch => "one", c_id => $owner, }; my $ct_users = $self->fetch_tablerecord($dbh,$users_pref); $u_name = $ct_users->{txt01}; } } return $u_name; } #collect serviceapp and DMS users for search select username u_id mapping sub users_map(){ my $self = shift; my $dbh = shift || $dbh_intern; my $mapref = shift || ""; my $and = ""; if(ref($mapref) eq "HASH"){ foreach my $key (keys (%$mapref)){ $and = " and u.$key=$mapref->{$key}" if($key =~ /int/); } } my $sql = "SELECT ct.* FROM contentadr ct, users u WHERE ct.c_id=u.u_id $and"; my $sth = $dbh->prepare($sql); my $rc = $sth->execute(); my $users_rec = $sth->fetchall_hashref('c_id'); $bw->log("DBtank users_map:",$sql,"") if($debug); return $users_rec; } #booking channel id's #TODO migrate all to global.cfg sub channel_map(){ my $self = shift; my $channel = { #167 => "sig cmd", 168 => "shareeio", 169 => "sigo connector", 172 => "reserve timeout", #173 => "merchant fallback",#mig 174 => "cronjob bonus", #175 => "cronjob cpdate", 176 => "Mein konrad App",#mig 177 => "LastenradBay App",#mig 178 => "payone API", 179 => "cronjob payone", #181 => "SMS API", #182 => "velofactur API", 183 => "Ilockit API", #184 => "web App",#mig #185 => "konstanz App",#mig 186 => "sharee.bike App",#mig 187 => "shareetool",#mig 188 => "sys API", 192 => "web Bayern", #193 => "web demo",#mig 195 => "web konrad",#mig and import 196 => "copri",#mig 197 => "web sharee.bike",#mig 198 => "primary",#mig 199 => "LV API",#mig 201 => "web Renta",#mig 294 => "example Web",#mig 295 => "example App",#mig 296 => "example Op",#mig 298 => "example Pr",#mig }; return $channel; } #get tpl sub get_tpl { my $self = shift; my $dbh = shift || $dbh_intern; my $tpl_id = shift || 0; my $sth = $dbh->prepare("SELECT * FROM template WHERE tpl_id='$tpl_id'"); my $rc = $sth->execute(); my $tpl = $sth->fetchrow_hashref(); return $tpl; } #all templates sub collect_tpl(){ my $self = shift; my $tpl_ids = shift || ""; my $dbh = shift || $dbh_intern; my $where = "where tpl_id != 98 and tpl_id != 97";#without meta-Config and EditNode $where .= " and tpl_id IN ($tpl_ids)" if($tpl_ids); my $sth = $dbh->prepare("SELECT * FROM template $where"); my $rc = $sth->execute(); my $tpl_all = $sth->fetchall_hashref("tpl_id"); return $tpl_all; } #get uri_path and meta data like tpl_order by menue path sub get_node_meta { my $self = shift; my $dbh = shift || $dbh_intern; my $viewsel = shift; my $node_name1 = $q->escapeHTML(@{$viewsel}[-1]); my @node_path = ("$node_name1"); my $where = "WHERE n.main_id=rel.main_id and rel.template_id=tpl.tpl_id and node_name = '$node_name1'"; pop @{$viewsel}; my @reverse_viewsel = reverse(@{$viewsel}); #print Dumper(@reverse_viewsel) . "
\n"; #bsp #SELECT * FROM nodes n,relation rel, template tpl WHERE n.main_id=rel.main_id and rel.template_id=tpl.tpl_id and n.node_name = 'Firma' and n.parent_id IN (SELECT n.main_id from nodes n where n.node_name='Einstellung' and n.parent_id IN (SELECT n.main_id from nodes n where n.node_name='JBW')); foreach(@reverse_viewsel){ #print $_ . "
\n"; my $node_nameX = $q->escapeHTML($_); push(@node_path, $node_nameX); $where .= " and n.parent_id IN (SELECT n.main_id from nodes n where n.node_name='$node_nameX'"; } foreach(@reverse_viewsel){ $where .= ")"; } my $sql = "SELECT n.owner AS nowner,n.change AS nchange,* FROM nodes n,relation rel, template tpl $where"; my $sth = $dbh->prepare($sql); my $rc = $sth->execute(); my $nrt = $sth->fetchrow_hashref(); my @reverse_node_path = reverse(@node_path); my $uri_path = ""; foreach(@reverse_node_path){ $uri_path .= "$_/"; } $uri_path =~ s/\/$//; $bw->log("get_node_meta $uri_path",$sql,"") if($debug); #print Dumper($nrt); return $nrt; } sub get_node { my $self = shift; my $dbh = shift || $dbh_intern; my $main_id = shift; my $sth = $dbh->prepare("SELECT * FROM nodes WHERE main_id=$main_id"); my $rc = $sth->execute(); my $node = $sth->fetchrow_hashref(); return $node; } # Nodes einer Ebene sub collect_node { my $self = shift; my $dbh = shift || $dbh_intern; my $main_id = shift; my $sth = $dbh->prepare("SELECT * FROM nodes WHERE parent_id=$main_id"); my $rc = $sth->execute(); my $nodes = $sth->fetchall_hashref("main_id"); my $rows = $sth->rows; return ($nodes,$rows); } #only used by dead_relation sub collect_relation { my $self = shift; my $dbh = shift || $dbh_intern; my $where = shift || "1=1"; my $sth = $dbh->prepare("SELECT * FROM relation where $where"); my $rc = $sth->execute(); my $rel = $sth->fetchall_hashref("rel_id"); return $rel; } #not used sub collect_relct { my $self = shift; my $dbh = shift || $dbh_intern; my $ref = shift; my $sth = $dbh->prepare("SELECT * FROM relation rel, $ref->{table} c where rel.content_id > 0 and rel.template_id=224 and rel.content_id=c.c_id order by rel.content_id"); my $rc = $sth->execute(); my $rel = $sth->fetchall_hashref("rel_id"); return $rel; } # Nodes einer Ebene mit relation sub collect_noderel { my $self = shift; my $dbh = shift || $dbh_intern; my $main_id = shift; my $template_id = shift || ""; #my $where = "WHERE n.main_id=rel.main_id and rel.content_id=0 and n.parent_id=$main_id"; my $where = "WHERE n.main_id=rel.main_id and rel.content_id=0 and n.parent_id=$main_id and node_public='t'"; $where .= " and rel.template_id=$template_id" if($template_id); my $sth = $dbh->prepare("SELECT * FROM nodes n, relation rel $where"); my $rc = $sth->execute(); my $nodes = $sth->fetchall_hashref("main_id"); my $rows = $sth->rows; return ($nodes,$rows); } #recursive node runner to get node path sub recurse_select { my $self = shift; my $dbh = shift || $dbh_intern; my $main_id = shift || ""; my $sth = $dbh->prepare("SELECT parent_id,node_name FROM nodes where main_id=$main_id"); my $rc = $sth->execute(); my $node = $sth->fetchrow_hashref(); return ($node->{parent_id},$node->{node_name}); } sub recurse_node { my $self = shift; my $dbh = shift || $dbh_intern; my $main_id = shift || ""; my $depth=$1 if($main_id =~ /^(\d)/); my $uri_path = "?failure=recurse_node"; my @nodes = (); if($main_id && $main_id > 20000){ $uri_path = ""; for(my $i=0; $i<$depth;$i++){ ($main_id,my $node_name) = $self->recurse_select($dbh,$main_id) if($main_id); push(@nodes, $node_name); #print $main_id . "|$node_name\n"; } my @node_path = reverse(@nodes); foreach(@node_path){ $uri_path .= "$_/"; } $uri_path =~ s/\/$//; } return $uri_path; } ############################### #get one subnode #ex. get contentpos template_id from subnode #select n.n_id,n.parent_id,n.main_id,rel.template_id from nodes n, relation rel where n.main_id=rel.main_id and n.parent_id=300029; # n_id | parent_id | main_id | template_id #------+-----------+---------+------------- # 431 | 300029 | 400004 | 401 sub get_subrelnode { my $self = shift; my $dbh = shift || $dbh_intern; my $main_id = shift; my $template_id = shift || ""; my $node_name = shift || ""; my $where = ""; $where .= " and rel.template_id = $template_id" if($template_id); $where .= " and n.node_name = '$node_name'" if($node_name); my $sql = "SELECT * FROM nodes n, relation rel where n.main_id=rel.main_id and n.parent_id=$main_id $where"; my $sth = $dbh->prepare($sql); my $rc = $sth->execute(); my $node = $sth->fetchrow_hashref(); $bw->log("get_subrelnode",$sql,""); return $node; } #because of different and dynamic pos templates we need template grouping sub pos_template_group { my $self = shift; my $dbh = shift || $dbh_intern; my $fetch = shift; my $ctcp_where = "1=1"; if($fetch->{table} eq "content" && $fetch->{table_pos} eq "contentpos"){ $ctcp_where .= " and ct.c_id=cp.cc_id"; }elsif($fetch->{table} eq "contentadr" && $fetch->{table_pos} eq "contentadrpos"){ $ctcp_where .= " and ct.c_id=cp.ca_id"; } my $sql = "SELECT tpl_id,tpl_order from template where tpl_id IN (SELECT cp.template_id from $fetch->{table_pos} cp, $fetch->{table} ct where $ctcp_where group by cp.template_id)"; my $sth = $dbh->prepare($sql); my $rc = $sth->execute(); my $templates = $sth->fetchall_hashref("tpl_id"); $bw->log("pos_template_group",$sql,""); return $templates; } #fetch relation, template, nodes sub fetch_rel4tpl4nd(){ my $self = shift; my $dbh = shift || $dbh_intern; my $fetch = shift; $fetch->{content_id}=0 if($fetch->{content_id} eq "null"); my $where = "WHERE nodes.main_id=relation.main_id and relation.template_id=template.tpl_id"; $where .= " and nodes.parent_id=$fetch->{parent_id}" if($fetch->{parent_id}); $where .= " and relation.main_id=$fetch->{main_id}" if($fetch->{main_id}); $where .= " and relation.content_id=$fetch->{content_id}" if($fetch->{content_id}); $where .= " and relation.template_id=$fetch->{template_id}" if($fetch->{template_id}); if($fetch->{template_id1} && $fetch->{template_id2}){ $where .= " and relation.template_id >= $fetch->{template_id1} and relation.template_id <= $fetch->{template_id2}"; } $where .= " and relation.rel_id=$fetch->{rel_id}" if($fetch->{rel_id}); $where .= " order by content_id $fetch->{ascdesc}" if($fetch->{ascdesc}); my $sql = "SELECT * FROM relation,template,nodes $where"; my $sth = $dbh->prepare($sql); my $rc = $sth->execute(); my $rel = { main_id => 0 }; if($fetch->{fetch} eq "all" && $fetch->{keyfield}){ $rel = $sth->fetchall_hashref($fetch->{keyfield}); }else{ $rel = $sth->fetchrow_hashref(); } #$bw->log("fetch_rel4tpl4nd ",$sql,"") if($debug); return $rel; } #azn time worktime from Von Bis sub select_worktime { my $self = shift; my $dbh = shift || $dbh_intern; my $fetch = shift; my $sql = "SELECT $fetch->{end_at} - $fetch->{start_at} AS worktime FROM $fetch->{table} where ct_id = $fetch->{ct_id} and barcode = $fetch->{barcode} and $fetch->{end_at} is not null and $fetch->{start_at} is not null"; my $sth = $dbh->prepare($sql); my $rc = $sth->execute(); my $record = $sth->fetchrow_hashref(); $bw->log("DBtank select_worktime: ",$sql,"") if($debug); return $record; } #all accounting position of contenttrans sub collect_contenttrans(){ my $self = shift; my $dbh = shift || $dbh_intern; my $ct_id = shift || ""; my $sth = $dbh->prepare("SELECT * FROM contenttrans where int20 = $ct_id"); my $rc = $sth->execute(); my $cpos = $sth->fetchall_hashref("c_id"); my $rows = $sth->rows; return ($cpos,$rows); } #all position of contenttrans sub collect_contentpos(){ my $self = shift; my $dbh = shift || $dbh_intern; my $table = shift; my $ct_id = shift || ""; my $where = "where ctt.c_id=pos.ct_id and ctt.c_id='$ct_id'"; if($ct_id){ my $sth = $dbh->prepare("SELECT pos.* FROM contenttranspos pos, contenttrans ctt $where"); my $rc = $sth->execute(); my $cpos = $sth->fetchall_hashref("c_id"); my $rows = $sth->rows; return ($cpos,$rows); }else{ my $cpos = { c_id => 0 }; my $rows = 0; return ($cpos,$rows); } } #Collect table ...post sub collect_post(){ my $self = shift; my $dbh = shift || $dbh_intern; my $fetch = shift; my $count = shift || ""; my $table; my $table_pos; my $ct_where = "1=1"; my $cp_where = "1=1"; my $ctcp_where = "1=1"; my $poscid = ""; if($fetch->{table} eq "content" && $fetch->{table_pos} eq "contentpos"){ #*2 $ctcp_where .= " and ct.c_id=cp.cc_id"; $poscid = "cp.cc_id"; }elsif($fetch->{table} eq "contentadr" && $fetch->{table_pos} eq "contentadrpos"){ #*1 $ctcp_where .= " and ct.c_id=cp.ca_id"; $poscid = "cp.ca_id"; }elsif(($fetch->{table} eq "contenttrans" && $fetch->{table_pos} eq "contenttranspos") || ($fetch->{table} eq "contenttver" && $fetch->{table_pos} eq "contenttverpos")){ #*3 $ctcp_where .= " and ct.c_id=cp.ct_id"; $poscid = "cp.ct_id"; }else{ return; } foreach my $key (keys %$fetch){ if($fetch->{$key}){ $fetch->{$key} =~ s/^\s//g; $fetch->{$key} =~ s/\s$//g; my $op = "="; my $value = $fetch->{$key}; ($op, $value) = split(/::/, $fetch->{$key}) if($fetch->{$key} =~ /::/); if($key =~ /^(ct_name|txt\d+)$/ && $value){ if($op eq "IN"){ $cp_where .= " and cp.$key $op $value"; }else{ if($key eq "txt01" && $value =~ /NaN/){ $cp_where .= " and $value"; }else{ $cp_where .= " and cp.$key $op '$value'"; } } }elsif($key =~ /ct\.close_time|ct\.state|ct\.int14/ && $value){#used to get open invoices $ct_where .= " and $key $op $value"; }elsif($key =~ /time/ && $value){ if($value =~ /interval/){ $cp_where .= " and cp.$key $op $value";#format like (now() - integer '7 day') }elsif($key eq "time_range"){ $cp_where .= " and $value";#look at only_first_free }else{ $cp_where .= " and cp.$key $op '$value'"; } }elsif($varenv{systype} && $varenv{systype} eq "azn"){ if($key =~ /^ct\.(contentadr_id|owner|barcode|int\d+)$/ && $value){ $ct_where .= " and $key $op $value"; }elsif($key eq "barcode" && $fetch->{fetch} eq "all"){ if($value =~ /\d-\d/){ my ($start_val,$end_val) = split(/-/, $value); $cp_where .= " and (cp.$key >= $start_val AND cp.$key <= $end_val)"; }else{ my $start_val = $value . "01"; my $end_val = $value . "31"; $cp_where .= " and (cp.$key >= $start_val AND cp.$key <= $end_val)"; } }elsif($key =~ /^(c_id|ca_id|ct_id|owner|barcode|int\d+)$/ && $value){ $cp_where .= " and cp.$key $op $value"; } }elsif($key =~ /^(c_id|ca_id|ct_id|owner|barcode|int\d+)$/ && $value){ $cp_where .= " and cp.$key $op $value"; }elsif($fetch->{catch} && $key eq "template_id" && $value){ $cp_where .= " and cp.$key $op $value"; #}elsif(!$fetch->{catch} && $key =~ /main_id|template_id/ && $value){ #$ct_where .= " and rel.$key $op $value"; } } } my $sth = ""; my $sql = ""; my $limit = ""; $limit = "LIMIT $count" if(looks_like_number($count)); if($fetch->{catch} && $fetch->{catch} eq "content_contentpos"){ $sql = "SELECT cp.* from $fetch->{table_pos} cp, $fetch->{table} ct where $ctcp_where and $cp_where and $ct_where order by cp.mtime DESC $limit"; $sth = $dbh->prepare($sql); }else{ #rental pos with capture booking ct.state #$sql = "SELECT cp.*, ct.state FROM $fetch->{table_pos} cp, $fetch->{table} ct WHERE $cp_where and cp.ct_id=ct.c_id and $poscid IN (SELECT ct.c_id FROM relation rel, $fetch->{table} ct WHERE rel.content_id=ct.c_id and $ct_where) order by cp.mtime ASC";#mtime aufsteigend get last (newest) entry $sql = "SELECT cp.*, ct.state FROM $fetch->{table_pos} cp, $fetch->{table} ct WHERE $cp_where and cp.ct_id=ct.c_id and $ct_where order by cp.mtime ASC";#mtime aufsteigend get last (newest) entry $sth = $dbh->prepare($sql); } $bw->log("DBtank collect_post ",$sql,"") if($debug); my $rc = $sth->execute(); my $record = { c_id => 0 }; if($fetch->{fetch} eq "all" && $fetch->{keyfield}){ $record = $sth->fetchall_hashref($fetch->{keyfield}); }elsif($fetch->{fetch} eq "one"){ $record = $sth->fetchrow_hashref(); } return $record; } #fetch CMS #coalesce works only on null values #It returns the first argument that is not null, from left to right sub fetch_cms { my $self = shift; my $dbh = shift || $dbh_intern; my $fetch = shift || {}; my $langfield = "txt02";#default to en my $lang = ""; $lang = lc($fetch->{lang}) if($fetch->{lang}); $langfield = "txt01" if($lang eq "de"); $langfield = "txt02" if($lang eq "en"); $langfield = "txt03" if($lang eq "fr"); my $wand = ""; $wand = "and ct_name like '$fetch->{ct_name}%'" if($fetch->{ct_name}); my $sql = "SELECT ct_name, coalesce($langfield, txt02, txt01) AS txt FROM contentuser, relation where template_id=194 and c_id=content_id $wand"; my $sth = $dbh->prepare($sql); my $rc = $sth->execute(); my $record = $sth->fetchall_hashref('ct_name'); return $record; }#end fetch_cms #fetch all|one content + relation + nodes sub fetch_record(){ my $self = shift; my $dbh = shift || $dbh_intern; my $fetch = shift; my $fetch_sql = shift || ""; my $where = "where ct.c_id=rel.content_id and nd.main_id=rel.main_id"; $where .= "$fetch_sql" if($fetch_sql);#enhancement to get bike_group OR my $order = ""; $order = "order by ct.barcode DESC" if($fetch->{table} eq "content"); foreach my $key (keys %$fetch){ if($fetch->{$key}){ $fetch->{$key} =~ s/^\s//g; $fetch->{$key} =~ s/\s$//g; my $op = "="; my $value = $fetch->{$key}; ($op, $value) = split(/::/, $fetch->{$key}) if($fetch->{$key} =~ /::/); #$value = $q->escapeHTML($value);#In DB context will always done by API #can also be "rel.main_id IN (300005,300024)" $where .= " and rel.$key $op $value" if($key =~ /^(parent_id|main_id|template_id|rel_id)$/ && $value); if($key =~ /^(ct_name$|txt\d+|uri\d+|state)$/ && $value){ if($value =~ /length/){ $where .= " and $value"; }elsif($value eq "null"){ $where .= " and (ct.$key is null OR ct.$key = '')"; }else{ $where .= " and ct.$key $op '$value'"; } } if($key =~ /^(c_id|barcode|int\d+|owner|contentadr_id)$/){ if(looks_like_number($value) || $value eq "null"){ if($value eq "null"){ $where .= " and (ct.$key is null OR ct.$key = 0)"; }else{ $where .= " and ct.$key $op $value"; } }elsif($op eq "IN"){ $where .= " and ct.$key $op $value"; } } if($key =~ /^(type_id)$/){ if(looks_like_number($value)){ $where .= " and nd.$key $op $value"; } } if($varenv{systype} && $varenv{systype} eq "azn" && $key =~ /start_time|end_time/){ if($key =~ /start_time/){ $where .= " and (ct.end_time >= '$fetch->{start_time}' AND ct.start_time <= '$fetch->{end_time}')"; $order = "order by ct.start_time DESC";#because to get ct_id for contenttverpos Übertrag } }elsif($key =~ /close_time$/ && $value){ $where .= " and ct.$key $op $value"; }elsif($key =~ /time$/ && $value){ if($value =~ /interval/){ $where .= " and ct.$key $op $value"; }else{ $where .= " and ct.$key $op '$value'"; } } } } #ct.* because of nd.txt01 and ct.txt01 . my $sql = "SELECT ct.*,rel.*,nd.node_name,nd.parent_id,nd.type_id,nd.energy_id FROM $fetch->{table} ct, relation rel, nodes nd $where $order"; my $sth = $dbh->prepare($sql); my $rc = $sth->execute(); #$bw->log("DBtank fetch_record : $rc",$sql,"") if($debug); my $record = { c_id => 0 }; if($fetch->{fetch} eq "all" && $fetch->{keyfield}){ $record = $sth->fetchall_hashref($fetch->{keyfield}); }elsif($fetch->{fetch} eq "one"){ $record = $sth->fetchrow_hashref(); } return $record; }#end fetch_record #fetch just in one table --> without relation ... sub fetch_tablerecord(){ my $self = shift; my $dbh = shift || $dbh_intern; my ($fetch) = @_; my $where = "where 1=1"; foreach my $key (keys %$fetch){ if($fetch->{$key}){ $fetch->{$key} =~ s/^\s//g; $fetch->{$key} =~ s/\s$//g; my $op = "="; my $value = $fetch->{$key}; ($op, $value) = split(/::/, $fetch->{$key}) if($fetch->{$key} =~ /::/); #print "$key: $fetch->{$key}|$op, $value\n"; #$value = $q->escapeHTML($value);#In DB context will always done by API if($key =~ /ct_name/ && $value =~ /CAST/){#CAST(c_id AS text) $where .= " and $key $op $value"; }elsif($key =~ /^(ct_name$|txt\d+|uri\d+|state)$/ && $value){ if($value =~ /length\($key\)/){ $where .= " and $value"; }elsif($value eq "null"){ $where .= " and $key $op $value"; }elsif($op eq "IN"){ $where .= " and $key $op $value"; }else{ $where .= " and $key $op '$value'"; } }elsif($key =~ /_itime$/ && $value){ $where .= " and itime $op '$value'"; }elsif($key =~ /start_mtime|end_mtime/ && $value){ $key =~ s/start_mtime/mtime/; $key =~ s/end_mtime/mtime/; $where .= " and $key $op '$value'"; }elsif($key =~ /time$/ && $value && $value =~ /interval/){#<= (now() - interval '15 minutes') $where .= " and $key $op $value"; }elsif($key =~ /time$|time\d+/ && $value){ $where .= " and $key $op '$value'"; }elsif($key eq "time_range"){#used for freed_time on request $where .= " and $value"; }elsif($key =~ /^(c_id|u_id|cc_id|ct_id|ca_id|barcode|int\d+|owner|template_id)$/ && (looks_like_number($value) || $value eq "null")){ if($value eq "null"){ $where .= " and ($key is null OR $key = 0)"; }elsif($value eq "nullOR1"){ $where .= " and ($key is null OR $key = 1)"; }else{ $where .= " and $key $op $value"; } }elsif($key =~ /int\d+/ && $op eq "IN"){ $where .= " and $key $op $value"; } } } #prio data with newest end_time if($fetch->{table} eq "contenttranspos"){ $where .= " order by end_time DESC"; }elsif($fetch->{order}){ $where .= " order by $fetch->{order} DESC"; } my $sql = "SELECT * FROM $fetch->{table} $where"; my $sth = $dbh->prepare($sql); my $rc = $sth->execute(); #$bw->log("DBtank fetch_tablerecord :",$sql,"") if($debug); my $record = { c_id => 0 }; if($fetch->{fetch} eq "all" && $fetch->{keyfield}){ $record = $sth->fetchall_hashref($fetch->{keyfield}); }elsif($fetch->{fetch} eq "one"){ $record = $sth->fetchrow_hashref(); } return $record; }#end fetch_tablerecord #update sql sub update_sql(){ my $self = shift; my $dbh = shift || $dbh_intern; my $update_sql = shift; my $rows = 0; my $sql = "$update_sql"; my $sth = $dbh->prepare($sql); $rows = $sth->execute(); $bw->log("DBtank update_sql: $rows",$sql,"") if($debug); return $rows; } #update one value sub update_one(){ my $self = shift; my $dbh = shift || $dbh_intern; my $update = shift; my $one_in = shift || ""; my $c_id = shift || ""; my $rows = 0; my $where = ""; if($c_id){ $where = "where c_id = $c_id"; }elsif($update->{c_id}){ $where = "where c_id = $update->{c_id}"; } if($update->{table} eq "users" && $update->{u_id}){ $where = "where u_id = $update->{u_id}"; } if($update->{table} eq "nodes" && $update->{main_id}){ $where = "where main_id = $update->{main_id}"; } if($update->{table} eq "relation" && $update->{main_id}){ $where = "where main_id = $update->{main_id} and content_id=0"; } if($update->{table} eq "relation" && $update->{rel_id}){ $where = "where rel_id = $update->{rel_id}"; } if($update->{table} eq "template" && $update->{tpl_id}){ $where = "where tpl_id = $update->{tpl_id}"; } my $one = $one_in; if($update->{table} =~ /^users|relation|node|template/){ $one .= ",change='now()'" if($update->{change} ne "no_time"); }else{ $one .= ",mtime='now()'" if($update->{mtime} ne "no_time"); } $one .= ",owner=$update->{owner}" if($update->{owner}); #only update if input if($where && $one_in){ my $sql = "UPDATE $update->{table} set $one $where"; my $sth = $dbh->prepare($sql); $rows = $sth->execute(); $bw->log("DBtank update_one : $rows",$sql,"") if($debug); } return $rows; } #update all sub update_record(){ my $self = shift; my $dbh = shift || $dbh_intern; my $update = shift; my $record = shift; my $where = ""; my $set = ""; my $rows = 0; #print Dumper($update); if(looks_like_number($record->{c_id}) || (looks_like_number($record->{barcode}) && $record->{barcode} > 0)){ if($record->{c_id}){ $where = "where c_id = $record->{c_id}"; }else{ $where = "where barcode = $record->{barcode}"; } foreach my $key (keys %$update){ $update->{$key} =~ s/^\s//g if($update->{$key}); $update->{$key} =~ s/\s$//g if($update->{$key}); my $value = $update->{$key} || ""; $value = "$update->{$key}" if(looks_like_number($update->{$key})); if($key =~ /^(ct_name$|txt\d+|state|start_time|end_time|byte)/){ if($value && $value eq "null"){ $set .= " $key=$value,"; }else{ $set .= " $key='$value',"; } } if($key =~ /^(barcode|contentadr_id|int\d+|time\d+|owner|owner_end|start_at\d+|end_at\d+)$/){ $value =~ s/,/\./ if($value); if($key =~ /int\d+|time\d+|start_at\d+|end_at\d+/ && $value && $value =~ /\d+:\d+/){#azn time format $set .= " $key='$value',"; }elsif(looks_like_number($value) || ($value && $value eq "null")){ $set .= " $key=$value,"; }elsif($key =~ /int\d+/ && !$value){ $set .= " $key=null,";#we need this for null values in operators loop } } if($key =~ /(mtime|atime|pay_time|invoice_time|warn_time)$/){ if($value && $value =~ /^\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}|^\d{2}\.\d{2}\.\d{4}$/){ $set .= " $key='$value',"; }elsif($key =~ /warn_time/ && $value eq "null"){ $set .= " $key=null,"; }else{ $set .= " $key='now()',"; } } } } if($set){ $set =~ s/,$//; my $sql = "UPDATE $update->{table} set $set $where"; my $sth = $dbh->prepare($sql); $rows = $sth->execute(); #$bw->log("DBtank update_record : $rows",$sql,"") if($debug); } return $rows; }#update_record #insert content sub insert_users { my $self = shift; my $dbh = shift || $dbh_intern; my $u_id = shift; my $owner = shift; my $sql = "INSERT INTO users (u_id,itime,mtime,owner) VALUES ('$u_id','now()','now()','$owner')"; my $sth = $dbh->prepare($sql); my $rows = $sth->execute(); $bw->log("DBtank INSERT DMS users $rows",$sql,"") if($debug); return $u_id; } sub select_users(){ my $self = shift; my $dbh = shift || $dbh_intern; my $u_id = shift || 0; my $sqlcon = shift || "";#used with "and int09=1" my $sql = "SELECT * FROM users WHERE u_id=$u_id $sqlcon"; my $sth = $dbh->prepare($sql); my $rc = $sth->execute(); my $users = $sth->fetchrow_hashref(); $bw->log("DBtank SELECT DMS users u_id: $users->{u_id}",$sql,"") if($debug); return $users; } #insert_content with all sub insert_contenthash(){ my $self = shift; my $dbh = shift || $dbh_intern; my $table = shift; my $sethash = shift; my ($keys,$values); if(ref($sethash) eq "HASH"){ foreach my $key (sort (keys(%$sethash))){ $keys .= $key . ","; $values .= "\'$sethash->{$key}\'" . ","; } $keys =~ s/,$//; $values =~ s/,$//; } #print "$keys --> $values\n"; my $sth = $dbh->prepare("INSERT INTO $table ($keys) VALUES ($values)"); my $rows = $sth->execute(); return $rows; } #insert content sub insert_contentoid { my $self = shift; my $dbh = shift || $dbh_intern; my $insert = shift; my $reset_keys = shift || ""; my $source = $dbh->get_info( $GetInfoType{SQL_DATABASE_NAME} ); if($insert->{table} eq "contentadr" && $reset_keys eq "reset_adropkeys"){ delete $insert->{txt17};#operators delete $insert->{txt30};#tarifs delete $insert->{txt15};#Bonusnr delete $insert->{int05};#Web-Login delete $insert->{int07};#Rabatt delete $insert->{int09};#Service App staff delete $insert->{int16};#payone-cron-interval delete $insert->{int19};#Ilockit Admin #delete $insert->{int12};#Vde (remove delete for global setting) delete $insert->{txt29};#Sonstiges } my $columns = ""; my $values = ""; foreach my $key (keys(%$insert)){ $insert->{$key} =~ s/^\s//g if($insert->{$key}); $insert->{$key} =~ s/\s$//g if($insert->{$key}); #because of time format without of looks_like_number if($varenv{systype} && $varenv{systype} eq "azn" && $insert->{table} eq "contenttverpos" && $key =~ /start_at|end_at|int/){ $columns .= "$key,"; if(!$insert->{$key} || $insert->{$key} eq "null"){ $values .= "null,"; }else{ $values .= "'$insert->{$key}',"; } } elsif($key =~ /^c_id|ct_name|barcode|txt|int|time|owner|byte/ && ($insert->{$key} || looks_like_number($insert->{$key}))){ $columns .= "$key,"; if($key =~ /_id|barcode|int|owner/ && !looks_like_number($insert->{$key})){ $values .= "null,"; }else{ $values .= "'$insert->{$key}',"; } } elsif($key =~ /template_id|cc_id|ct_id|ca_id/ && $insert->{table} =~ /contentpos|contentadrpos|contenttranspos|contenttheftpos/){ $columns .= "$key,"; if(!looks_like_number($insert->{$key})){ $values .= "null,"; }else{ $values .= "'$insert->{$key}',"; } } } $columns =~ s/,$//; $values =~ s/,$//; my $sql = "INSERT INTO $insert->{table} ($columns) VALUES ($values) RETURNING c_id"; my $sth = $dbh->prepare($sql); my $rows = $sth->execute(); my $last_id; $sth->bind_columns(\$last_id); my $c_id = $sth->fetchrow_array(); $bw->log("insert_contentoid $source c_id: $c_id",$sql,"") if($debug); if($insert->{table} =~ /content$|contentadr$|contenttrans$|contenttver$|contentuser$/ && $insert->{main_id} && $insert->{template_id}){ my $foreignkey = ""; $foreignkey = "ca_id" if($insert->{table} eq "contentadr"); $foreignkey = "cc_id" if($insert->{table} eq "content"); $foreignkey = "ct_id" if($insert->{table} eq "contenttrans"); $foreignkey = "cu_id" if($insert->{table} eq "contentuser"); $foreignkey = "cv_id" if($insert->{table} eq "contenttver"); my $sql_rel = "INSERT INTO relation (main_id,content_id,template_id,change,$foreignkey) VALUES('$insert->{main_id}','$c_id','$insert->{template_id}','now()','$c_id')"; my $sth3 = $dbh->prepare($sql_rel); $sth3->execute(); $bw->log("insert_contentoid relation $source c_id: $c_id",$sql_rel,"") if($debug); } return $c_id; } #delete content sub delete_content(){ my $self = shift; my $dbh = shift || $dbh_intern; my $table = shift; my $c_id = shift || 0; my $template_id = shift || ""; my $rows = 0; if($c_id){ my $where = "c_id=$c_id"; $where = "template_id = $template_id" if($table eq "contentpos" && $template_id && $c_id eq "all"); $where = "u_id=$c_id" if($table eq "users"); my $sql = "DELETE FROM $table WHERE $where"; my $sth = $dbh->prepare($sql); $rows = $sth->execute(); $bw->log("delete_content : $rows",$sql,"") if($debug); } return $rows; } #collect contenttranspos with contenttrans sub collect_transpos { my $self = shift; my $dbh = shift || $dbh_intern; my $search = shift; $search->{offset} = 0 if(!$search->{offset}); my $where = "where cp.ct_id=ct.c_id"; $where .= " and cp.int05 is null";#do not select sub workflow docs like storno foreach my $key (keys (%$search)){ $search->{$key} =~ s/^\s//g; $search->{$key} =~ s/\s$//g; $where .= " and cp.c_id = $search->{$key}" if(($key eq "c_id" || $key eq "cttpos_id") && $search->{$key}); $where .= " and cp.$key ilike '%$search->{$key}%'" if($key eq "txt08" && $search->{$key}); $where .= " and cp.$key ilike '%$search->{$key}%'" if($key eq "txt23" && $search->{$key}); $where .= " and cp.int04 = $search->{$key}" if($key eq "int04" && looks_like_number($search->{$key})); $where .= " and cp.int06 = $search->{$key}" if($key eq "int06" && looks_like_number($search->{$key})); $where .= " and cp.ct_name = '$search->{$key}'" if($key eq "cp_ct_name" && $search->{$key}); $where .= " and ct.ct_name = '$search->{$key}'" if($key eq "ct_ct_name" && $search->{$key}); $where .= " and ct.txt06 ilike '$search->{$key}%'" if($key eq "ct_txt06" && $search->{$key}); $where .= " and cp.$key = '$search->{$key}'" if($key eq "ct_id" && looks_like_number($search->{$key})); $where .= " and cp.$key = $search->{$key}" if($key eq "int10" && looks_like_number($search->{$key})); $where .= " and cp.$key = $search->{$key}" if($key eq "int20" && looks_like_number($search->{$key})); $where .= " and cp.$key = $search->{$key}" if($key eq "barcode" && looks_like_number($search->{$key})); $where .= " and cp.$key = $search->{$key}" if($key eq "int12" && looks_like_number($search->{$key})); $where .= " and (cp.$key = $search->{$key} OR cp.owner_end = $search->{$key})" if($key eq "owner" && looks_like_number($search->{$key})); $where .= " and (cp.$key is $search->{$key} OR cp.$key = 0)" if($key eq "int34" && $search->{$key} eq "null"); } #adding itime to get also not rental dependent entries if($search->{start_date_time} && $search->{end_date_time}){ $where .= " and ((cp.end_time >= '$search->{start_date_time}' and cp.end_time <= '$search->{end_date_time}' and cp.start_time <= '$search->{end_date_time}') OR (cp.itime >= '$search->{start_date_time}' and cp.itime <= '$search->{end_date_time}'))"; }elsif($search->{start_time_interval}){ $where .= " and cp.start_time <= $search->{start_time_interval}"; } $where .= " ORDER BY cp.c_id DESC LIMIT $search->{limit} OFFSET $search->{offset}" if($search->{limit}); my $sql = "SELECT cp.*,ct.txt07 AS phone from $search->{table} cp, contenttrans ct $where"; my $sth = $dbh->prepare($sql); my $rc = $sth->execute(); my $ct = $sth->fetchall_hashref("c_id"); #$bw->log("collect_transpos",$sql,"") if($debug); return $ct; } #collect contenttheftpos sub collect_theftpos { my $self = shift; my $dbh = shift || $dbh_intern; my $search = shift; $search->{offset} = 0 if(!$search->{offset}); my $where = "where 1=1"; foreach my $key (keys (%$search)){ if($search->{$key} =~ /::/ && $key =~ /int\d+/){ $search->{$key} =~ s/\s//g; my $op = "="; my $value = $search->{$key}; ($op, $value) = split(/::/, $search->{$key}); $where .= " and $key $op $value"; }elsif($key eq "speedORmeter"){ $where .= " and $search->{$key}"; }else{ $search->{$key} =~ s/\s//g; $where .= " and cp.c_id = $search->{$key}" if($key eq "cttpos_id" && $search->{$key}); $where .= " and cp.end_time >= '$search->{$key}'" if($key eq "start_date_time"); $where .= " and cp.end_time <= '$search->{$key}'" if($key eq "end_date_time"); $where .= " and cp.start_time <= '$search->{$key}'" if($key eq "end_date_time"); $where .= " and cp.$key ilike '%$search->{$key}%'" if($key eq "txt06" && $search->{$key}); $where .= " and cp.$key = $search->{$key}" if($key eq "int10" && looks_like_number($search->{$key}));#bike_state $where .= " and cp.$key = $search->{$key}" if($key eq "int20" && looks_like_number($search->{$key}));#lock_state $where .= " and cp.$key = $search->{$key}" if($key eq "barcode" && looks_like_number($search->{$key})); $where .= " and cp.$key = $search->{$key}" if($key eq "int12" && looks_like_number($search->{$key}));#flot_id $where .= " and cp.$key = $search->{$key}" if($key eq "int13" && looks_like_number($search->{$key}));#deviceId $where .= " and cp.$key = $search->{$key}" if($key eq "owner" && looks_like_number($search->{$key})); } } $where .= " ORDER BY cp.c_id DESC LIMIT $search->{limit} OFFSET $search->{offset}" if($search->{limit}); my $sth = $dbh->prepare("SELECT cp.* from $search->{table} cp $where"); my $rc = $sth->execute(); my $ct = $sth->fetchall_hashref("c_id"); $sth->finish; return $ct; } # new node sub insert_nodeoid(){ my $self = shift; my $dbh = shift || $dbh_intern; my $insert = shift; my $node_name = $insert->{node_name}; my $node_path = $insert->{node_name}; ($node_name,$node_path) = split(/\|/,$node_name) if($node_name =~ /\|/); my $sth2 = $dbh->prepare("INSERT INTO nodes (main_id,parent_id,node_name,node_path,n_sort,owner,node_public) VALUES('$insert->{main_id}','$insert->{parent_id}','$node_name','$node_path','$insert->{n_sort}','$insert->{owner}','t')"); my $rc = $sth2->execute(); $sth2 = $dbh->prepare("INSERT INTO relation (main_id,template_id,content_id,change) VALUES('$insert->{main_id}','$insert->{template_id}','$insert->{content_id}','now()') RETURNING rel_id"); $rc = $sth2->execute(); my $last_id; $sth2->bind_columns(\$last_id); my $rel_id = $sth2->fetchrow_array(); return $rel_id; } # Delete node and relation! (without content) sub delete_noderel(){ my $self = shift; my $dbh = shift || $dbh_intern; my $main_id = shift; my $sth = $dbh->prepare("DELETE FROM relation WHERE main_id=$main_id and content_id=0"); my $rc = $sth->execute(); $sth = $dbh->prepare("DELETE FROM nodes WHERE main_id=$main_id"); $rc = $sth->execute(); $sth->finish(); return $rc; } sub delete_relation(){ my $self = shift; my $dbh = shift || $dbh_intern; my $rel_id = shift; my $sth = $dbh->prepare("DELETE FROM relation WHERE rel_id=$rel_id"); my $rc = $sth->execute(); return $rc; } sub delete_template(){ my $self = shift; my $dbh = shift || $dbh_intern; my $tpl_id = shift; my $sth = $dbh->prepare("DELETE FROM template WHERE tpl_id=$tpl_id"); my $rc = $sth->execute(); return $rc; } # get next free node sub get_freenode(){ my $self = shift; my $dbh = shift || $dbh_intern; my $prefix_id = shift; my $s_id = "$prefix_id"; my $e_id = "$prefix_id"; $s_id .= "00001"; $e_id .= "99999"; my $main_id = ""; for (my $x_id=$s_id; $x_id < $e_id; $x_id++){ my $sth1 = $dbh->prepare("SELECT main_id from nodes where main_id='$x_id'"); my $rc1 = $sth1->execute(); $main_id = $sth1->fetchrow_array(); if(!$main_id){ return $x_id; } } } # # get next free template id sub get_freetpl(){ my $self = shift; my $dbh = shift || $dbh_intern; my ($s_id,$e_id) = @_; my $tpl_id = ""; for (my $x_id=$s_id; $x_id < $e_id; $x_id++){ my $sth1 = $dbh->prepare("SELECT tpl_id from template where tpl_id='$x_id'"); my $rc1 = $sth1->execute(); $tpl_id = $sth1->fetchrow_array(); if(!$tpl_id){ return $x_id; } } } # sub rental_description_template { my $self = shift; my $varenv = shift; my $tpl_order = { 1 => {int35 => "$varenv->{cms}->{'tarif-rental-fee'}->{txt}"},#unit_price1 2 => {int36 => "$varenv->{cms}->{'tarif-rental-fee-from-second-day'}->{txt}"},#unit_price2 #3 => {int37 => "Grundgebühr"},#startup_price 4 => {int17 => "$varenv->{cms}->{'tarif-max-fee'}->{txt}"},#max_fee/day 5 => {time01 => "$varenv->{cms}->{'tarif-time-unit'}->{txt}"},#unit_time 6 => {time02 => "$varenv->{cms}->{'tarif-rental-free-time'}->{txt}"},#free_time 7 => {xduration => "$varenv->{cms}->{'tarif-current-rental-period'}->{txt}"}, 8 => {xprice => "$varenv->{cms}->{'tarif-current-rental-cost'}->{txt}"}, }; return $tpl_order; } sub time_format { my $self = shift; my $varenv = shift; my $time = shift; my $time_unit = ""; my $day = ""; if($time =~ /(\d+) day/){ $day = $1; if($1 > 0 && $1 <= 1){ $day .= " $varenv->{cms}->{'unit-day'}->{txt} "; }else{ $day .= " $varenv->{cms}->{'unit-days'}->{txt} "; } $time_unit .= $day; $time =~ s/\d+ day //; } my ($std,$min,$sec) = split(/:/,$time); $std =~ s/^0//; $min =~ s/^0//; $time_unit .= "$std $varenv->{cms}->{'unit-hour'}->{txt} " if($std > 0); $time_unit .= "$min $varenv->{cms}->{'unit-minute'}->{txt} " if($min > 0); return $time_unit; } # copy template sub copy_template(){ my $self = shift; my $dbh = shift || $dbh_intern; my $master_tpl_id = shift; my $new_tpl_id = shift; my $new_tpl_name = shift; my $owner = shift; my $columns = "tpl_name,tpl_order,ct_table,tpl_height,tpl_width,bg_color"; my $sql = "INSERT INTO template ($columns) SELECT $columns from template where tpl_id=$master_tpl_id RETURNING tpl_id"; my $sth = $dbh->prepare($sql); my $rows = $sth->execute(); my $last_id; $sth->bind_columns(\$last_id); my $auto_tpl_id = $sth->fetchrow_array(); $bw->log("DBtank copy_template : $rows",$sql,"") if($debug); my $sth2 = $dbh->prepare("UPDATE template set tpl_id=$new_tpl_id, tpl_name='$new_tpl_name', change='now()',owner=$owner where tpl_id=$auto_tpl_id"); $rows = $sth2->execute(); return $new_tpl_id; } #copy content sub copy_content { my $self = shift; my $dbh = shift || $dbh_intern; my $table = shift; my $sourcec_id = shift; my $targetc_id = shift; my $new_ct_name = shift; my $owner = shift; my $rows = 0; my $cref = { table => $table, fetch => "one", c_id => $sourcec_id, }; my $record = { c_id => 0 }; $record = $self->fetch_record($dbh,$cref); if($record->{c_id} > 0){ delete $record->{c_id}; delete $record->{ct_name}; delete $record->{itime}; delete $record->{mtime}; delete $record->{owner}; my $update = { %$record, table => $table, ct_name => $new_ct_name, mtime => 'now()', owner => $owner, c_id => $targetc_id, }; $rows = $self->update_record($dbh,$update,$update); if($rows != 1){ my $newc_id = $self->insert_contentoid($dbh,$update,""); $rows = 1 if($newc_id); } } return; } #content of txt08 changed to ctadr->{txt01} Name sub insert_pos(){ my $self = shift; my $dbh = shift || $dbh_intern; my $ctt_id = shift; my $ct = shift || {}; my $ct_station = shift || {}; my $ctadr = shift || {}; my $ct_tariff = shift || ""; my $endRental = shift || "0000-00-00"; my $ct_name = shift || ""; my $status = shift || ""; my $owner = shift || ""; my $sig_book = shift || {}; my $aa_station = $ct_station->{int42} || 0; $ct_name = $ct->{barcode} if(!$ct_name);#artikelnr or bikenr my $prefix = ""; $ct_name =~ s/S[1-9]X/SX/;#sig $prefix = $1 if($ct_name =~ /^([A-Z]+)(\d+)$/i); my $user_name = $ctadr->{txt01}; $user_name = $ctadr->{txt08} if(!$user_name || $user_name eq "no name"); my $staff = 0; $staff = 1 if($ctadr->{int09});#service staff (no sms message) my $deviceId = $ct->{int13} || 0; my $bike_charge = $ct->{int19} || 0; my $trackon = $ct->{int25} || 0; my $bike_type_id = $ct->{type_id} || 0; my $from_main_id = $ct->{main_id} || 0; my $from_template_id = $ct->{template_id} || 0; my $start_station = $ct->{int04} || 0; my $end_station = "null";#2023-07-12 will be not set on request. my $fibumark = $ct->{int16} || 0; my $rabatt = 0; my $unit_price = $ct->{int02} || 0;#article price my $unit_price1 = 0; my $unit_price2 = 0; my $start_price = 0; my $daymax_price = 0; my $startup_price = 0; my $abo_price = 0;#not used my $unit_time = "00:00"; my $free_time = "00:00"; my $tariff_nr = 0; my $tariff_desc; my $sharing_type = 0; my $menge = 0; if(ref($ct_tariff) eq "HASH" && $ct_tariff->{barcode}){ $rabatt = $ctadr->{int07} || 0; $unit_price = $ct_tariff->{int02} || 0;#old and should in future not used by rental $unit_price1 = $ct_tariff->{int35} || 0; $unit_price2 = $ct_tariff->{int36} || 0; $start_price = $ct_tariff->{int37} || 0; $abo_price = $ct_tariff->{int15} || 0;#not used $daymax_price = $ct_tariff->{int17} || 0; $tariff_nr = $ct_tariff->{barcode} || 0; $tariff_desc = $ct_tariff->{ct_name}; $unit_time = $ct_tariff->{time01} || "00:00"; $free_time = $ct_tariff->{time02} || "00:00"; $sharing_type = $ct_tariff->{int18} || 0; } my $sth; #Verleihräder if($ct->{template_id} && $ct->{template_id} == 205){#Leihrad_list $sth = $dbh->prepare("INSERT INTO contenttranspos (ct_id,cc_id,ca_id,ct_name,barcode,txt01,txt08,txt02,txt09,txt12,itime,start_time,end_time,int01,int02,int03,int06,txt05,txt06,txt07,int10,int12,template_id,int13,owner,int07,txt04,int09,int17,int15,int11,int18,int19,txt17,txt18,int20,int25,int29,int34,txt22,txt11,int35,int36,int37,int42,time01,time02) VALUES ('$ctt_id','$ct->{c_id}','$ctadr->{c_id}','$ct_name','$ct->{barcode}','$ct->{txt01}','$user_name','$ct->{txt02}','$ctadr->{txt09}','$prefix',now(),now(),'$endRental','1','$unit_price','$menge','$start_station','$ct->{txt06}','$ct->{txt06}','$ct->{txt07}','$status','$from_main_id','$from_template_id','$deviceId','$owner','$rabatt','$tariff_desc','$tariff_nr','$daymax_price','$abo_price','$ct->{int11}','$sharing_type','$bike_charge','$ct->{txt17}','$ct->{txt18}','1','$trackon','$bike_type_id','$staff','$sig_book->{bikeId}','$sig_book->{rentalId}','$unit_price1','$unit_price2','$start_price','$aa_station','$unit_time','$free_time') RETURNING c_id"); }else{ $sth = $dbh->prepare("INSERT INTO contenttranspos (ct_id,cc_id,ca_id,ct_name,barcode,txt08,txt09,itime,int01,int02,int03,txt01,txt06,txt07,int10,int12,int16,template_id,owner) VALUES ('$ctt_id','$ct->{c_id}','$ctadr->{c_id}','$ct_name','$ct->{barcode}','$user_name','$ctadr->{txt09}',now(),'1','$unit_price','1','$ct->{txt01}','$ct->{txt06}','$ct->{txt07}','0','$from_main_id','$fibumark','$from_template_id','$owner') RETURNING c_id"); } my $rows = $sth->execute(); my $last_id; $sth->bind_columns(\$last_id); my $c_id = $sth->fetchrow_array(); if($c_id && $status){ #update Leihräder in Stammdaten my $set2 = "owner=$owner" if($owner); $set2 .= ",int10='$status'" if($status); $set2 .= ",mtime='now()'"; my $sth2 = $dbh->prepare("UPDATE content SET $set2 where c_id='$ct->{c_id}'"); my $rows2 = $sth2->execute(); } return $c_id; } # insert contenttrans sub insert_contenttrans(){ my $self = shift; my $dbh = shift || $dbh_intern; my $ctadr = shift; my $main_id = shift; my $tpl_id = shift; my $invoice_nr = shift || "----"; my $owner = shift || 0; $owner="199" if(!$owner); my $sth = $dbh->prepare("INSERT INTO contenttrans (ct_name,txt00,int10,txt02,txt01,txt03,txt06,txt07,txt08,owner,itime) VALUES('$invoice_nr','Rechnung','$ctadr->{c_id}','$ctadr->{txt02}','$ctadr->{txt01}','$ctadr->{txt03}','$ctadr->{txt06}','$ctadr->{txt07}','$ctadr->{txt08}','$owner','now()') RETURNING c_id"); my $rows = $sth->execute(); my $last_id; $sth->bind_columns(\$last_id); my $c_id = $sth->fetchrow_array(); my $sth3 = $dbh->prepare("INSERT INTO relation (ct_id,content_id,template_id,main_id,change) VALUES('$c_id','$c_id','$tpl_id','$main_id','now()')"); $sth3->execute(); return $c_id; } #compute amount of wawi content sub update_content4comp(){ my $self = shift; my $dbh = shift || $dbh_intern; my $c_id = shift || 0; my $op = shift; my $amount = shift; my $where = "c_id=$c_id"; my $ct_set = "int03=(int03 $op $amount)"; my $sth = $dbh->prepare("UPDATE content SET $ct_set where $where"); my $rows = $sth->execute(); return $rows; } #should be in DB sub evaluationsfragen { my $self = shift; my $dbh = shift || $dbh_intern; my $user_miniquery = { title => "Bitte unterstützen Sie unsere Begleitforschung", subtitle => "Ihre drei Antworten werden anonym gespeichert.", footer => "Herzlichen Dank und viel Spaß bei der nächsten Fahrt!", questions => { q1 => { type => "check_one", quest_text => "1. Frage: Was war der Hauptzweck dieser Ausleihe?", query => { opt1 => "1. Einkauf", opt2 => "2. Kinderbeförderung", opt3 => "3. Freizeitaktivitäten, wie Ausflüge", opt4 => "4. Nutzung ohne Lastentransport", opt5 => "5. Gewerbliche Zwecke", opt6 => "6. Ausprobieren", opt7 => "7. Sonstiger Zweck" } }, q2 => { type => "check_one", quest_text => "2. Frage: Welches Verkehrsmittel hätten Sie ohne Mietlastenrad für diese Fahrt genutzt?", query => { opt1 => "1. Fahrrad", opt2 => "2. Auto", opt3 => "3. Zu Fuß", opt4 => "4. Bus/Bahn", opt5 => "5. Anderes Lastenrad", opt6 => "6. Motorad/-roller", opt7 => "7. Keins (ich hätte den Weg nicht gemacht)", opt7 => "8. Sonstige" } }, q3 => { type => "text", quest_text => "3. Haben Sie Anmerkungen oder Anregungen?", query => { opt1 => "" } } } }; return $user_miniquery; } #search table content. sub search_content(){ my $self = shift; my $dbh = shift || $dbh_intern; my $searchref = shift; my $node_meta = shift; my $users_dms = shift; my $main_ids = shift || ""; my $tplids = shift || ""; my $ct_ids = shift || ""; my $v_journal = shift || ""; my $ck4ex = shift || ""; my $table = $node_meta->{ct_table}; $main_ids =~ s/,$//; $tplids =~ s/,$//; $ct_ids =~ s/,$//; $ck4ex =~ s/\s/,/g; $ck4ex =~ s/,$//; my $owner = $users_dms->{u_id}; my $sort_updown = $users_dms->{sort_updown}; my $scol = $searchref->{scol}; my $offset = $searchref->{offset}; my $limit = $searchref->{limit}; my $export = $searchref->{export}; my $opos = $searchref->{opos}; my $stamp_time = strftime("%d.%m.%Y %H:%M",localtime(time)); my $debug=0; $debug=1; open(FILE,">>$varenv{logdir}/Liste3.log") if($debug); print FILE "*** $stamp_time Libenzdb.search_content3 ***\n" if($debug); print FILE Dumper($searchref) if($debug); print FILE "$table,$node_meta->{node_name},$owner,$main_ids,$tplids,$ct_ids,$v_journal,$ck4ex\n" if($debug); close(FILE) if($debug); my $table_pos = $searchref->{table_pos} || ""; my $txt_where; my $cptxt_where; my $cpgroup_where; my $valref = {}; my $opref = {}; foreach my $key (keys(%$searchref)){ if($searchref->{$key} || $searchref->{$key} eq "0"){ $valref->{$key} = $searchref->{$key}; $opref->{$key} = "="; ($opref->{$key}, $valref->{$key}) = split(/::/, $searchref->{$key}) if($searchref->{$key} =~ /::/); if($key =~ /table_pos/){ $table_pos = $valref->{$key}; } if($key =~ /c_id|int\d+|barcode|time|sort|owner/){ $searchref->{$key} =~ s/,/./g; if($searchref->{$key} =~ /(\<\=|\>\=|\<|\>|\=)/){ $opref->{$key} = $1; } if($searchref->{$key} =~ /([-0-9\.]+)/){ $valref->{$key} = $1; } if($searchref->{$key} =~ /null/){ $opref->{$key} = "is"; } chomp($valref->{$key}); } $valref->{$key} = $q->escapeHTML($valref->{$key}); #print $key . ":" . $opref->{$key} . ":" . $valref->{$key} . "\n"; if($table_pos =~ /contentpos|contentadrpos|users/){ if($key =~ /ct_name/){ $cptxt_where .= " and cp.$key ilike '$valref->{$key}'"; }elsif($key =~ /txt/){ $cptxt_where .= " and cp.$key ilike '%$valref->{$key}%'"; }elsif($key =~ /barcode|int|owner/ && (looks_like_number($valref->{$key}) || $valref->{$key} eq "null")){ $cptxt_where .= " and cp.$key $opref->{$key} $valref->{$key}"; } }else{ if($key eq "ct_name" && $valref->{$key} =~ /^(\d+)(0\d)$/){ $txt_where .= " and (ct.$key ilike '$valref->{$key}' OR ct.barcode $opref->{$key} $valref->{$key})"; }elsif($key eq "ct_name"){ $txt_where .= " and ct.$key ilike '$valref->{$key}'"; }elsif($key =~ /_id|barcode|int\d+|sort|owner/ && (looks_like_number($valref->{$key}) || $valref->{$key} =~ /null|0/)){ $txt_where .= " and ct.$key $opref->{$key} $valref->{$key}"; }elsif($key =~ /txt|uri/){ $txt_where .= " and ct.$key ilike '%$valref->{$key}%'"; }elsif($key eq "state"){ #searchs also order_state $txt_where .= " and (ct.state ilike '%$valref->{$key}%' OR ct.txt22 ilike '%$valref->{$key}%')"; }elsif($key =~ /byte/){ $txt_where .= " and ct.$key = '\\x$valref->{$key}'"; } #sum pos doesn't work anymore #if($key =~ /int01/ && $table eq "contenttrans" && looks_like_number($valref->{$key})){ #$cpgroup_where .= " group by cp.ct_id HAVING sum(cp.int02) $opref->{$key} $valref->{$key}"; #} } #if($key =~ /end_/ && $key =~ /time$/){ #$valref->{$key} .= " 23:59" if($valref->{$key} !~ /\d:\d/); #} if(!$v_journal){ if($table_pos =~ /contentpos|contentadrpos|users/ && $key =~ /mtime/ && $valref->{$key} =~ /\d+\.\d+\.\d+/){ $cptxt_where .= " and cp.mtime >= '$valref->{$key}'" if($key =~ /start/); $cptxt_where .= " and cp.mtime < '$valref->{$key}'" if($key =~ /end/); } elsif($table_pos =~ /contentpos|contentadrpos|users/ && $key eq "template_id_pos" && $valref->{$key}){ $cptxt_where .= " and cp.template_id = $valref->{$key}"; } elsif($key =~ /mtime/ && $valref->{$key} =~ /\d+\.\d+\.\d+/){ $txt_where .= " and ct.mtime >= '$valref->{$key}'" if($key =~ /start/); $txt_where .= " and ct.mtime < '$valref->{$key}'" if($key =~ /end/); } }elsif($v_journal){ if($key =~ /itime/ && $valref->{$key} =~ /\d+\.\d+\.\d+/){ $txt_where .= " and ct.itime >= '$valref->{$key}'" if($key =~ /start/); $txt_where .= " and ct.itime < '$valref->{$key}'" if($key =~ /end/); } if($key =~ /start_mtime/ && $valref->{$key} =~ /^\d+$/){ $txt_where .= " and ct.int11 = '$valref->{$key}'";#int11 = c_id-abschluss key }elsif($key =~ /start_mtime/ && $valref->{$key} =~ /date.*\d+\.\d+\.\d+/){ $txt_where .= " and ct.mtime >= $valref->{$key}"; }elsif($key =~ /start_mtime/ && $valref->{$key} =~ /\d+\.\d+\.\d+/){ $txt_where .= " and ct.mtime >= '$valref->{$key}'"; } if($key =~ /end_mtime/ && $valref->{$key} =~ /\d+\.\d+\.\d+/){ $txt_where .= " and ct.mtime < '$valref->{$key}'"; } } if($key =~ /start_pay_time/ && $valref->{$key} =~ /\d+\.\d+\.\d+/){ $txt_where .= " and ct.pay_time >= '$valref->{$key}'"; } if($key =~ /end_pay_time/ && $valref->{$key} =~ /\d+\.\d+\.\d+/){ $txt_where .= " and ct.pay_time < '$valref->{$key}'"; } if($key =~ /start_warn_time/ && $valref->{$key} =~ /\d+\.\d+\.\d+/){ $txt_where .= " and ct.warn_time >= '$valref->{$key}'"; } if($key =~ /end_warn_time/ && $valref->{$key} =~ /\d+\.\d+\.\d+/){ $txt_where .= " and ct.warn_time < '$valref->{$key}'"; } } }# if($v_journal =~ /Tagesbericht/){ $txt_where .= " and (ct.state ~ '[a-z]') and ct.int01 is not null and ct.close_time is null"; $txt_where .= " and ct.int14 is $opos" if($opos eq "null"); } $txt_where = " and ct.c_id IN ($ck4ex)" if($export =~ /check4export/); my $sth = ""; my $updown = "ASC"; $updown = "DESC" if($sort_updown eq "down"); if($v_journal =~ /_parts/){#collects ct_ids my $cp_scol = "ct_name"; $cp_scol = $1 if($scol =~ /(ct_name|barcode|mtime|txt0[1-9]|int0[1-9])/); $sth = $dbh->prepare("SELECT cp.* FROM contenttranspos cp WHERE cp.ct_id IN (SELECT ct.c_id FROM relation rel, contenttrans ct WHERE rel.content_id=ct.c_id and rel.main_id IN ($main_ids) and rel.template_id IN ($tplids) $txt_where) $cptxt_where ORDER BY cp.$cp_scol $updown"); }elsif($valref->{long_rent} || $valref->{start_date_time} =~ /^\d+\.\d+\.\d+/ || $valref->{end_date_time} =~ /^\d+\.\d+\.\d+/ || $cpgroup_where){ $sth = $dbh->prepare("SELECT * FROM relation rel, $table ct WHERE rel.content_id=ct.c_id and rel.main_id IN ($main_ids) and rel.template_id IN ($tplids) $txt_where and c_id IN (SELECT cp.ct_id from contenttranspos cp WHERE 1=1 $cptxt_where $cpgroup_where) ORDER BY $scol $updown LIMIT $limit OFFSET $offset"); }elsif($v_journal && $ct_ids){#and executes ct_ids $ct_ids = 0 if(!$ct_ids); $sth = $dbh->prepare("SELECT * FROM relation rel, $table ct WHERE rel.content_id=ct.c_id and rel.main_id IN ($main_ids) and rel.template_id IN ($tplids) and rel.content_id IN ($ct_ids) $txt_where ORDER BY $scol $updown LIMIT $limit OFFSET $offset"); }elsif($table_pos && $table_pos eq "contentpos"){ $sth = $dbh->prepare("SELECT cp.* FROM contentpos cp WHERE cp.cc_id IN (SELECT ct.c_id FROM relation rel, content ct WHERE rel.content_id=ct.c_id and rel.main_id IN ($main_ids) and rel.template_id IN ($tplids) $txt_where) $cptxt_where ORDER BY cp.$scol $updown LIMIT $limit OFFSET $offset"); }elsif($table_pos && $table_pos eq "contentadrpos"){ if($valref->{template_id_pos} eq 602){#because of user_minianswer have to be anonym $sth = $dbh->prepare("SELECT cp.* FROM contentadrpos cp WHERE 1=1 $cptxt_where ORDER BY cp.$scol $updown LIMIT $limit OFFSET $offset"); }else{ $sth = $dbh->prepare("SELECT ct.txt01,ct.txt08,cp.c_id,cp.mtime,cp.barcode,cp.int01,cp.txt02 FROM contentadr ct, contentadrpos cp WHERE ct.c_id=cp.ca_id $txt_where $cptxt_where ORDER BY cp.$scol $updown LIMIT $limit OFFSET $offset"); } }elsif($table_pos && $table_pos eq "users"){ $sth = $dbh->prepare("SELECT cp.* FROM contentadr ct, users cp WHERE ct.c_id=cp.u_id $txt_where $cptxt_where ORDER BY cp.$scol $updown LIMIT $limit OFFSET $offset"); }else{ $sth = $dbh->prepare("SELECT * FROM relation rel, $table ct WHERE rel.content_id=ct.c_id and rel.main_id IN ($main_ids) and rel.template_id IN ($tplids) $txt_where ORDER BY $scol $updown LIMIT $limit OFFSET $offset"); } my $rc = $sth->execute(); my $s_id = "c_id"; $s_id = "u_id" if($table_pos && $table_pos eq "users"); my $search = $sth->fetchall_hashref("$s_id"); return $search; } #search json for automcomplete sub search_json(){ my $self = shift; my $dbh = shift || $dbh_intern; my $table = shift; my $search = shift || ""; my $template_id = shift || ""; my $c_id = shift || 0; my $catch_equal = shift || 0; my $sel = "1=2"; my $sth = ""; my $rows = 0; if($search =~ /^\d+$/ && $table eq "content"){ if($catch_equal){ $sel = "(ct_name ilike '$search' OR CAST(barcode AS text) like '$search') and c_id != $c_id"; }else{ $sel = "(ct_name ilike '$search%' OR CAST(barcode AS text) like '$search%') and c_id != $c_id"; } $sth = $dbh->prepare("SELECT ct.ct_name || ' , ' || ct.barcode || ' , ' || ct.txt01 AS value, ct.ct_name AS spart_ct_name, ct.c_id FROM $table ct, relation rel WHERE ct.c_id=rel.content_id and rel.template_id IN ($template_id) and $sel"); my $rc = $sth->execute(); $rows = $sth->rows; }elsif($search =~ /\w{3}/ && $table eq "contentadr"){ my $sel = "txt01 ilike '%$search%'"; $sth = $dbh->prepare("SELECT ct.txt01 || ', ' || ct.c_id AS value, ct.txt01 AS vorname_name, ct.c_id FROM $table ct, relation rel WHERE ct.c_id=rel.content_id and rel.template_id=$template_id and $sel"); my $rc = $sth->execute(); $rows = $sth->rows; } return ($rows,$sth); } 1;