I want to make a query to a sqlite database and return an array of objects.
I'm creating a telegram bot and i have to store the date of last message per user_id, because telegram API returns messages i've already read. So i've created a sqlite db with two tables: users and messages; users contains all the user_id and username; messages contains the last message_id i've read.
I've done this function, it works but it isn't performing very well because it has to recreate the entire array of objects (fetchrow_hashref).
sub sqlLiteSelect {
my ($db,$table,$columnsRef,$where,$others) = @_;
my $columns = join(', ', @{ $columnsRef });
$others ||= '';
my $query = "select ${columns} from ${table} ${where}${others}";
my $obj = $db->prepare($query);
my $ret = $obj->execute() or die $DBI::errstr;
my @array = ();
while(my $row = $obj->fetchrow_hashref) {
my $tmp = {};
foreach my $column (@{ $columnsRef }) {
$tmp->{$column} = $row->{$column};
}
push @array, $tmp;
}
return @array;
}
my @columns = ('user_id','first_name','username','type');
my $where = ' where user_id in (1,2)';
my @result = sqlLiteSelect($db,'users',\@columns,$where,'');
foreach my $row (@result) {
print "user_id=$row->{user_id}, username=$row->{username}\n";
}
I expect my select to return an array of object without recreate it everytime.
$tmpinstead of directly pushing$row?push @array, $row;isn't clear enough?executereturn fetchall_arrayref({})... that will produce the entire list as nice hashrefs, exactly as you have now, but let smart DBI do all the annoying work for youprepare,execute,bind_columns(\$user_id, \$first_name, \$username, \$type)and then straight dowhile ($sth->fetch) { print "$user_id $username\n }forget about the entire subroutine that did create the entire list first