0

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.

1 Answer 1

7

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";
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.