hmssql
Safe HaskellNone
LanguageHaskell2010

Hmssql.Tds.Primitives

Description

Binary encodings of individual SQL Server scalar types.

These are the leaf encoders/decoders shared by Hmssql.Tds.TypeInfo, Hmssql.Decoding and Hmssql.Encoding.

Synopsis

Reading values in place

type ValueReader a = ByteString -> Either String a Source #

A conversion of one whole value, given exactly its bytes; where they lay in the packets is the parser's concern. They may be a slice of a receive buffer, so a reader must copy any it keeps.

Writing a value

runPutSized :: Int -> Put -> ByteString Source #

The bytes of a short Put of (at most, or it is slower) n bytes, in a buffer of that size: how a parameter's value is encoded by the put* functions below. binary's own runPut starts with a 4 KiB buffer, a large object of its own, and toStrict then copies the few bytes out of it: about 100 ns and 4 KiB per value.

money / smallmoney

data E4 Source #

Resolution of 1/10000, matching money and smallmoney.

Instances

Instances details
HasResolution E4 Source # 
Instance details

Defined in Hmssql.Tds.Primitives

Methods

resolution :: p E4 -> Integer #

newtype Money Source #

A money or smallmoney value: a fixed-point number with four decimal places, exactly as the server stores it.

Constructors

Money (Fixed E4) 

Instances

Instances details
Num Money Source # 
Instance details

Defined in Hmssql.Tds.Primitives

Fractional Money Source # 
Instance details

Defined in Hmssql.Tds.Primitives

Real Money Source # 
Instance details

Defined in Hmssql.Tds.Primitives

Methods

toRational :: Money -> Rational #

RealFrac Money Source # 
Instance details

Defined in Hmssql.Tds.Primitives

Methods

properFraction :: Integral b => Money -> (b, Money) #

truncate :: Integral b => Money -> b #

round :: Integral b => Money -> b #

ceiling :: Integral b => Money -> b #

floor :: Integral b => Money -> b #

Show Money Source # 
Instance details

Defined in Hmssql.Tds.Primitives

Methods

showsPrec :: Int -> Money -> ShowS #

show :: Money -> String #

showList :: [Money] -> ShowS #

Eq Money Source # 
Instance details

Defined in Hmssql.Tds.Primitives

Methods

(==) :: Money -> Money -> Bool #

(/=) :: Money -> Money -> Bool #

Ord Money Source # 
Instance details

Defined in Hmssql.Tds.Primitives

Methods

compare :: Money -> Money -> Ordering #

(<) :: Money -> Money -> Bool #

(<=) :: Money -> Money -> Bool #

(>) :: Money -> Money -> Bool #

(>=) :: Money -> Money -> Bool #

max :: Money -> Money -> Money #

min :: Money -> Money -> Money #

FromSqlField Money Source #

money and smallmoney, with all four decimal places.

Instance details

Defined in Hmssql.Decoding

ToSqlField Money Source #

money; values outside its range (±922,337,203,685,477.58) are rejected.

Instance details

Defined in Hmssql.Encoding

Methods

fieldEncoder :: FieldEncoder Money Source #

fieldParam :: Money -> FieldParams -> FieldParams

putMoney4 :: Money -> Put Source #

Fails (with error) outside the smallmoney range (money4Problem).

putMoney8 :: Money -> Put Source #

Fails (with error) outside the money range (money8Problem) rather than sending the value modulo 2^64.

readMoney :: ValueReader Money Source #

smallmoney (4 bytes) or money (8 bytes), by the value's length. A money value is two little-endian DWORDs, the high half first.

moneyUnits :: ValueReader Int64 Source #

A money or smallmoney value as its count of 1/10000ths.

money4Problem :: Money -> Maybe String Source #

Likewise for smallmoney (-214,748.3648 through 214,748.3647).

money8Problem :: Money -> Maybe String Source #

Why a Money value doesn't fit in money (a signed 64-bit count of 1/10000ths: -922,337,203,685,477.5808 through 922,337,203,685,477.5807), if it doesn't. Money itself is unbounded.

datetime / smalldatetime (legacy)

putDateTime4 :: LocalTime -> Either String Put Source #

