2

I am trying to write a custom report in Spiceworks, which uses SQLite queries. This report will fetch me hard drive serial numbers that are unfortunately stored in a few different ways depending on what version of Windows and WMI were on the machine.

Three common examples (which are enough to get to the actual question) are as follows:

Actual serial number: 5VG95AZF
Hexadecimal string with leading spaces: 2020202057202d44585730354341543934383433
Hexadecimal string with leading zeroes: 3030303030303030313131343330423137454342

The two hex strings are further complicated in that even after they are converted to ASCII representation, each pair of numbers are actually backwards. Here is an example:

3030303030303030313131343330423137454342 evaluates to 00000000111430B17ECB

However, the actual serial number on that hard drive is 1141031BE7BC, without leading zeroes and with the bytes swapped around. According to other questions and answers I have read on this site, this has to do with the "endianness" of the data.

My temporary query so far looks something like this (shortened to only the pertinent section):

SELECT  pd.model as HDModel,
  CASE
     WHEN pd.serial like "30303030%" THEN
         cast(('X''' || pd.serial || '''') as TEXT)
     WHEN pd.serial like "202020%" THEN
         LTRIM(X'2020202057202d44585730354341543934383433')
  ELSE
     pd.serial
  END  as HDSerial

The result of that query is something like this:

HDModel             HDSerial
-----------------   -------------------------------------------
Normal Serial       5VG95AZF
202020% test case   W -DXW05CAT94843
303030% test case   X'3030303030303030313131343330423137454342'

This shows that the X'....' notation style does convert into the correct (but backwards) result of W -DXW05CAT94843 when given a fully literal number (the 202020% line). However, I need to find a way to do the same thing to the actual data in the column, pd.serial, and I can't find a way.

My initial thought was that if I could build a string representation of the X'...' notation, then perhaps cast() would evaluate it. But as you can see, that just ends up spitting out X'3030303030303030313131343330423137454342' instead of the expected 00000000111430B17ECB. This means the concatenation is working correctly, but I can't find a way to evaluate it as hex the same was as in the manual test case.

I have been googling all morning to see if there is just some syntax I am missing, but the closest I have come is this concatenation using the || operator.

EDIT: Ultimately I just want to be able to have a simple case statement in my query like this:

SELECT  pd.model as HDModel,
  CASE
     WHEN pd.serial like "30303030%" THEN
         LTRIM(X'pd.serial')
     WHEN pd.serial like "202020%" THEN
         LTRIM(X'pd.serial')
  ELSE
     pd.serial
  END  as HDSerial

But because pd.serial gets wrapped in single quotes, it is taken as a literal string instead of taken as the data contained in that column. My hope was/is that there is just a character or operator I need to specify, like X'$pd.serial' or something.

END EDIT

If I can get past this first hurdle, my next task will be to try and remove the leading zeroes (the way LTRIM eats the leading spaces) and reverse the bytes, but to be honest, I would be content even if that part isn't possible because it wouldn't be hard to post-process this report in Excel to do that.

If anyone can point me in the right direction I would greatly appreciate it! It would obviously be much easier if I was using PHP or something else to do this processing, but because I am trying to have it be an embedded report in Spiceworks, I have to do this all in a single SQLite query.

Curtis
  • 101,612
  • 66
  • 270
  • 352
Jim Sanders
  • 521
  • 1
  • 4
  • 10
  • It must be getting late, but can you simplify, or perhaps just re-ask the question at the end just as a synthesis of everything that comes before? I'm saying this because I don't understand what you are asking exactly. –  Apr 18 '12 at 16:34
  • Well, what I want to do is be able to put X'pd.serial' and have it understand what I am trying to do. Unfortunately, because pd.serial (the column with the data) is wrapped in single quotes, the query treats it as a literal string. Does that help at all clarify? – Jim Sanders Apr 18 '12 at 16:40

1 Answers1

0

X'...' is a BLOB literal expression in sqlite. If the values are string, you can just use them as such.

This should be a start:

sqlite> select X'3030303030303030313131343330423137454342';
00000000111430B17ECB
sqlite> select ltrim(X'3030303030303030313131343330423137454342','0');
111430B17ECB

I hope this puts you on the right path.

qris
  • 7,900
  • 3
  • 44
  • 47
  • Right, I have been doing that manually as you show, and that converts the data the way I want. (nice tip on getting rid of the leading zeroes, btw!) But I have 300+ entries in my table and I need do get the binary representation for each of them and output the results. – Jim Sanders Apr 18 '12 at 17:23