MSSQL ODBC refusing valid TINYINT values (Numeric value out of range) - c++

I'm trying to insert into a TINYINT column which according to MSDN docs should take numbers between 0-255. Unfortunately it only takes 0-127. If I try to insert 128 or higher it complains:
[22003] (native 0): [Microsoft][ODBC Driver 11 for SQL Server]Numeric value out of range
The data is bound as SQL_C_SBIGINT because it's a general code meant to take all integers, but I think that that shouldn't matter because for numbers 0-127 it works correctly. There's also an option to send it as a SQL_C_CHAR string, but that returns the same error.
Anyone knows where the problem might lie?

So, the problem was actually happening because as part of a test, I was "selecting" the inserted data back using SQLFetch() and SQLGetData(), and as target datatype used for the SQLGetData() function, I used SQL_C_STINYINT aka the signed version. Therefore the problem didn't happen when inserting the data but when I tried to "select" them back.

The answer is actually already given, but not highlighted.
TINYINT is a one-byte signed integer. All values from Hex 00 to Hex 7F (or Bin 0000 0000 to 0111 1111, or Dec 0 to 127) are positive; all values from Hex 80 to Hex FF (or Bin 1000 0000 to 1111 1111 or Dec 128 to 255) are negative.
I'm afraid that for any signed integer greater than 127, you'll have to use a two-byte integer, SMALLINT.
And SMALLINT is supported by many more database platforms than TINYINT would be.
If you really want a single-byte integer, you'll have to cast your 64bit integer to unsigned char in C++, and put it into an unsigned char host variable.
But then you'll only see the "correct" value, if it's above 127, in your front end, and SELECT-ing from the database using any other tool, you'll see garbage.
Good luck -
Marco the Sane

Related

Incorrect CRC32 output unless input bytes are equal

I need to reproduce the output of a hardware CRC calculator for testing purposes. It is set up for ethernet CRC 32, in trace32 format:
/CRC 32. 0x04C11DB7 1 1 0FFFFFFFF 0FFFFFFFF (checksum width, polynom, input reflection, output reflection, crc init, final XOR)
If I feed it values where the 4 bytes are equal (e.g 0x12121212 as each byte being 0x12), the output will match what I calculate using CRC32 or python.
However if I feed it any value where the 4 bytes are not equal, the results are off. For example 0x12341234 will return 0x093c454b (should be 0xa1768922).
Or 0x12345678 will return 0xAF6D87D2 (should be 0x4a090e98).
In the HW I can only select the init value and the polynomial, beyond feeding it 4 bytes to calculate. Rolling calculations(multiple words worth) behave the same way, the output is correct as long as each word fed to it has all bytes the same. Anything else, the output is off.
I am not too knowledgeable about CRC32 and has run out of ideas. Any pointers would be appreciated, what am I doing wrong here? I have double checked the polynomial, but if that was wrong, I could only get the right results extremely rarely, right?
Thank you!
You get your "should be" with the correct byte order. You get your "will return" by reversing the bytes. The bytes 12 34 56 78 gives, for the CRC you described, 0x4a090e98. The bytes 78 56 34 12 gives the CRC 0xaf6d87d2.
Your question is very vague, with no code or how it is being used. I can only guess that you are giving your CRC routine a 32-bit value instead of bytes, and it is being processed in little-endian order when you are expecting big-endian order.

Outputting Huffman codes to file

I have a program that reads a file and saves the frequency of each character. It then constructs a huffman tree based on each character's frequency and then outputs to a file the huffman codes for the tree.
So an input like "Hello World" would output this sequence to a file:
01010101 0010 010 010 01010 0101010 000 01010 00101 010 0001
This makes sense because the most frequent characters have the shortest codes. The issue is, this increases the file size ten-fold. I realized the reason why is because each 1 and 0 is being represented in memory as its own character, so they get each get expanded out to a byte of data.
I was thinking what I could do is convert each code (E.G. "010") to a character and save that to file - but that still would pad the code to be a byte long (Or mess it up if the code is longer than a byte).
How do I go about this? I can give code snippets if needed - I'm basically saving each code into a string so that's why the file's coming out so big (It's outputting each "bit" as a byte). If I were to convert the code to a long for example, then a code like 00010 would be represented as 2 and a code like 010 would also be represented as 2.
You basically have to do it a byte (or a word) at a time. Maintain a byte which you fill with bits, and a record of how many bits have been filled in so far. When you get to 8, write the byte and start over with an empty one.

Store 32 bit value as C string in most efficient form