Rounds to the nearest minute (1900-01-01 through 2079-06-06).

putDateTime8 :: LocalTime -> Either String Put Source #

Rounds to the nearest 1/300 s (1753-01-01 through 9999-12-31).

readDateTime4With :: (Day -> Int64 -> a) -> ValueReader a Source #

smalldatetime, passing the day and the picoseconds since midnight to the function (localTimeOf, utcTimeOf).

readDateTime8With :: (Day -> Int64 -> a) -> ValueReader a Source #

datetime, passing the day and the picoseconds since midnight (rounded down) to the function.

date time datetime2 / datetimeoffset (TDS 7.3+)

data DateTimeOffset Source #

A datetimeoffset value: an instant plus the UTC offset it was recorded with.

Constructors

DateTimeOffset 

Fields

Instances

Instances details
Show DateTimeOffset Source # 
Instance details

Defined in Hmssql.Tds.Primitives

Eq DateTimeOffset Source # 
Instance details

Defined in Hmssql.Tds.Primitives

Ord DateTimeOffset Source # 
Instance details

Defined in Hmssql.Tds.Primitives

FromSqlField DateTimeOffset Source # 
Instance details

Defined in Hmssql.Decoding

ToSqlField DateTimeOffset Source #

datetimeoffset(7), rounded like LocalTime. The offset must be within ±14:00 and both the UTC and the local time within years 1 through 9999.

Instance details

Defined in Hmssql.Encoding

Methods

fieldEncoder :: FieldEncoder DateTimeOffset Source #

fieldParam :: DateTimeOffset -> FieldParams -> FieldParams

dateTimeOffsetToZonedTime :: DateTimeOffset -> ZonedTime Source #

The same instant as a ZonedTime in the value's offset.

zonedTimeToDateTimeOffset :: ZonedTime -> DateTimeOffset Source #

An offset beyond the range of Int16 is clamped to it rather than wrapped (so it stays outside the ±14:00 a datetimeoffset allows, and putDateTimeOffset rejects it).

scaleProblem :: String -> Scale -> Maybe String Source #

Why a time, datetime2 or datetimeoffset (named) can't have this scale, if it can't: MS-TDS 2.2.5.4.2 allows 0 through 7. Every exported function here that takes a scale checks it with this.

timeLength :: Scale -> Int Source #

Number of bytes used for the time portion at a given scale (5 for any scale above 4, including invalid ones: see scaleProblem).

putDate :: Day -> Either String Put Source #

0001-01-01 through 9999-12-31.

putTime :: Scale -> TimeOfDay -> Either String Put Source #

Rounds to the nearest unit, but never past 23:59:59.(9...) at the scale.

putDateTime2 :: Scale -> LocalTime -> Either String Put Source #

Rounds to the nearest unit, carrying into the next day.

putDateTimeOffset :: Scale -> DateTimeOffset -> Either String Put Source #

Rounds like putDateTime2. The offset must be within ±14:00, and both the UTC and the local time must be in range.

readDate :: ValueReader Day Source #

date: 3-byte count of days since 0001-01-01.

readTime :: Scale -> ValueReader TimeOfDay Source #

time(scale): a count of units of 10^-scale seconds since midnight.

readDateTime2 :: Scale -> ValueReader LocalTime Source #

datetime2(scale): the time units, then the date.

readDateTimeOffset :: Scale -> ValueReader DateTimeOffset Source #

datetimeoffset(scale): the time units and the date, both in UTC, then the offset as a signed count of minutes.

readDateWith :: (Day -> a) -> ValueReader a Source #

date, passing the day to the function.

readTimeWith :: (Int64 -> a) -> Scale -> ValueReader a Source #

time(scale), passing the picoseconds since midnight to the function.

readDateTime2With :: (Day -> Int64 -> a) -> Scale -> ValueReader a Source #

datetime2(scale), passing the day and the picoseconds since midnight to the function.

readDateTimeOffsetWith :: (Day -> Int64 -> Int16 -> a) -> Scale -> ValueReader a Source #

