Beefy Boxes and Bandwidth Generously Provided by pair Networks
Just another Perl shrine
 
PerlMonks  

DBI converting hex values

by Sprad (Hermit)
on Nov 02, 2006 at 17:15 UTC ( [id://581926]=perlquestion: print w/replies, xml ) Need Help??

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

I'm using DBI with the ODBC driver. In my DB, I have some hex values. I'd dearly like to leave them as hex values. Unfortunately, when I extract them, DBI assumes they're some sort of binary data and converts them to text.

For example, the hex string "0x5061756c" becomes the ASCII string "Paul". This is a documented feature of DBI, so the fact that it's doing this doesn't surprise me. What I'm wondering, though, is can I turn it off? I'd rather get the hex string as a literal "0x" followed by the literal hex digits.

---
A fair fight is a sign of poor planning.

Replies are listed 'Best First'.
Re: DBI converting hex values
by VSarkiss (Monsignor) on Nov 02, 2006 at 18:22 UTC

    This really boils down to two questions: what data type is the column in your database, and what are you doing to "view" it?

    Your comment leads me to believe you've got an integer or some numeric type. The internal representation, including the number base, is usually invisible to the application. So whether the column contains hex, decimal, octal, or whatever base, is up to the interpretation of the application program.

    In other words, what may be more relevant is how you choose to display the value. Are you doing a print? It may be as simple as switching to printf "0x%x" to see the hex representation. See printf for details.

    Of course, this is all guesswork until you clarify the first two questions.

      In this particular case, the data type is a custom type derived from Binary. But my code doesn't know that, it gets queries passed in from outside. My code runs them (managing all the DB connection details) and passes back the results.

      As for how I'm seeing the value, I'm using Data::Dumper and print statements. I could convert it back to a string representation of the hex value, but only if I can know which fields got changed in this way. Since the SQL code could be pretty much anything, I'm not sure if this is possible.

      I'd like to push this burden off to the calling scripts, since they know what their SQL is. But my intermediate layer previously used another DB module (Sybase::CTLib), which returned the hex values in the way I want. I've got to make my layer behave the same way, or I'll break all the other scripts.

      ---
      A fair fight is a sign of poor planning.

        OK, now we're getting somewhere. :-)

        So the underlying database is Sybase, and you used to use Sybase::CTLib to handle some VARBINARY-ish type. If so, and if you have the option, the easiest choice may be to switch to DBD::Sybase instead of DBD::ODBC. Then a lot of the behavior should be as you expect. (The last time I used Sybase was about five years ago, so things may have changed.)

        I think I understand your problem: you know how to format the columns as string or hex, you just don't know which ones should be formatted in each way. If that's the case, then you may want to look at the TYPE attribute of the statement handle (documented in DBI, usually used along with the type_info method), which will allow you to find the underlying type of each result column. It sounds like that may give you enough information to decide how to format each column. Something like this (cheesy, untested) example:

        my $type_i_want = $dbh->type_info( [ SQL_whatever ] ); # # ...later... # $sth->execute(@parameters); my @types = $sth->{TYPE}; my $row = $sth->fetch(); for (my $i = 0; $i < $sth->{NUM_OF_FIELDS}; $i++) { if ($types[$i] eq $type_i_want) { printf "0x%x", $row[$i]; } else { printf "%s", $row[$i]; } }

        Hope that gets you closer.

        There may be a way to get the underlying DBD layer to treat it as binary data using bind_col or bind_param (I can't remember which is for which direction; I think you want the former).

Re: DBI converting hex values
by samtregar (Abbot) on Nov 02, 2006 at 18:35 UTC
    If you can't convince DBI to leave your hex value alone you can always convert it back:

    $a = "Paul"; $a =~ s!(.)!sprintf("%02x", ord($1))!eg; print "0x$a";

    I'm sure there's a more clever way to do that with unpack, but I'm way too lazy to figure it out!

    -sam

      From Saints in our Book: "..and remember there are a lot of things monks are supposed to be but lazy is not one of them" :-)
      perl -le ' print "0x",unpack "H*",pack "A*","Paul"' 0x5061756c

      --shmem

      _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                    /\_¯/(q    /
      ----------------------------  \__(m.====·.(_("always off the crowd"))."·
      ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}

        You might want to be more lazy and skip the pack "A*". (:

        - tye        

      The problem, though, is that this DBI call is part of a larger module that encapsulates DB access for some tools. It's another layer on top of DBI. My layer doesn't know which items were formerly hex and which were strings all along, so I can't blindly convert.

      I could convert, though, if there were a way to know what data I was getting back. That might be another way to tackle the problem, but I'm not sure how to do that either. All I've done so far is just hand back the result array, which works great for everything except these fields.

      ---
      A fair fight is a sign of poor planning.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others browsing the Monastery: (5)
As of 2024-03-29 08:41 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found