This is the catalog for the odbc scalar functions.

https://msdn.microsoft.com/en-us/library/ms711813(v=vs.85).aspx

TODO: this needs finishing

> {-# LANGUAGE OverloadedStrings #-}
> module Database.HsSqlPpp.Dialects.OdbcCatalog
>      (odbcCatalog,odbcConvertTypes,odbcIntervalTypes) where
>
> --import Database.HsSqlPpp.Internals.Catalog.CatalogInternal
> import Database.HsSqlPpp.Internals.Catalog.CatalogTypes

todo: refactor this so we only have the names in this file and get rid
of the leakage of Type into here.

> import Database.HsSqlPpp.Internals.TypesInternal
> --import Database.HsSqlPpp.Internals.TypesInternal

todo: we have to add odbc on top of different dialects, do some tests
then figure out how to handle e.g. the canonical type names being
different in different dialects.

> typeBigInt,typeFloat8,typeChar,typeNumeric,typeFloat4,
>   typeSmallInt,typeInt,typeDate,typeTimestamp,typeVarChar :: Type
> typeBigInt = ScalarType "int8"
> typeFloat8 = ScalarType "float8"
> typeChar = ScalarType "char"
> typeNumeric = ScalarType "numeric"
> typeFloat4 = ScalarType "float4"
> typeSmallInt = ScalarType "int2"
> typeInt = ScalarType "int4"
> typeDate = ScalarType "date"
> typeTimestamp = ScalarType "timestamp"
> typeVarChar = ScalarType "varchar"

> -- | The odbc catalog contains the odbc specific functions
> -- if you want to type check sql with odbc specific functions, you
> -- can add these catalog updates to your catalog and then it should
> -- work
> odbcCatalog :: [CatalogUpdate]
> odbcCatalog = [

string functions

ASCII(string_exp) (ODBC 1.0)
Returns the ASCII code value of the leftmost character of string_exp as an integer.

>         CatCreateFunction "!odbc-ascii" ["text"] False "int4"
>        ,CatCreateFunction "!odbc-ascii" ["char"] False "int4"
>        ,CatCreateFunction "!odbc-ascii" ["varchar"] False "int4"

BIT_LENGTH(string_exp) (ODBC 3.0)
Returns the length in bits of the string expression.
Does not work only for string data types, therefore will not implicitly convert string_exp to string but instead will return the (internal) size of whatever datatype it is given.

>        ,CatCreateFunction "!odbc-bit_length" ["text"] False "int4"
>        ,CatCreateFunction "!odbc-bit_length" ["char"] False "int4"
>        ,CatCreateFunction "!odbc-bit_length" ["varchar"] False "int4"

CHAR(code) (ODBC 1.0)
Returns the character that has the ASCII code value specified by code. The value of code should be between 0 and 255; otherwise, the return value is data sourcedependent.

>        ,CatCreateFunction "!odbc-char" ["int4"] False "char"

CHAR_LENGTH(string_exp) (ODBC 3.0)
Returns the length in characters of the string expression, if the string expression is of a character data type; otherwise, returns the length in bytes of the string expression (the smallest integer not less than the number of bits divided by 8). (This function is the same as the CHARACTER_LENGTH function.)

>        ,CatCreateFunction "!odbc-char_length" ["text"] False "int4"
>        ,CatCreateFunction "!odbc-char_length" ["char"] False "int4"
>        ,CatCreateFunction "!odbc-char_length" ["varchar"] False "int4"

CHARACTER_LENGTH(string_exp) (ODBC 3.0)
Returns the length in characters of the string expression, if the string expression is of a character data type; otherwise, returns the length in bytes of the string expression (the smallest integer not less tha the number of bits divided by 8). (This function is the same as the CHAR_LENGTH function.)

>        ,CatCreateFunction "!odbc-character_length" ["text"] False "int4"
>        ,CatCreateFunction "!odbc-character_length" ["char"] False "int4"
>        ,CatCreateFunction "!odbc-character_length" ["varchar"] False "int4"

CONCAT(string_exp1,string_exp2) (ODBC 1.0)
Returns a character string that is the result of concatenating string_exp2 to string_exp1. The resulting string is DBMS-dependent. For example, if the column represented by string_exp1 contained a NULL value, DB2 would return NULL but SQL Server would return the non-NULL string.

concat not in pg

>       ,CatCreateFunction "!odbc-concat" ["text","text"] False "text"
>       ,CatCreateFunction "!odbc-concat" ["char","char"] False "char"
>       ,CatCreateFunction "!odbc-concat" ["varchar","varchar"] False "varchar"

DIFFERENCE(string_exp1,string_exp2) (ODBC 2.0)
Returns an integer value that indicates the difference between the values returned by the SOUNDEX function for string_exp1 and string_exp2.

difference not in pg

>       ,CatCreateFunction "!odbc-difference" ["text","text"] False "int4"
>       ,CatCreateFunction "!odbc-difference" ["char","char"] False "int4"
>       ,CatCreateFunction "!odbc-difference" ["varchar","varchar"] False "int4"

INSERT(string_exp1, start, length, string_exp2) (ODBC 1.0)
Returns a character string where length characters have been deleted from string_exp1, beginning at start, and where string_exp2 has been inserted into string_exp, beginning at start.

insert not in pg

>       ,CatCreateFunction "!odbc-insert" ["text","int4","int4","text"] False "text"
>       ,CatCreateFunction "!odbc-insert" ["char","int4","int4","char"] False "char"
>       ,CatCreateFunction "!odbc-insert" ["varchar","int4","int4","varchar"] False "varchar"

lcase not in pg

LCASE(string_exp) (ODBC 1.0)
Returns a string equal to that in string_exp, with all uppercase characters converted to lowercase.

>       ,CatCreateFunction "!odbc-lcase" ["text"] False "text"
>       ,CatCreateFunction "!odbc-lcase" ["char"] False "char"
>       ,CatCreateFunction "!odbc-lcase" ["varchar"] False "varchar"

left is opposite in pg

LEFT(string_exp, count) (ODBC 1.0)
Returns the leftmost count characters of string_exp.

>       ,CatCreateFunction "!odbc-left" ["text","int4"] False "text"
>       ,CatCreateFunction "!odbc-left" ["char","int4"] False "char"
>       ,CatCreateFunction "!odbc-left" ["varchar","int4"] False "varchar"

LENGTH(string_exp) (ODBC 1.0)
Returns the number of characters in string_exp, excluding trailing blanks.
LENGTH only accepts strings. Therefore will implicitly convert string_exp to a string, and return the length of this string (not the internal size of the datatype).

TODO: we don't support the custom implicit conversion to string unless
there is a standard implicit conversion usable.

>       ,CatCreateFunction "!odbc-length" ["text"] False "text"
>       ,CatCreateFunction "!odbc-length" ["char"] False "char"
>       ,CatCreateFunction "!odbc-length" ["varchar"] False "varchar"


LOCATE(string_exp1, string_exp2[, start])  (ODBC 1.0)
Returns the starting position of the first occurrence of string_exp1 within string_exp2. The search for the first occurrence of string_exp1 begins with the first character position in string_exp2 unless the optional argument, start, is specified. If start is specified, the search begins with the character position indicated by the value of start. The first character position in string_exp2 is indicated by the value 1. If string_exp1 is not found within string_exp2, the value 0 is returned.
If an application can call the LOCATE scalar function with the string_exp1, string_exp2, and start arguments, the driver returns SQL_FN_STR_LOCATE when SQLGetInfo is called with an Option of SQL_STRING_FUNCTIONS. If the application can call the LOCATE scalar function with only the string_exp1 and string_exp2 arguments, the driver returns SQL_FN_STR_LOCATE_2 when SQLGetInfo is called with an Option of SQL_STRING_FUNCTIONS. Drivers that support calling the LOCATE function with either two or three arguments return both SQL_FN_STR_LOCATE and SQL_FN_STR_LOCATE_2.

>       ,CatCreateFunction "!odbc-locate" ["text","text"] False "int4"
>       ,CatCreateFunction "!odbc-locate" ["text","text","int4"] False "int4"
>       ,CatCreateFunction "!odbc-locate" ["char","char"] False "int4"
>       ,CatCreateFunction "!odbc-locate" ["char","char","int4"] False "int4"
>       ,CatCreateFunction "!odbc-locate" ["varchar","varchar"] False "int4"
>       ,CatCreateFunction "!odbc-locate" ["varchar","varchar","int4"] False "int4"

LTRIM(string_exp) (ODBC 1.0)
Returns the characters of string_exp, with leading blanks removed.

>       ,CatCreateFunction "!odbc-ltrim" ["text"] False "text"
>       ,CatCreateFunction "!odbc-ltrim" ["char"] False "char"
>       ,CatCreateFunction "!odbc-ltrim" ["varchar"] False "varchar"


OCTET_LENGTH(string_exp) (ODBC 3.0)
Returns the length in bytes of the string expression. The result is the smallest integer not less than the number of bits divided by 8.
Does not work only for string data types, therefore will not implicitly convert string_exp to string but instead will return the (internal) size of whatever datatype it is given.

>       ,CatCreateFunction "!odbc-octet_length" ["text"] False "int4"
>       ,CatCreateFunction "!odbc-octet_length" ["char"] False "int4"
>       ,CatCreateFunction "!odbc-octet_length" ["varchar"] False "int4"

POSITION(character_exp IN character_exp) (ODBC 3.0)
Returns the position of the first character expression in the second character expression. The result is an exact numeric with an implementation-defined precision and a scale of 0.

we don't support position for now since we this is a ansi sql syntax
which we also don't currently support

REPEAT(string_exp, count) (ODBC 1.0)
Returns a character string composed of string_exp repeated count times.

>       ,CatCreateFunction "!odbc-repeat" ["text","int4"] False "text"
>       ,CatCreateFunction "!odbc-repeat" ["char","int4"] False "char"
>       ,CatCreateFunction "!odbc-repeat" ["varchar","int4"] False "varchar"

REPLACE(string_exp1, string_exp2, string_exp3) (ODBC 1.0)
Search string_exp1 foroccurrences of string_exp2, and replace with string_exp3.

>       ,CatCreateFunction "!odbc-replace" ["text","text","text"] False "text"
>       ,CatCreateFunction "!odbc-replace" ["char","char","char"] False "char"
>       ,CatCreateFunction "!odbc-replace" ["varchar","varchar","varchar"] False "varchar"

RIGHT(string_exp, count) (ODBC 1.0)
Returns the rightmost count characters of string_exp.

>       ,CatCreateFunction "!odbc-right" ["text","int4"] False "text"
>       ,CatCreateFunction "!odbc-right" ["char","int4"] False "char"
>       ,CatCreateFunction "!odbc-right" ["varchar","int4"] False "varchar"


RTRIM(string_exp) (ODBC 1.0)
Returns the characters of string_exp with trailing blanks removed.

>       ,CatCreateFunction "!odbc-rtrim" ["text"] False "text"
>       ,CatCreateFunction "!odbc-rtrim" ["char"] False "char"
>       ,CatCreateFunction "!odbc-rtrim" ["varchar"] False "varchar"

SOUNDEX(string_exp) (ODBC 2.0)
Returns a data sourcedependent character string representing the sound of the words in string_exp. For example, SQL Server returns a 4-digit SOUNDEX code; Oracle returns a phonetic representation of each word.

>       ,CatCreateFunction "!odbc-soundex" ["text"] False "text"
>       ,CatCreateFunction "!odbc-soundex" ["char"] False "char"
>       ,CatCreateFunction "!odbc-soundex" ["varchar"] False "varchar"


SPACE(count) (ODBC 2.0)
Returns a character string consisting of count spaces.

>       ,CatCreateFunction "!odbc-space" ["int4"] False "char"

SUBSTRING(string_exp, start, length) (ODBC 1.0)
Returns a character string that is derived from string_exp, beginning at the character position specified by start for length characters.

>       ,CatCreateFunction "!odbc-substring" ["text","int4","int4"] False "text"
>       ,CatCreateFunction "!odbc-substring" ["char","int4","int4"] False "char"
>       ,CatCreateFunction "!odbc-substring" ["varchar","int4","int4"] False "varchar"

UCASE(string_exp) (ODBC 1.0)
Returns a string equal to that in string_exp, with all lowercase characters converted to uppercase.

>       ,CatCreateFunction "!odbc-ucase" ["text"] False "text"
>       ,CatCreateFunction "!odbc-ucase" ["char"] False "char"
>       ,CatCreateFunction "!odbc-ucase" ["varchar"] False "varchar"

numeric functions

>       ]

ABS(numeric_exp) (ODBC 1.0)
Returns the absolute value of numeric_exp.

>        ++ [CatCreateFunction "!odbc-abs" [n] False n  | n <- numTypes]

ACOS(float_exp) (ODBC 1.0)
Returns the arccosine of float_exp as an angle, expressed in radians.

>        ++ [CatCreateFunction "!odbc-acos" [n] False n  | n <- floatTypes]

ASIN(float_exp) (ODBC 1.0)
Returns the arcsine of float_exp as an angle, expressed in radians.

>        ++ [CatCreateFunction "!odbc-asin" [n] False n  | n <- floatTypes]

ATAN(float_exp) (ODBC 1.0)
Returns the arctangent of float_exp as an angle, expressed in radians.

>        ++ [CatCreateFunction "!odbc-atan" [n] False n  | n <- floatTypes]

ATAN2(float_exp1, float_exp2) (ODBC 2.0)
Returns the arctangent of the x and y coordinates, specified by float_exp1 and float_exp2, respectively, as an angle, expressed in radians.

>        ++ [CatCreateFunction "!odbc-atan2" [n] False n  | n <- floatTypes]

CEILING(numeric_exp) (ODBC 1.0)
Returns the smallest integer greater than or equal to numeric_exp. The return value is of the same data type as the input parameter.

>        ++ [CatCreateFunction "!odbc-ceiling" [n] False n  | n <- numTypes]

COS(float_exp) (ODBC 1.0)
Returns the cosine of float_exp, where float_exp is an angle expressed in radians.

>        ++ [CatCreateFunction "!odbc-cos" [n] False n  | n <- floatTypes]

COT(float_exp) (ODBC 1.0)
Returns the cotangent of float_exp, where float_exp is an angle expressed in radians.

>        ++ [CatCreateFunction "!odbc-cot" [n] False n  | n <- floatTypes]

DEGREES(numeric_exp) (ODBC 2.0)
Returns the number of degrees converted from numeric_exp radians.

>        ++ [CatCreateFunction "!odbc-degrees" [n] False n  | n <- numTypes]

EXP(float_exp) (ODBC 1.0)
Returns the exponential value of float_exp.

>        ++ [CatCreateFunction "!odbc-exp" [n] False n  | n <- floatTypes]

FLOOR(numeric_exp) (ODBC 1.0)
Returns the largest integer less than or equal to numeric_exp. The return value is of the same data type as the input parameter.

>        ++ [CatCreateFunction "!odbc-floor" [n] False n  | n <- numTypes]

LOG(float_exp) (ODBC 1.0)
Returns the natural logarithm of float_exp.

>        ++ [CatCreateFunction "!odbc-log" [n] False n  | n <- floatTypes]

LOG10(float_exp) (ODBC 2.0)
Returns the base 10 logarithm of float_exp.

>        ++ [CatCreateFunction "!odbc-log10" [n] False n  | n <- floatTypes]

MOD(integer_exp1, integer_exp2) (ODBC 1.0)
Returns the remainder (modulus) of integer_exp1 divided by integer_exp2.

>        ++ [CatCreateFunction "!odbc-mod" [n] False n  | n <- intTypes]

PI( ) (ODBC 1.0)
Returns the constant value of pi as a floating-point value.

>        ++ [CatCreateFunction "!odbc-pi" [] False "float8"]

POWER(numeric_exp, integer_exp) (ODBC 2.0)
Returns the value of numeric_exp to the power of integer_exp.

>        ++ [CatCreateFunction "!odbc-power" [n,m] False n | n <- numTypes, m <- intTypes]

RADIANS(numeric_exp) (ODBC 2.0)
Returns the number of radians converted from numeric_exp degrees.

>        ++ [CatCreateFunction "!odbc-radians" [n] False n | n <- numTypes]

RAND([integer_exp]) (ODBC 1.0)
Returns a random floating-point value using integer_exp as the optional seed value.

>        ++ [CatCreateFunction "!odbc-rand" [n] False n | n <- intTypes]

ROUND(numeric_exp, integer_exp) (ODBC 2.0)
Returns numeric_exp rounded to integer_exp places right of the decimal point. If integer_exp is negative, numeric_exp is rounded to |integer_exp| places to the left of the decimal point.

>        ++ [CatCreateFunction "!odbc-round" [n,m] False n | n <- numTypes, m <- intTypes]

SIGN(numeric_exp) (ODBC 1.0)
Returns an indicator of the sign of numeric_exp. If numeric_exp is less than zero, 1 is returned. If numeric_exp equals zero, 0 is returned. If numeric_exp is greater than zero, 1 is returned.

>        ++ [CatCreateFunction "!odbc-sign" [n] False n  | n <- numTypes]

SIN(float_exp) (ODBC 1.0)
Returns the sine of float_exp, where float_exp is an angle expressed in radians.

>        ++ [CatCreateFunction "!odbc-sin" [n] False n  | n <- floatTypes]

SQRT(float_exp) (ODBC 1.0)
Returns the square root of float_exp.

>        ++ [CatCreateFunction "!odbc-sqrt" [n] False n  | n <- floatTypes]

TAN(float_exp) (ODBC 1.0)
Returns the tangent of float_exp, where float_exp is an angle expressed in radians.

>        ++ [CatCreateFunction "!odbc-tan" [n] False n  | n <- floatTypes]

TRUNCATE(numeric_exp, integer_exp) (ODBC 2.0)
Returns numeric_exp truncated to integer_exp places right of the decimal point. If integer_exp is negative, numeric_exp is truncated to |integer_exp| places to the left of the decimal point.

>        ++ [CatCreateFunction "!odbc-log10" [n,m] False n  | n <- numTypes, m <- intTypes]

>        ++ [

time

CURRENT_DATE( ) (ODBC 3.0)
Returns the current date.

>        CatCreateFunction "!odbc-current_date" [] False "date"

CURRENT_TIME[(time-precision)] (ODBC 3.0)
Returns the current local time. The time-precision argument determines the seconds precision of the returned value.

>       ,CatCreateFunction "!odbc-current_time" [] False "time"

CURRENT_TIMESTAMP [(timestamp-precision)] (ODBC 3.0)
Returns the current local date and local time as a timestamp value. The timestamp-precision argument determines the seconds precision of the returned timestamp.

>       ,CatCreateFunction "!odbc-current_timestamp" [] False "timestamp"

CURDATE( ) (ODBC 1.0)
Returns the current date.

>       ,CatCreateFunction "!odbc-curdate" [] False "date"

CURTIME( ) (ODBC 1.0)
Returns the current local time.

>       ,CatCreateFunction "!odbc-curtime" [] False "time"]

DAYNAME(date_exp) (ODBC 2.0)
Returns a character string containing the data sourcespecific name of the day (for example, Sunday through Saturday or Sun. through Sat. for a data source that uses English, or Sonntag through Samstag for a data source that uses German) for the day portion of date_exp.

>       ++ [CatCreateFunction "!odbc-dayname" [d] False "varchar" | d <- dateTypes]

DAYOFMONTH(date_exp) (ODBC 1.0)
Returns the day of the month based on the month field in date_exp as an integer value in the range of 131.

>       ++ [CatCreateFunction "!odbc-dayofmonth" [d] False "int4" | d <- dateTypes]

DAYOFWEEK(date_exp) (ODBC 1.0)
Returns the day of the week based on the week field in date_exp as an integer value in the range of 17, where 1 represents Sunday.

>       ++ [CatCreateFunction "!odbc-dayofweek" [d] False "int4" | d <- dateTypes]

DAYOFYEAR(date_exp) (ODBC 1.0)
Returns the day of the year based on the year field in date_exp as an integer value in the range of 1366.

>       ++ [CatCreateFunction "!odbc-dayofyear" [d] False "int4" | d <- dateTypes]

EXTRACT(extract-field FROM extract-source) (ODBC 3.0)
Returns the extract-field portion of the extract-source. The extract-source argument is a datetime or interval expression. The extract-field argument can be one of the following keywords:
YEAR MONTH DAY HOUR MINUTE SECOND
The precision of the returned value is implementation-defined. The scale is 0 unless SECOND is specified, in which case the scale is not less than the fractional seconds precision of the extract-source field.

This is a special case and handled purely in the typechecker

HOUR(time_exp) (ODBC 1.0)
Returns the hour based on the hour field in time_exp as an integer value in the range of 023.

>       ++ [CatCreateFunction "!odbc-hour" [d] False "int4" | d <- timeTypes]

MINUTE(time_exp) (ODBC 1.0)
Returns the minute based on the minute field in time_exp as an integer value in the range of 059.

>       ++ [CatCreateFunction "!odbc-minute" [d] False "int4" | d <- timeTypes]

MONTH(date_exp) (ODBC 1.0)
Returns the month based on the month field in date_exp as an integer value in the range of 112.

>       ++ [CatCreateFunction "!odbc-month" [d] False "int4" | d <- dateTypes]

MONTHNAME(date_exp) (ODBC 2.0)
Returns a character string containing the data sourcespecific name of the month (for example, January through December or Jan. through Dec. for a data source that uses English, or Januar through Dezember for a data source that uses German) for the month portion of date_exp.

>       ++ [CatCreateFunction "!odbc-monthname" [d] False "varchar" | d <- dateTypes]

NOW( ) (ODBC 1.0)
Returns current date and time as a timestamp value.

>       ++ [CatCreateFunction "!odbc-now" [] False "timestamp"]

QUARTER(date_exp) (ODBC 1.0)
Returns the quarter in date_exp as an integer value in the range of 14, where 1 represents January 1 through March 31.

>       ++ [CatCreateFunction "!odbc-quarter" [d] False "int4" | d <- dateTypes]

SECOND(time_exp) (ODBC 1.0)
Returns the second based on the second field in time_exp as an integer value in the range of 059.

>       ++ [CatCreateFunction "!odbc-second" [d] False "int4" | d <- timeTypes]

TIMESTAMPADD(interval, integer_exp, timestamp_exp) (ODBC 2.0)
Returns the timestamp calculated by adding integer_exp intervals of type interval to timestamp_exp. Valid values of interval are the following keywords:
SQL_TSI_FRAC_SECOND
SQL_TSI_SECOND
SQL_TSI_MINUTE
SQL_TSI_HOUR
SQL_TSI_DAY
SQL_TSI_WEEK
SQL_TSI_MONTH
SQL_TSI_QUARTER
SQL_TSI_YEAR
where fractional seconds are expressed in billionths of a second. For example, the following SQL statement returns the name of each employee and his or her one-year anniversary date:
SELECT NAME, {fn TIMESTAMPADD(SQL_TSI_YEAR, 1, HIRE_DATE)} FROM EMPLOYEES
If timestamp_exp is a time value and interval specifies days, weeks, months, quarters, or years, the date portion of timestamp_exp is set to the current date before calculating the resulting timestamp.
If timestamp_exp is a date value and interval specifies fractional seconds, seconds, minutes, or hours, the time portion of timestamp_exp is set to 0 before calculating the resulting timestamp.
An application determines which intervals a data source supports by calling SQLGetInfo with the SQL_TIMEDATE_ADD_INTERVALS option.

>        ++ [CatCreateFunction "!odbc-timestampadd" ["int4","int4","date"] False "date"
>       ,CatCreateFunction "!odbc-timestampadd" ["int4","int4","time"] False "time"
>       ,CatCreateFunction "!odbc-timestampadd" ["int4","int4","timestamp"] False "timestamp"

TIMESTAMPDIFF(interval, timestamp_exp1, timestamp_exp2) (ODBC 2.0)
Returns the integer number of intervals of type interval by which timestamp_exp2 is greater than timestamp_exp1. Valid values of interval are the following keywords:
SQL_TSI_FRAC_SECOND
SQL_TSI_SECOND
SQL_TSI_MINUTE
SQL_TSI_HOUR
SQL_TSI_DAY
SQL_TSI_WEEK
SQL_TSI_MONTH
SQL_TSI_QUARTER
SQL_TSI_YEAR
where fractional seconds are expressed in billionths of a second. For example, the following SQL statement returns the name of each employee and the number of years he or she has been employed:
SELECT NAME, {fn TIMESTAMPDIFF(SQL_TSI_YEAR, {fn CURDATE()}, HIRE_DATE)} FROM EMPLOYEES
If either timestamp expression is a time value and interval specifies days, weeks, months, quarters, or years, the date portion of that timestamp is set to the current date before calculating the difference between the timestamps.
If either timestamp expression is a date value and interval specifies fractional seconds, seconds, minutes, or hours, the time portion of that timestamp is set to 0 before calculating the difference between the timestamps.
An application determines which intervals a data source supports by calling SQLGetInfo with the SQL_TIMEDATE_DIFF_INTERVALS option.

>       ,CatCreateFunction "!odbc-timestampdiff" ["int4","time","time"] False "int4"
>       ,CatCreateFunction "!odbc-timestampdiff" ["int4","date","date"] False "int4"
>       ,CatCreateFunction "!odbc-timestampdiff" ["int4","timestamp","timestamp"] False "int4"]


WEEK(date_exp) (ODBC 1.0)
Returns the week of the year based on the week field in date_exp as an integer value in the range of 153.

>       ++ [CatCreateFunction "!odbc-week" [d] False "int4" | d <- dateTypes]

YEAR(date_exp) (ODBC 1.0)
Returns the year based on the year field in date_exp as an integer value. The range is data sourcedependent.

>       ++ [CatCreateFunction "!odbc-year" [d] False "int4" | d <- dateTypes]

system

DATABASE( ) (ODBC 1.0)
Returns the name of the database corresponding to the connection handle. (The name of the database is also available by calling SQLGetConnectOption with the SQL_CURRENT_QUALIFIER connection option.)

>       ++ [CatCreateFunction "!odbc-database" [] False "varchar"]

IFNULL(exp,value) (ODBC 1.0)
If exp is null, value is returned. If exp is not null, exp is returned. The possible data type or types of value must be compatible with the data type of exp.

>       ++ [CatCreateFunction "!odbc-ifnull" [t,t] False t | t <- allTypes]

USER( ) (ODBC 1.0)
Returns the user name in the DBMS. (The user name is also available by way of SQLGetInfo by specifying the information type: SQL_USER_NAME.) This can be different than the login name.

>       ++ [CatCreateFunction "!odbc-user" [] False "varchar"]

conversion function

CONVERT(value_exp, data_type)
The function returns the value specified by value_exp converted to the specified data_type, where data_type is one of the following keywords:
SQL_BIGINT
SQL_INTERVAL_HOUR_TO_MINUTE
SQL_BINARY
SQL_INTERVAL_HOUR_TO_SECOND
SQL_BIT
SQL_INTERVAL_MINUTE_TO_SECOND
SQL_CHAR
SQL_LONGVARBINARY
SQL_DECIMAL
SQL_LONGVARCHAR
SQL_DOUBLE
SQL_NUMERIC
SQL_FLOAT
SQL_REAL
SQL_GUID
SQL_SMALLINT
SQL_INTEGER
SQL_DATE
SQL_INTERVAL_MONTH
SQL_TIME
SQL_INTERVAL_YEAR
SQL_TIMESTAMP
SQL_INTERVAL_YEAR_TO_MONTH
SQL_TINYINT
SQL_INTERVAL_DAY
SQL_VARBINARY
SQL_INTERVAL_HOUR
SQL_VARCHAR
SQL_INTERVAL_MINUTE
SQL_WCHAR
SQL_INTERVAL_SECOND
SQL_WLONGVARCHAR
SQL_INTERVAL_DAY_TO_HOUR
SQL_WVARCHAR
SQL_INTERVAL_DAY_TO_MINUTE

SQL_INTERVAL_DAY_TO_SECOND


>    ++ [CatCreateFunction "!odbc-convert" [t,"int4"] False t
>       | t <- ["int2","int4","int8", "float4", "float8", "numeric"
>              ,"date","time","timestamp","char","varchar","text"
>              ,"bool"]
>       ]
>    where
>      floatTypes = ["float4","float8"]
>      numTypes = ["int2","int4","int8", "float4", "float8", "numeric"]
>      -- if a numeric with a fraction part is used, then maybe
>      -- it is a runtime error, or maybe the typechecker can understand this
>      -- most of the time and give a compile error, or maybe
>      -- it should cast it?
>      intTypes = ["int2","int4","int8", "numeric"]
>      timeTypes = ["time","timestamp"]
>      dateTypes = ["date","timestamp"]
>      allTypes = ["int2","int4","int8", "float4", "float8", "numeric"
>                 ,"date","time","timestamp","char","varchar","text"
>                 ,"bool"]

TODO : all the weird ones are commented out. I couldn't find a clear
reference on what the correspondence between the convert enum
identifiers and sql types are. The interval ones are the most likely
to be needed out of the commented out ones. Maybe they return smallint
or int or something.

> odbcConvertTypes :: [(String,Type)]
> odbcConvertTypes = [("sql_bigint", typeBigInt)
>                    ,("sql_float", typeFloat8)
>                    --,("sql_interval_hour_to_minute", typeFloat8)
>                    --,("sql_binary", $ ScalarType "unknown")
>                    --,("sql_interval_hour_to_second", typeFloat8)
>                    --,("sql_bit", $ ScalarType "unknown")
>                    --,("sql_interval_minute_to_second", typeFloat8)
>                    ,("sql_char", typeChar)
>                    --,("sql_longvarbinary", $ ScalarType "unknown")
>                    ,("sql_decimal", typeNumeric)
>                    --,("sql_longvarchar", typeVarChar)
>                    ,("sql_double", typeFloat8)
>                    ,("sql_numeric", typeNumeric)
>                    ,("sql_float", typeFloat8)
>                    ,("sql_real", typeFloat4)
>                    --,("sql_guid", $ ScalarType "unknown")
>                    ,("sql_smallint", typeSmallInt)
>                    ,("sql_integer", typeInt)
>                    ,("sql_date", typeDate)
>                    --,("sql_interval_month", typeFloat8)
>                    ,("sql_time", ScalarType "time")
>                    --,("sql_interval_year", typeFloat8)
>                    ,("sql_timestamp", typeTimestamp)
>                    --,("sql_interval_year_to_month", typeFloat8)
>                    --,("sql_tinyint", $ ScalarType "unknown")
>                    --,("sql_interval_day", typeFloat8)
>                    --,("sql_varbinary", $ ScalarType "unknown")
>                    --,("sql_interval_hour", typeFloat8)
>                    ,("sql_varchar", typeVarChar)
>                    --,("sql_interval_minute", typeFloat8)
>                    --,("sql_wchar", $ ScalarType "unknown")
>                    --,("sql_interval_second", typeFloat8)
>                    --,("sql_wlongvarchar", typeVarChar)
>                    --,("sql_interval_day_to_hour", typeFloat8)
>                    --,("sql_wvarchar", $ ScalarType "unknown")
>                    --,("sql_interval_day_to_minute", typeFloat8)
>                    --,("sql_interval_day_to_second", typeFloat8)
>                    ]

> odbcIntervalTypes :: [String]
> odbcIntervalTypes = ["sql_tsi_frac_second"
>                     ,"sql_tsi_second"
>                     ,"sql_tsi_minute"
>                     ,"sql_tsi_hour"
>                     ,"sql_tsi_day"
>                     ,"sql_tsi_week"
>                     ,"sql_tsi_month"
>                     ,"sql_tsi_quarter"
>                     ,"sql_tsi_year"]