Skip to content

Commit

Permalink
Add support for Money and SmallMoney in result set rows.
Browse files Browse the repository at this point in the history
Fixes #12
  • Loading branch information
pekim committed Feb 12, 2012
1 parent e7c67bf commit 411ddb6
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 3 deletions.
9 changes: 6 additions & 3 deletions lib/token/data-type.coffee
Expand Up @@ -88,6 +88,10 @@ TYPE =
type: 'FLTN'
name: 'FloatN'
dataLengthLength: 1
0x6E:
type: 'MONEYN'
name: 'MoneyN'
dataLengthLength: 1
0x6F:
type: 'DATETIMN'
name: 'DateTimeN'
Expand Down Expand Up @@ -121,11 +125,10 @@ TYPE =
hasCollation: true
dataLengthLength: 2

###
# Variable-length types
# Types not (yet) supported
###
DECIMALTYPE: 0x37 # Decimal (legacy support)
NUMERICTYPE: 0x3F # Numeric (legacy support)
MONEYNTYPE: 0x6E # (see below)
DATENTYPE: 0x28 # (introduced in TDS 7.3)
TIMENTYPE: 0x29 # (introduced in TDS 7.3)
DATETIME2NTYPE: 0x2A # (introduced in TDS 7.3)
Expand Down
14 changes: 14 additions & 0 deletions lib/token/row-token-parser.coffee
Expand Up @@ -6,6 +6,7 @@ require('../buffertools')
NULL = (1 << 16) - 1
MAX = (1 << 16) - 1
THREE_AND_A_THIRD = 3 + (1 / 3)
MONEY_DIVISOR = 10000

PLP_NULL = new Buffer([0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF])
UNKNOWN_PLP_LEN = new Buffer([0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE])
Expand Down Expand Up @@ -90,6 +91,19 @@ parser = (buffer, columnsMetaData) ->
value = buffer.readDoubleLE()
else
throw new Error("Unsupported dataLength #{dataLength} for FloatN")
when 'Money', 'SmallMoney', 'MoneyN'
switch dataLength
when 0
value = null
when 4
value = buffer.readInt32LE() / MONEY_DIVISOR
when 8
high = buffer.readInt32LE()
low = buffer.readUInt32LE()
value = low + (0x100000000 * high)
value /= MONEY_DIVISOR
else
throw new Error("Unsupported dataLength #{dataLength} for MoneyN")
when 'Bit'
value = !!buffer.readUInt8()
when 'BitN'
Expand Down
24 changes: 24 additions & 0 deletions test/integration/datatypes-in-results-test.coffee
Expand Up @@ -79,6 +79,30 @@ exports.numericExtremelyLargeValue = (test) ->
exports.numericNull = (test) ->
execSql(test, "select cast(null as numeric(3,2))", null)

exports.smallMoney = (test) ->
execSql(test, "select cast(1.22229 as smallmoney)", 1.2223)

exports.smallMoneyNegative = (test) ->
execSql(test, "select cast(-1.22229 as smallmoney)", -1.2223)

exports.smallMoneyN = (test) ->
execSql(test, "select cast(null as smallmoney)", null)

exports.money = (test) ->
execSql(test, "select cast(1.22229 as money)", 1.2223)

exports.moneyNegative = (test) ->
execSql(test, "select cast(-1.22229 as money)", -1.2223)

exports.moneyLarge = (test) ->
execSql(test, "select cast(123456789012345.11 as money)", 123456789012345.11)

exports.moneyLargeNegative = (test) ->
execSql(test, "select cast(-123456789012345.11 as money)", -123456789012345.11)

exports.moneyN = (test) ->
execSql(test, "select cast(null as money)", null)

exports.varchar = (test) ->
execSql(test, "select cast('abc' as varchar(10))", 'abc')

Expand Down
33 changes: 33 additions & 0 deletions test/unit/token/row-token-parser-test.coffee
Expand Up @@ -82,6 +82,39 @@ module.exports.float = (test) ->

test.done()

module.exports.money = (test) ->
colMetaData = [
{type: dataTypeByName.SmallMoney}
{type: dataTypeByName.Money}
{type: dataTypeByName.MoneyN}
{type: dataTypeByName.MoneyN}
{type: dataTypeByName.MoneyN}
{type: dataTypeByName.MoneyN}
]
value = 123.456
valueLarge = 123456789012345.11

buffer = new WritableTrackingBuffer(0)
buffer.writeBuffer(new Buffer([0x80, 0xd6, 0x12, 0x00]))
buffer.writeBuffer(new Buffer([0x00, 0x00, 0x00, 0x00, 0x80, 0xd6, 0x12, 0x00]))
buffer.writeBuffer(new Buffer([0x00]))
buffer.writeBuffer(new Buffer([0x04, 0x80, 0xd6, 0x12, 0x00]))
buffer.writeBuffer(new Buffer([0x08, 0x00, 0x00, 0x00, 0x00, 0x80, 0xd6, 0x12, 0x00]))
buffer.writeBuffer(new Buffer([0x08, 0xf4, 0x10, 0x22, 0x11, 0xdc, 0x6a, 0xe9, 0x7d]))

token = parser(new ReadableTrackingBuffer(buffer.data, 'ucs2'), colMetaData)
#console.log(token)

test.strictEqual(token.columns.length, 6)
test.strictEqual(token.columns[0].value, value)
test.strictEqual(token.columns[1].value, value)
test.strictEqual(token.columns[2].value, null)
test.strictEqual(token.columns[3].value, value)
test.strictEqual(token.columns[4].value, value)
test.strictEqual(token.columns[5].value, valueLarge)

test.done()

module.exports.varChar = (test) ->
colMetaData = [type: dataTypeByName.VarChar]
value = 'abc'
Expand Down

0 comments on commit 411ddb6

Please sign in to comment.