Beefy Boxes and Bandwidth Generously Provided by pair Networks
No such thing as a small change
 
PerlMonks  

Can't I chop the lvalue of join?

by DapperDan (Pilgrim)
on Sep 28, 2002 at 14:14 UTC ( [id://201441]=perlquestion: print w/replies, xml ) Need Help??

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

This code is supposed to do a SQL insert using the contents of the hash %$c.

In the values section of the SQL statement, I need a string of the form "?,?,?" where there is a ? for each field, and all the ?s are delimited by commas. However, there can not be a trailing comma at the end or syntax errors in the database (PostgreSQL) result.

I tried

my $sth = $dbh->prepare( 'INSERT INTO table(' . join(',', keys %$c) . ") VALUES (" . chop(join('', map {'?,'} keys %$c)) . ")" );

I managed to make the code work by taking it out and explicitly assigning the value of the expression to a scalar, $placeholderstr. I would like to inline the rvalue of the first line of this code in the $dbh->prepare() statement. Any ideas?

code:

my $placeholderstr = join('', map {'?,'} keys %$c); chop $placeholderstr; my $sth = $dbh->prepare( 'INSERT INTO table(' . join(',', keys %$c) . ") VALUES ($placeholderstr)" ); $sth->execute(values %$c) or die $dbh->errstr;

Replies are listed 'Best First'.
Re: Can't I chop the lvalue of join?
by japhy (Canon) on Sep 28, 2002 at 14:19 UTC
    Can I ask why you're using join(',', keys %$c) in your code, but you're not using join(',', map '?', keys %$c)?

    Anyway, since chop() modifies its argument, it must be a variable. But do what I said above.

    _____________________________________________________
    Jeff[japhy]Pinyan: Perl, regex, and perl hacker, who'd like a job (NYC-area)
    s++=END;++y(;-P)}y js++=;shajsj<++y(p-q)}?print:??;

      I hadn't used join with an in-lined map before. You're right, it's so damned obvious given the way i used join with keys, but I just couldn't see that until it was pointed out to me.

      Thanks a lot japhy.

      PS: not that it really matters any more, but is there a reason *why* chop only works on a variable rather than any scalar lvalue?

        It does work on lvalues. But the return value of join() is not an lvalue. You can't assign to it. join('x', qw( a b c )) = "foo"; is a syntax error, whereas substr($x, 2, 4) = "ouch"; is not, so you can say chop(substr($x, 2, 4)).

        _____________________________________________________
        Jeff[japhy]Pinyan: Perl, regex, and perl hacker, who'd like a job (NYC-area)
        s++=END;++y(;-P)}y js++=;shajsj<++y(p-q)}?print:??;

Re: Can't I chop the lvalue of join?
by broquaint (Abbot) on Sep 28, 2002 at 14:29 UTC
    Here's another way of building up your query string
    my $c = { qw/a bunch of values in a hash here/ }; my @fields = keys %$c; print 'INSERT INTO table(' . join(',', @fields) . ') VALUES (?' . ',?' x $#fields . ')'; __output__ INSERT INTO table(of,a,hash,in) VALUES (?,?,?,?)

    HTH

    _________
    broquaint

Re: Can't I chop the lvalue of join?
by Aristotle (Chancellor) on Sep 28, 2002 at 18:23 UTC
    This is very close to broquaint's, but a bit more orthogonal:
    print 'INSERT INTO table(' . join(',', @fields) . ') VALUES (' . join(',', ('?') x @fields) . ')';
    However that's too many parens and single quotes to grok for my taste. Here's what I'd do:
    { local $" = ','; print "INSERT INTO table(@fields) VALUES (@{[ map '?', @fields]})" +; }
    Update: or of course, even better
    { local $" = ','; print "INSERT INTO table(@fields) VALUES (@{[('?') x @fields]})"; }
    Update 2002 09 30: it has to be $" of course, not $, -- doh.

    Makeshifts last the longest.

Re: Can't I chop the lvalue of join?
by chromatic (Archbishop) on Sep 28, 2002 at 16:26 UTC

    You also probably don't want to concatenate the return value of chop.

Re: Can't I chop the lvalue of join?
by bart (Canon) on Sep 29, 2002 at 11:45 UTC
    In the values section of the SQL statement, I need a string of the form "?,?,?" where there is a ? for each field, and all the ?s are delimited by commas.
    Just do
    join ',', map "?", keys %$c
    or
    join ',', ("?") x keys %$c
    (preferably the latter.)

    And no, you can't chop the result of join directly, though your code (at least, the first two lines) works fine, as does this slightly more compacted version:

    chop(my $placeholderstr = join '', map {'?,'} keys %$c);
    Your immediate problem must lie elsewhere.

    p.s. A combination of your and my ideas resulted in

    chop(my $placeholderstr = '?,' x keys %$c);
    and it works just fine.

Log In?
Username:
Password:

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

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

    No recent polls found