I am trying to find the most efficient way to encode 32 bit hashed string values into text strings for transmission/logging in low bandwidth environments. Complex compression can't be used because the hash values need to be contained in human readable text strings when logged and sent between client and host.
Consider the following contrived examples:
given the key/value map
table[0xFE12ABCD] = "models/texture/red.bmp";
table[0x3EF088AD] = "textures/diagnostics/pink.jpg";
and the string formats:
"Loaded asset (0x%08x)"
"Replaced (0x%08x) with (0x%08x)"
they could be printed as:
"Loaded asset models/texture/red.bmp"
"Replaced models/texture/red.bmp with textures/diagnostics/pink.jpg"
Or if the key/value map is known by the client and server:
"Loaded asset (0xFE12ABCD)"
"Replaced (0xFE12ABCD) with (0x3EF088AD)"
The receiver can then scan for the (0xNNNNNNNN) pattern and expand it locally.
This is what I am doing right now but I would like to find a way to represent the 32 bit value more efficiently. A simple step would be to use a better identifying token:
"Loaded asset $FE12ABCD"
"Replaced $1000DEEE with $3EF088AD"
Which already reduces the length of each token - $ is not used anywhere else so it is reasonable.
However, what other options are there to make that 32 bit value even smaller? I can't use an index - it has to be a full 32 bit value because in some cases the generator of the string has the hash and sometimes it has a string it will hash immediately.
A common solution is to use Base-85 coding. You can code four bytes into five Base-85 digits, since 855 > 232. Pick 85 printable characters and assign them to the digit values 0..84. Then do base conversion to go either way. Since there are 94 printable characters in ASCII, it is usually easy to find 85 that are "safe" in whatever constrains your strings to be "readable".

Subtracting Numbers larger than 18 digits in length

Ok this is a tough one or else a stupid one but it has me stumped. I am working with serial numbers in MSSQL and they are stored in the database as nvarchar(50) and to do subtracting calculations on them I use the following query to convert them to the data-type BIGINT and subtract as normal.
SELECT
SUM(
CAST(second_Serial_Nb AS BIGINT)-CAST(Serial_Nb AS BIGINT))
FROM [TEST].[dbo].[Serial_Table]
WHERE ID = '3'
this query works fine for serial numbers up to 18 digits in length, but as soon as I increase there size of the serial numbers to 20 digits in length I get the error that the numbers can not be converted to data-type bigint
Msg 8815, Level 16, State 2, Line 2
Arithmetic overflow error converting expression to data type bigint
Is there a work around using a different number data type like hexi or something. I am also using C++ maybe I could create a function there instead of SQL?
Any comments or suggestions greatly appreciated, Thanks for reading.
BIGINT is just a normal, 64-bit integer. It is not an arbitrary-precision integer.
If you want to store more information, you can either keep it in string form, or use a NUMERIC or DECIMAL type; both solutions are of course much slower than a native, fixed-width integer.

C/C++: How to convert 6bit ASCII to 7bit ASCII

I have a set of 6 bits that represent a 7bit ASCII character. How can I get the correct 7bit ASCII code out of the 6 bits I have? Just append a zero and do an bitwise OR?
Thanks for your help.
Lennart
ASCII is inherently a 7-bit character set, so what you have is not "6-bit ASCII". What characters make up your character set? The simplest decoding approach is probably something like:
char From6Bit( char c6 ) {
// array of all 64 characters that appear in your 6-bit set
static SixBitSet[] = { 'A', 'B', ... };
return SixBitSet[ c6 ];
}
A footnote: 6-bit character sets were quite popular on old DEC hardware, some of which, like the DEC-10, had a 36-bit architecture where 6-bit characters made some sense.
You must tell us how your 6-bit set of characters looks, I don't think there is a standard.
The easiest way to do the reverse mapping would probably be to just use a lookup table, like so:
static const char sixToSeven[] = { ' ', 'A', 'B', ... };
This assumes that space is encoded as (binary) 000000, capital A as 000001, and so on.
You index into sixToSeven with one of your six-bit characters, and get the local 7-bit character back.
I can't imagine why you'd be getting old DEC-10/20 SIXBIT, but if that's what it is, then just add 32 (decimal). SIXBIT took the ASCII characters starting with space (32), so just add 32 to the SIXBIT character to get the ASCII character.
The only recent 6-bit code I'm aware of is base64. This uses four 6-bit printable characters to store three 8-bit values (6x4 = 8x3 = 24 bits).
The 6-bit values are drawn from the characters:
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/
which are the values 0 thru 63. Four of these (say UGF4) are used to represent three 8-bit values.
UGF4 = 010100 000110 000101 111000
= 01010000 01100001 01111000
= Pax
If this is how your data is encoded, there are plenty of snippets around that will tell you how to decode it (and many languages have the encoder and decoder built in, or in an included library). Wikipedia has a good article for it here.
If it's not base64, then you'll need to find out the encoding scheme. Some older schemes used other lookup methods of the shift-in/shift-out (SI/SO) codes for choosing a page within character sets but I think that was more for choosing extended (e.g., Japanese DBCS) characters rather than normal ACSII characters.
If I were to give you the value of a single bit, and I claimed it was taken from Windows XP, could you reconstruct the entire OS?
You can't. You've lost information. There is no way to reconstruct that, unless you have some knowledge about what was lost. If you know that, say, the most significant bit was chopped off, then you can set that to zero, and you've reconstructed at least half the characters correctly.
If you know how 'a' and 'z' are represented in your 6-bit encoding, you might be able to guess at what was removed by comparing them to their 7-bit representations.