Reputation: 147
I'm beginner in Perl programming, and I want to learn about OOP in Perl. I develop a simple application about sql creator, but I have a problem. I think the problem is passing multiple parameters.
package SqlCreator;
use warnings;
use strict;
sub new {
my ($class, %args) = @_;
return bless \%args, $class;
}
sub editArray {
my (@array) = @_;
my $text = '';
my $arraySize = scalar @array;
for(my $i = 1; $i<$arraySize; $i++) {
$text .= "'" . $array[$i] . "'". ",";
}
my $length = length $text;
$text = substr($text, 0, $length-1);
return $text;
}
sub createInsertColumn {
my (@column ) = @_;
my $sql = '';
$sql .= ' (';
$sql .= editArray(@column);
$sql .= ')';
return $sql;
}
sub createInsertValue{
my (@value) = @_;
my $sql = '';
$sql .= ' VALUES (';
$sql .= editArray(@value);
$sql .= ')';
return $sql;
}
sub createInsertSql{
my ($table, @column, @value) = @_;
my $sql = 'INSERT INTO ' . $table;
$sql .= createInsertColumn(@column);
$sql .= createInsertValue(@value);
return $sql;
}
1;
use warnings;
use strict;
use SqlCreator;
my $object = SqlCreator->new;
my @column = ('name', 'gender', 'age');
my @value = ('Mehmed Fatih Temiz', 'male', 28);
my $sql = $object->createInsertSql('person', @column, @value);
print $sql;
This is my sample code. If you solve the problem, please help me.
Upvotes: 0
Views: 266
Reputation: 385655
You can't pass arrays to subs, only scalars. When you do
my $sql = $object->createInsertSql(
'person', @column, @value );
you are passing the following to the method:
$object, 'person', $column[0], $column[1], ..., $value[0], $value[1], ...
Inside the method, you have
my ( $table, @column, @value ) = @_;
First of all, you forgot to account for the invocant. There should be a leading $self
parameter.
Secondly, there's no way to know how many of the scalars to add to @column
and how many to add to @value
, so all but the first are added to @column
.
This means you were effectively doing the following:
my $table = $object;
my @column = ( 'person', $column[0], $column[1], ..., $value[0], $value[1], ... );
my @value = ();
If you want to pass an array, pass a reference to it instead.
my $sql = $object->createInsertSql( 'person', \@column, \@value );
The sub becomes
sub createInsertSql {
my ( $self, $table, $column, $value ) = @_;
my $sql = 'INSERT INTO '.$table; # XXX Injection bug
$sql .= createInsertColumn(@$column);
$sql .= createInsertValue(@$value);
return $sql;
}
By the way, your code is full of injection errors. You aren't properly converting text into SQL identifiers and SQL string literals.
Fixed:
package SqlCreator;
use warnings;
use strict;
sub new {
my ( $class, %args ) = @_;
return bless \%args, $class;
}
sub createInsertSql{
my ( $self, $table, $cols, $vals ) = @_;
my $dbh = $self->{dbh};
return sprintf(
'INSERT INTO %s ( %s ) VALUES ( %s )'
$dbh->quote_identifier($table),
( join ', ', map { $dbh->quote_identifier($_) } @$cols ),
( join ', ', map { $dbh->quote($_) } @$vals ),
);
}
1;
use warnings;
use strict;
use DBI qw( );
use SqlCreator qw( );
my $dbh = DBI->connect(...);
my $sql_creator = SqlCreator->new( dbh => $dbh );
my @cols = ( 'name', 'gender', 'age' );
my @vals = ( 'Mehmed Fatih Temiz', 'male', 28 );
my $sql = $sql_creator->createInsertSql( 'person' , \@cols , \@vals );
print "$sql\n";
Upvotes: 7