datetimeoffset(scale), passing the UTC day, the picoseconds since UTC midnight and the offset in minutes to the function. The value is checked as readDateTimeOffset checks it: the offset within ±14:00, and the local date within 0001-01-01 through 9999-12-31.

localTimeOf :: Day -> Int64 -> LocalTime Source #

A LocalTime, evaluated, from a day and picoseconds since midnight.

utcTimeOf :: Day -> Int64 -> UTCTime Source #

A UTCTime, evaluated, from a day and picoseconds since midnight.

picosecondsToTimeOfDay :: Int64 -> TimeOfDay Source #

A time of day from picoseconds since midnight (less than a day).

decimal / numeric

precisionToLength :: Precision -> Int Source #

Length of the magnitude (excluding the sign byte) for a given precision.

putDecimal :: Precision -> Scale -> Decimal -> Put Source #

A decimal at the precision and scale, rounded to the scale: the sign byte and precisionToLength bytes of magnitude.

readDecimal :: Precision -> Scale -> ValueReader Decimal Source #

decimal and numeric: a sign byte (0 negative, 1 positive) followed by a little-endian unsigned magnitude of 4, 8, 12 or 16 bytes (MS-TDS 2.2.5.5.1.3). The magnitude is usually precisionToLength bytes, but SQL Server doesn't always send that: a decimal(10,0) zero read from a table has 4, and a decimal(1,0) in a sql_variant has 16. So any of the four lengths is accepted, as SqlClient accepts them, and the value is checked against the precision instead. Another length, another sign byte, or a magnitude with more digits than the precision allows is a Left.

readDecimalWith :: (Bool -> Word64 -> Word64 -> Scale -> a) -> Precision -> Scale -> ValueReader a Source #

decimal and numeric, checked as readDecimal checks them, passing the value's parts to the function: whether it is negative, the high and low 64 bits of its magnitude, and the scale. A zero is never negative, though the wire can carry one.

uniqueidentifier

putGuid :: UUID -> Put Source #

The layout of readGuid, written.

readGuid :: ValueReader UUID Source #

uniqueidentifier. The first three groups are little-endian on the wire, unlike RFC 4122.

collation

data Collation Source #

MS-TDS 2.2.5.1.2 Collation Rule Definition. Kept opaque: the LCID, flags and version share a DWORD, followed by the sort ID byte.

Constructors

Collation 

Instances

Instances details
Show Collation Source # 
Instance details

Defined in Hmssql.Tds.Primitives

Eq Collation Source # 
Instance details

Defined in Hmssql.Tds.Primitives

collationAt :: ByteString -> Int -> Collation Source #

The five bytes of a collation at an offset.

putCollation :: Collation -> Put Source #

The five bytes of a collation.

UCS-2 strings

decodeUtf16LE :: ByteString -> Text Source #

Decode UTF-16LE text from the server, never failing.

SQL Server stores and sends UCS-2 code units without validating them, so a value can hold unpaired surrogates (NCHAR(0xD800), a reversed pair, a high surrogate cut off at the end of a string). Following the Unicode Standard's recommended practice ("U+FFFD Substitution of Maximal Subparts", ch. 3), each ill-formed code unit becomes exactly one U+FFFD and every well-formed scalar value decodes unchanged. A trailing odd byte (a truncated code unit) also becomes one U+FFFD.

text's own decodeUtf16LE throws on such input, and its decodeUtf16LEWith resynchronizes byte by byte, emitting one U+FFFD per byte and then misreading the following units.

One pass writing UTF-8 into the Text array, eight ASCII units at a time (Hmssql.Tds.Utf16).

putUcs2 :: Text -> Put Source #

Write text as UTF-16LE without a length prefix.

putBVarChar :: Text -> Put Source #

B_VARCHAR: one-byte character count followed by UCS-2 text. Fails (with error) for text of more than 255 UTF-16 code units, which the length byte can't count; check with ucs2Length first.

putUsVarChar :: Text -> Put Source #

US_VARCHAR: two-byte character count followed by UCS-2 text. Fails (with error) for text of more than 65535 UTF-16 code units.

ucs2Length :: Text -> Int Source #

The length of text in UTF-16 code units, which is what B_VARCHAR and US_VARCHAR count (a character outside the BMP is two).