Beefy Boxes and Bandwidth Generously Provided by pair Networks
Problems? Is your data what you think it is?
 
PerlMonks  

Counting rows Sqlite

by fanticla (Scribe)
on May 08, 2010 at 21:16 UTC ( [id://839063]=perlquestion: print w/replies, xml ) Need Help??

fanticla has asked for the wisdom of the Perl Monks concerning the following question:

Hi Monks,

maybe it's a very stupid question, but I can't count the rows of a query with Sqlite:

$all = $dbh->selectall_arrayref("SELECT ID, col1, col2 FROM table + WHERE col1 = 'xxx'"); print "Number of rows selected: $all ";

Any idea what I am doing wrong?

Thanks, Cla

Replies are listed 'Best First'.
Re: Counting rows Sqlite
by ikegami (Patriarch) on May 08, 2010 at 22:01 UTC
    selectall_arrayref returns a reference to an array of rows.
    my $all = $dbh->selectall_arrayref(" SELECT ID, col1, col2 FROM table WHERE col1 = 'xxx' "); print "Number of rows selected: ", 0+@$all, "\n";
    or if you don't actually need the rows:
    my ($count) = $dbh->selectrow_array(" SELECT COUNT(*) FROM table WHERE col1 = 'xxx' "); print "Number of rows selected: $count\n";
Re: Counting rows Sqlite
by CountZero (Bishop) on May 09, 2010 at 07:00 UTC
    Why let Perl do all the work, when SQL can do it?
    $count = $dbh->selectrow_array('SELECT count(ID) FROM table WHERE col1 + = ?', \%attr, 'xxx'); print "Number of rows selected: $count ";

    CountZero

    A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James

Re: Counting rows Sqlite
by toolic (Bishop) on May 08, 2010 at 22:02 UTC
    Judging by its name, I would guess that selectall_arrayref returns a reference to an array. If that is what the documentation says, then you should be able to dereference the array to get a count of its elements:
    print "Number of rows selected: ", scalar @{$all};
    See also: References quick reference
Re: Counting rows Sqlite
by afoken (Chancellor) on May 09, 2010 at 05:03 UTC

    You have a second problem: You don't use placeholders. That usually means that you are vulnerable to SQL injection, and you prevent any caching of prepared statements.

    Always use placeholders, even if the underlying database does not support placeholders. Placeholders are part of the DBI specification, so you can use them with ANY database and pseudo-database supported by DBI. Each database driver (DBD::Whatever) must support placeholders, and together with the DBI, it will take care of proper quoting if needed. Since most database support parameters, there is no need for quoting or modification of the SQL statement, the values are simply passed through a different part of the communication channel to the database, and so the database can optimize and cache much better than with inline values.

    I would prefer that DBI issued a warning or even refuse to work with inline values, but that would add a lot of overhead, as DBI would need to actually parse the SQL statement.

    Alexander

    --
    Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)
      I would prefer that DBI issued a warning or even refuse to work with inline values, but that would add a lot of overhead, as DBI would need to actually parse the SQL statement.

      Worse than that, it would simply be impossible to do.

      On receiving the query "SELECT * FROM foo WHERE bar = 'baz'", how would DBI know whether it had been called as $dbh->selectall_arrayref("SELECT * FROM foo WHERE bar = 'baz'"); (which is fine - the baz is a hard-coded literal) or as $dbh->selectall_arrayref("SELECT * FROM foo WHERE bar = '$myvar'"); (which is potentially dangerous)? Even if it could make that determination, in the latter case, how would it know whether $myvar's value came from user input (unsafe) or the statement my $myvar = 'baz'; (another hard-coded literal, so safe)?

      We've already got taint mode and you can set DBI to reject tainted values (DBI->connect(..., { TaintIn => 1 })), but that's about as close as you're likely to be able to get.

        Note that the SQL statement would be tainted as soon as you interpolate tainted variables into it.

        Tainting would also have been my answer to the problem of mixing untrusted user input with SQL fragments.

        For constants (your "hard-coded literals"), I really don't care. I've used DBI nearly daily in the last few years, and I rarely needed constants. And for the few cases where I really had constants, I replaced them with placeholders and a constant bind value just because I have the habit to pass all values using placeholders. So having DBI warn or die when it finds a string or number literal in an SQL statement would not hurt much, it would just force you to pass even constants via placeholders. Of course, this "paranoia mode" would break some existing code, and it needs to be disabled by default for a long time. Any by the way: Because no user code needs the $dbh->quote() method in "paranoia mode", DBI should warn or die when non-DBD code calls this method.

        I see a different problem that really blocks the implementation of this "paranoia mode": The different SQL dialects. For example, it is possible and sometimes needed to create PL/SQL code via DBI/DBD::Oracle, and that code may legally contain any hard-coded literal. So the actual parsing has to be done in the DBD code, at least for those special cases. DBI code may provide a default parser, for DBDs that don't have those special cases.

        Alexander

        --
        Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://839063]
Approved by toolic
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others examining the Monastery: (4)
As of 2024-04-25 23:57 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found