Beefy Boxes and Bandwidth Generously Provided by pair Networks
Your skill will accomplish
what the force of many cannot
 
PerlMonks  

pp concatenate path

by IB2017 (Pilgrim)
on Apr 20, 2018 at 20:44 UTC ( [id://1213280]=perlquestion: print w/replies, xml ) Need Help??

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

Windows 10, Strawberryperl 5.16.3, pp

If I pack the following two scripts with pp, the first work, the second not (Can't connect to data source 'DBI:SQLite:\C:\Users\DON\Desktop\data.db' because I can't work out what driver to use (it doesn't seem to contain a 'dbi:driver:' prefix and the DBI_DRIVER env var is not set) at script/myscript.pl). In the first, the database path is hard encoded, in the second it is read by a configuration file (in the example a simple text file). Note that both works nicely from command line

use warnings; use strict; use DBI; use DBD::SQLite; my $Path='C:\Users\DON\Desktop\data.db'; my $dsn = "DBI:SQLite:" . $Path; print "Connecting $dsn ... \n"; my %attr = (RaiseError => 1, sqlite_unicode => 1, AutoCommit = +> 1); my $dbh = DBI->connect($dsn, "", "", \%attr) || die $DBI::errs +tr; print "done!\n";

And here the second script, reading the same $Path value from file

use warnings; use strict; use DBI; use DBD::SQLite; my $Path; print "Reading configuration file...\n"; my $FileInput="config.txt";#simple txt file containing this: C +:\Users\DON\Desktop\data.db open my $FH, "<:encoding(UTF-8)", $FileInput; while (my $line = <$FH>) { $Path = $line; } my $dsn = "DBI:SQLite:" . $Path; print "Connecting $dsn ... \n"; my %attr = (RaiseError => 1, sqlite_unicode => 1, AutoCommit = +> 1); my $dbh = DBI->connect($dsn, "", "", \%attr) || die $DBI::errs +tr; print "done!\n";

What is wrong in the second script that pp doesn't like?

Replies are listed 'Best First'.
Re: pp concatenate path -- DBI datasource
by Discipulus (Canon) on Apr 20, 2018 at 21:33 UTC
    Hello, no time to investigate further right now but..

    $Path can be different across the two version if the file end with a newline (but yoou say that's ok from command line so..) About this you can replace the loop with my $Path = <$fh>; chomp $Path

    Have you tried also C:/Users/DON/Desktop/data.db ?

    Anyway the driver part seems to be merged into the path for the db location: the error is for the driver missing.

    Have you tried the standard way to connect: my $dbh = DBI->connect("dbi:SQLite:dbname=$dbfile","",""); too? Here the path is a named parameter dbname

    You can also workaround (and again does not explain why the packed version fails..) setting both env vars:

    $ENV{DBI_DSN} = 'C:/Users/DON/Desktop/data.db' ; $ENV{DBI_DSNDRIVER} = 'dbi:SQLite'; my $dbh = DBI->connect();

    L*

    There are no rules, there are no thumbs..
    Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.
Re: pp concatenate path
by kcott (Archbishop) on Apr 21, 2018 at 10:11 UTC

    This looks remarkably similar to a problem I fixed in legacy code at work in the last week or two.

    The issue occurs somewhere in the code behind DBI->connect($dsn, ... (which I didn't delve into to any great depth). The problem relates to the backslashes in the MSWin path which, somewhere in the DBI code, get interpreted as escapes.

    In your first script, you use a literal for the path; in your second script, you don't. Consider:

    $ cat > fred $x = 'one_dir\two_dir'; $y = "one_dir\two_dir"; $ perl -MO=Deparse fred $x = 'one_dir\\two_dir'; $y = "one_dir\two_dir"; fred syntax OK

    $x has the "\t" part escaped (i.e. "...\\t..."); but $y does not and is actually "one_dir<TAB>wo_dir".

    The fix I implemented used quotemeta. I notice throughout this thread that you tried different versions of the DSN string; I suspect something like this might suffice for your needs:

    my $dsn = "dbi:SQLite:\Q$path";

    — Ken

      The fix I implemented used quotemeta. I suspect something like this might suffice for your needs: my $dsn = "dbi:SQLite:\Q$path";

      Did you try it? Because it makes no difference, it simply can't

      The problem relates to the backslashes in the MSWin path which, somewhere in the DBI code, get interpreted as escapes.

      No. DBI project doesn't have that problem. It would be extremely serious case of stupid.

      DBI::Shell on the other hand does use eval stupidly, but it hasn't been touched in 10 years, has https://rt.cpan.org/Public/Dist/Display.html?Name=DBI-Shell}19 open tickets... and is not part of DBI project.

      I didn't delve into to any great depth

      Does that make you a troll?

Re: pp concatenate path
by LanX (Saint) on Apr 20, 2018 at 21:52 UTC

      Lanx: Maybe you should check for errors from open?

      How would checking for errors from open change the error message from DBI which includes an apparent filepath?

Re: Can't connect to data source 'DBI:SQLite:\C:\Users\DON\Desktop\data.db
by Anonymous Monk on Apr 20, 2018 at 21:35 UTC

    Hi,

    Use forward slashes for filename? Esp on windows

    'DBI:SQLite:C:/Users/DON/Desktop/data.db

    I doubt your non-par version works at all

    If does works as you say, it probably doesn't do what you think it does, it probably opens an ADStream and not the filename you wanted.

    For \C:\Users\DON\Desktop\data.db

    The filename is "\C"

    and the stream is " users" ... but I've never seem a stream with slashes so that would fail also

      Thank you monks. I have tried any possible solution (cleaning the path for Windows, setting ENV etc.), but NO solution works in the packed versions (pp). And I really do not understand why! Here is a better script that reproduces the problem (the first part works, the second no).

      use warnings; use strict; use DBI; use DBD::SQLite; #Working part with hard coded path my $dbfile1="C:/users/DON/Desktop/data.db"; print "\nFIRST Connection to dbfile path read from script ($dbfile1) . +.. "; my $dbh = DBI->connect("dbi:SQLite:dbname=$dbfile1","","") || die $DBI +::errstr; print "done!\n\n"; #NOT working part with path from file my $dbfile2; print "Reading dbfile path from configuration file... "; my $FileInput="config.txt";#simple txt file containing this: C:/users/ +DON/Desktop/data.db open my $FH, "<:encoding(UTF-8)", $FileInput || die (print "can't open + file $dbfile2"); while (my $line = <$FH>) { $dbfile2 = $line; chomp $dbfile2; } print "$dbfile2\n"; print "SECOND Connection with dbfile read from file $dbfile2 ... "; $dbh = DBI->connect("dbi:SQLite:dbname=$dbfile2","","")|| die $DBI::er +rstr; print "done!\n";

      Again, from the command line the script works correctly. The by pp compiled version behaves like this:

      FIRST Connection to dbfile path read from script (C:/users/DON/Desktop +/data.db) ... done! Reading dbfile path from configuration file... C:/users/DON/Desktop/da +ta.db Can't connect to data source 'dbi:SQLite:dbname=C:/users/DON/Desktop/d +ata.db' because I can't work out what driver to use (it doesn't seem +to contain a 'dbi:driver:' prefix and the DBI_DRIVER env var is not s +et) at script/myscript.pl line 22. SECOND Connection with dbfile read from file C:/users/DON/Desktop/data +.db ...
      I

      I've been stuck for days on this problem. So any help is very much appreciated

        Besides noticing that open my $FH, "<:encoding(UTF-8)", $FileInput || die (print "can't open file $dbfile2"); should probably be open my $FH, "<:encoding(UTF-8)", $FileInput || die (print "can't open file $FileInput");

        i wonder what adding

        if ($dbfile1 eq $dbfile2){ print "same\n";} else {print "different\n";}
        would output. seeing "<:encoding(UTF-8)" makes me wonder even more as dbfile2 will be marked as UTF characters rather than bytes

        Edit: and that means the first parm to the second connect will be marked as UTF as well to doesnt it? Maybe you should try creating both "dbi:SQLite:dbname=$..." strings outside the connect call and compare them as well.

        I've been stuck for days on this problem. So any help is very much appreciated

        What is your  perl -V ?

        First line from  pp --version ?

        You par packer command line  pp .... ?

        Additional output if you add  DBI->trace(1); ?

        DBI/DBD::SQLite version?

        I cannot reproduce this error on v5.16.1 with PAR Packager, version 1.036 (PAR version 1.015) and DBI 1.636 DBD::SQLite 1.48 and old windows

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others cooling their heels in the Monastery: (3)
As of 2024-04-20 14:10 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found