Skip to content
CA Datacom Core - 15.1
Documentation powered by DocOps

Scalar Functions

Last update December 5, 2018

Scalar functions are a CA Datacom®/DB extension. A scalar function produces a single value from another value. It is expressed in the form of a function name, followed by a list of arguments enclosed in parentheses.

Scalar functions may be nested within scalar functions or column functions, and column functions may be nested within scalar functions. For more information about nesting, see Rules for Scalar Functions.

Following is the syntax diagram for scalar functions. This is CA Datacom®/DB extension. For details, see the following:

►►─┬─┬─ DATE ────────┬─ (expression) ───────────────────────┬─────────────────►◄
   │ ├─ DAY ─────────┤                                      │
   │ ├─ DAYS ────────┤                                      │
   │ ├─ DIGITS ──────┤                                      │
   │ ├─ FLOAT ───────┤                                      │
   │ ├─ HEX ─────────┤                                      │
   │ ├─ HOUR ────────┤                                      │
   │ ├─ INTEGER ─────┤                                      │
   │ ├─ LENGTH ──────┤                                      │
   │ ├─ MICROSECOND ─┤                                      │
   │ ├─ MINUTE ──────┤                                      │
   │ ├─ MONTH ───────┤                                      │
   │ ├─ SECOND ──────┤                                      │
   │ ├─ TIME ────────┤                                      │
   │ ├─ VARGRAPHIC ──┤                                      │
   │ └─ YEAR ────────┘                                      │
   ├─ CHAR(expression ─┬────────┬─ ) ───────────────────────┤
   │                   ├─ ,ISO ─┤                           │
   │                   ├─ ,USA ─┤                           │
   │                   ├─ ,EUR ─┤                           │
   │                   └─ ,JIS ─┘                           │
   ├─ DECIMAL(expression ─┬───────────────────────────┬─ ) ─┤
   │                      └─ ,integer ─┬────────────┬─┘     │
   │                                   └─ ,integer ─┘       │

   ├─ MOD(expression1,expression2)──────────────────────────┤

   ├─ SUBSTR(string,start ─┬───────────┬─ ) ────────────────┤
   │                       └─ ,length ─┘                    │
   ├─ TIMESTAMP(expression ─┬───────────────┬─ ) ───────────┤
   │                        └─ ,expression ─┘               │
   │                    ┌───────────────┐                   │
   ├─ VALUE(expression ─▼─ ,expression ─┴─ ) ───────────────┤
   ├─ character-functions ──────────────────────────────────┤
   ├─ bit-level-functions ──────────────────────────────────┤
   ├─ byte-level-function ──────────────────────────────────┤
   └─ xml-functions ────────────────────────────────────────┘

Topics discussed on this page include:

 

Rules for Scalar Functions

Scalar functions may be nested within scalar functions. For example:

DATE(TIMESTAMP(LASTCHANGED)) results in the conversion of the value in a column from a string representation of a TIMESTAMP into a TIMESTAMP value and then extracts the DATE from that TIMESTAMP.

Scalar functions may be nested within column functions. For example:

AVG(YEAR(HIREDATE)) results in the average year all hiring was done.

Column functions may be nested within scalar functions. For example:

YEAR(MAX(HIREDATE)) results in the last year hiring was done.

Description

The following descriptions of the entries shown in the previous syntax diagram are listed in alphabetical order, except for the description of expression, described first because of its multiple occurrences in the diagram. Also, see Rules for Scalar Functions.

  • bit-level-functions
    See Bit-Level Functions
  • byte-level-function
    See Byte-Level Function
  • CHAR
    Use the CHAR function to obtain a string representation of a date/time value. The result is a fixed-length character string. Its first argument must be a date, time, or timestamp. Its second argument is used, when the first argument is a date or time, to specify an ISO, USA, EUR, or JIS string format.
    If the first argument is a date, the result has a length of 10 and is the character string representation of the date in the format specified by the second argument.
    If the first argument is a time, the result has a length of eight and is the character string representation of the time in the format specified by the second argument.
    If the first argument is a timestamp, the result has a length of 26 and is the character string representation of the timestamp. Do not specify a second argument (for a string format) when the first argument is a timestamp.
    For information about date, time, and timestamp formats, see Character String Literals in Basic SQL Language Elements.
    • ,ISO
      Specifies International Standards Organization format.
    • ,USA
      Specifies International USA Standard format.
    • ,EUR
      Specifies IBM European Standard format.
    • ,JIS
      Specifies Japanese Industrial Standard format.
  • character-functions
    See Character Functions
  • DATE
    Use the DATE function to obtain a date from a value. The result is a date. Its argument must be a date, timestamp, a string representation of a date, a character string of length 7, or a positive number.
    For example, DATE(TIMESTAMP('1989-03-20-11.30.00') + 2 DAYS) results in a date of 1989-03-22 (in ISO or JIS format).
    If its argument is a character string of length seven, it is assumed to have the form yyyynnn where yyyy is the year and nnn is the day within the year in the range of 001 to 366.
    For example, DATE('1989079') results in a date of 1989-03-20 (in ISO or JIS format).
    If the argument is a positive number, n, the result is the date that is n days after December 31, 0000.
    For example, DATE(32) results in a date of 0001-02-01 (in ISO or JIS format).
  • DAY
    Use the DAY function to obtain the day part of a value. The result is an integer representing a day. The sign of the result is negative only if the value of its expression is a negative duration. Its argument must be a date, timestamp, or DECIMAL(8,0) number interpreted as a date-duration.
    For example, if BIRTHDATE is March 25, 1945, that is to say, 19450325, then DAY(BIRTHDATE) results in 25.
  • DAYS
    Use the DAYS function to obtain an integer representation of a date. The result is an integer representing the number of days since December 31, 0000 (that is to say, January 1 is 1 day, February 1 is 32 days, and so on). The sign of the result is always positive. Its argument can be a date, timestamp, or string representation of a date.
    For example, DAYS('0001-02-01') results in 32 days.
  • DECIMAL
    Use the DECIMAL function to obtain a decimal representation of a numeric value. Three arguments are possible. The first argument is required. The second and third arguments (labeled as "integer" in the syntax diagram) are optional. The result is a decimal number with a precision of p and a scale of s, where p is the second argument and s is the third argument.
    The first argument must be a number. If you specify a second argument, it represents the precision p and must be an integer in the range of 1 to 31. If you specify a third argument, it represents the scale s and must be an integer in the range of 0 to the p specified in the second argument. You cannot specify a third argument if you have not specified a second argument.
  • Note: A character is allowed for the first argument. However, it must follow the rules in the note after the comparison chart for unsigned numeric and characters in the Numerics section of Basic SQL Language Operations (Assignment and Comparison).
    Omitting the third argument results in a value of 0 for the scale. Omitting the second argument results in:
    • p = 15 if the first argument is floating-point or decimal
    • p = 10 if the first argument is a large integer
    • p = 5 if the first argument is a small integer.
    The result can be null if the first argument can be null; the result is the null value if the first argument is null. The result is the same number that would occur if the first argument were assigned to a decimal column or variable with a precision of p and a scale of s.
    If the number of significant decimal digits required to represent the whole part of the number is greater than p-s, an error occurs.
    For example, if SALARY is a FLOAT column, DECIMAL(AVG(SALARY),8,2) results in the average salary being converted to a packed decimal value of xxxxxx.xx.
  • DIGITS
    Use the DIGITS function to obtain a fixed-length character string representation of a number. Its argument must be an integer or a decimal number. The string of digits that make up the result represent the absolute value of the argument without regard to its scale. Therefore, the result does not include a sign or a decimal point. Leading zeros are included in the result as necessary so that length of string equals:
    • 5 if argument is a small integer
    • 10 if argument is a large integer
    • p if argument is a decimal number with precision p.
    The result can be null if the argument can be null; the result is the null value if the argument is null.
    For example, if the data type of COLUMNX is DECIMAL(6,2), and if COLUMNX has a value of -7.27, then DIGITS(COLUMNX) gives '000727' as the result.
  • (expression)
    Enter the expression which is to be the argument of the function. For more information about expressions, see Expressions.
  • FLOAT
    Use the FLOAT function to obtain a floating-point representation of a number. Its argument must be a number. A double precision floating-point number is the result. The result can be null if the argument can be null; the result is the null value if the argument is null.
    For example, if ACSTAFF is an INTEGER column, FLOAT(ACSTAFF)/2 results in the double precision floating-point representation of half of the value in ACSTAFF.
  • HEX
    Use the HEX function to obtain an hexadecimal representation of a value. A character string is the result of the function. The result can be null if the argument can be null; the result is the null value if the argument is null.
    In the string of hexadecimal digits that form the result, the first two digits represent the first byte of the argument, the second two digits the second byte, and so on. If a date or time value is the argument, the result is the hexadecimal representation of the internal form of the argument.
    The length of the result is twice the defined (maximum) length of the argument.
    If the argument is not a varying-length string and the length of the result is less than 255, the result is a fixed-length string. Otherwise, the result is a varying-length string whose maximum length depends on the following considerations. If the argument:
    • Is not a varying-length string: maximum length of the result string is the same as the length of the result.
    • Is a varying-length string: maximum length of the result string is twice the maximum length of the argument.
    For example, if 'ABC' is contained in CHAR column COLX, HEX(COLX) results in the fixed-length string 'C1C2C3'.
  • HOUR
    Use the HOUR function to obtain the hour part of a value. The result is an integer representing an hour. The sign of the result is negative only if the value of its argument is a negative duration. Its argument must be a time, timestamp, or a DECIMAL(6,0) number interpreted as a time-duration.
    For example, if TIME1 is a timestamp of 19890203093020009900, then HOUR(TIME1) results in 9.
  • INTEGER
    Use the INTEGER function to obtain an integer representation of a number. The argument must be a number. A large integer is the result of the function. The result can be null if the argument can be null; the result is the null value if the argument is null.
    The result obtained by this function is the same number that would occur if the argument were assigned to a large integer column or variable. An error occurs if the whole part of the argument is not within the range of integers.
    For example, if PAYNUM is a DECIMAL(8,2) column, INTEGER(SUM(PAYNUM)+.5) results in the sum (rounded up) as an integer value.
  • LENGTH
    Use the LENGTH function to obtain the length of a value. Any value can be used as the argument. The result is a large integer. The result can be null if the argument can be null. The result is the null value if the argument is null.
    The length of the argument is the result. The null indicator byte of column arguments that allow null values is not included in the length. Blanks are included in the length of strings, but the length control field of varying-length strings is not included in the length. The actual (not the maximum) length of varying-length strings is the length.
    The length is the number of bytes used to represent the value as follows:
    • Character string: length of the string
    • Small integer: 2
    • Large integer: 4
    • Floating-point: 8
    • Decimal numbers with precision p: INTEGER(p/2) + 1
    • Date: 4
    • Time: 3
    • Timestamp: 10
    • Numeric numbers with precision p: p
    For example, if COLX is a VARCHAR(20) column, LENGTH(COLX) returns the actual length of the string in that column.
  • MICROSECOND
    Use the MICROSECOND function to obtain the microsecond part of a value. The result is an integer representing a number of microseconds. The sign of the result is always positive. Its argument must be a timestamp.
    For example, if TIME1 is 19890320093020109000 then, MICROSECOND(TIME1) results in 109000 microseconds.
  • MINUTE
    Use the MINUTE function to obtain the minute part of a value. The result is an integer representing a minute. The sign of the result is negative only if the value of its argument is a negative duration. Its argument must be a time, timestamp, or a DECIMAL(6,0) number interpreted as a time-duration.
    For example, if TIME1 is a timestamp of 19890203093020009900, then MINUTE(TIME1) results in 30.
  • MOD
    Use the MOD function to obtain the remainder after dividing two numeric values. If one argument is null, the result is a null value. For example, MOD(13,4) results in 1. The arguments must be any built-in numeric data types, except FLOAT.
    The data type of the result is based on the data types of the arguments as follows:
    • If both arguments are large or small integers, the data type of the result is a large integer.
    • If one argument is an integer and the other is a decimal, the data type of the result is decimal.
    • If both arguments are decimal, the result is decimal. The precision of the result is min(p-s,p'-s') + max(s,s'), and the results scale is MAX(s,s'), where p and s denote the precision and scale of the first argument, and the symbols p' and s' denote the precision and scale of the second argument.
      The sign of the result is the same as the sign of the dividend.
  • MONTH
    Use the MONTH function to obtain the month part of a value. The result is an integer representing a month. The sign of the result is negative only if the value of its expression is a negative duration. Its argument must be a date, timestamp, or DECIMAL(8,0) number interpreted as a date-duration.
    For example, if BIRTHDATE is of March 25, 1945, that is to say, 19450325, then MONTH(BIRTHDATE) results in 3.
  • SECOND
    Use the SECOND function to obtain the seconds part of a value. The result is an integer representing a second. The sign of the result is negative only if the value of its argument is a negative duration. Its argument must be a time, timestamp, or a DECIMAL(6,0) number interpreted as a time-duration.
    For example, if TIME1 is a timestamp of 19890203093020009900, then SECOND(TIME1) results in 20.
  • SUBSTR
    Use the SUBSTR function to obtain a substring of a string. Three arguments are possible: string, start, and length. The string and start arguments are required, but the length argument is optional. The result can be null if any of the arguments can be null. The result is the null value if any of the arguments are null.

    Note: The SUBSTR function accepts mixed data strings. However, because SUBSTR operates on a strict byte-count basis with character strings, the result is not necessarily a properly formed mixed data string.

    DBCS characters can be used in either GRAPHIC or CHAR with MIXED DATA. When GRAPHIC is used, there is no problem because there are no shift-out or shift-in bytes, and start and length refer to double-byte characters (not bytes). However, be aware that in CHAR MIXED DATA, the shift-out and shift-in may not balance in the result string.
    You can use the VARGRAPHIC scalar function to normalize data before doing comparisons.

    • string
      Refers to an expression specifying the string from which the result is derived. The string must be a character string or a graphic string. If string is a character string, the result of the function is a character string. If it is a graphic string, the result of the function is a graphic string.
      A substring of the string argument is 0 or more contiguous characters of the string argument.
    • ,start
      Refers to an expression specifying the position of the first character of the result. The start argument must be a positive binary integer that is not greater than the length attribute of the string argument. Note that the length attribute of a varying-length string is its maximum length.
    • ,length
      Refers to an expression specifying the length of the result. If you specify the length argument, it must be a binary integer in the range of 0-n, where n is the length attribute of the string argument minus the start argument plus 1, with the exception that n must not be the integer constant 0.
      If you explicitly specify the length argument, the string argument is effectively padded on the right with the necessary number of blank characters so that the specified substring of the string argument always exists. The length argument has a default of the number of characters from the character specified by the start argument to the last character of the string argument, but if the string argument is a varying-length string with a length that is less than the start argument, the default is 0 and the result is the empty string.
      If you explicitly specify the length argument to be an integer constant of less than 255, the result is a fixed-length string. If you do not explicitly specify the length argument but the string argument is a fixed-length string and the start argument is an integer constant, the result is a fixed-length string. In all other cases, the result is a varying-length string with a maximum length that is the same as the length attribute of the string argument.
      If the string argument is a fixed-length string, omitting the length argument is an implicit specification of
      LENGTH(string) - start + 1
      If the string argument is a varying-length string, omitting the length argument is an implicit specification of either
      LENGTH(string) - start + 1
      or 0, whichever is greater.
    For example, if FIRSTNAME is a VARCHAR(20) column, SUBSTR(FIRSTNAME,1,1) results in a fixed-length string value containing the first character of the value in FIRSTNAME.
  • TIME
    Use the TIME function to obtain the time from a value. The result is a time. Its argument must be a time, timestamp, a string representation of a time. For example if TIME1 is 10890320093020, then TIME(TIME1) results in time 9.30.20 (in ISO or EUR format).
  • TIMESTAMP
    Use the TIMESTAMP function to obtain a timestamp from a value or a pair of values. The result is a timestamp. If only one argument is given, it must be a timestamp, a string representation of a timestamp, a character string of length 8, or a character string of length 14. If the value is a character string of length 8, it is assumed to be a STORE CLOCK value representation of a timestamp. If the value is a character string of length 14, it must be in the form yyyymmddhhmmss where yyyy is the year, mm the month, dd the day, hh the hours, mm the minutes, and ss the seconds.
    If a second optional argument is specified, the second argument must be a time or a string representation of a time, and the first argument must be a date or a string representation of a date.
    For example, TIMESTAMP(CURRENT DATE, '11.30.00') results in the timestamp 11:30 today.
  • VALUE
    Use the VALUE function to substitute a value for the null value. The arguments' data types must be compatible. Because character strings are not converted to date/time values, all arguments must be dates if any argument is a date. Similarly, all arguments must be times if any argument is a time, all must be timestamps if any are timestamps, and all must be character strings if any are character strings.
    Arguments are evaluated in the order of specification. The result of the function is equal to the first argument that is not null. The result can only be null if all arguments can be null. The result is the null value only if all arguments are null.
    The result is defined as equal to an argument because that argument is converted or extended, if necessary, in order to conform to the data type of the function. The data type of the result is derived from the data types of the specified arguments as follows:
    • strings:
      If any argument is a varying-length string, the result is a varying-length string whose maximum length is equal to the longest string that can result from the application of the function.
      If all arguments are fixed-length strings, the result is a fixed-length string whose length is equal to the longest string that can result from the application of the function.
    • date/time values:
      The result is a date if the arguments are dates, times if the arguments are times, or timestamps if the arguments are timestamps.
    • numbers:
      If the arguments are numbers, the result is the numeric data type that would occur if all arguments were part of a single arithmetic expression. If that data type is decimal, it has a precision of p and a scale of s. Therefore, s is the largest result scale of any argument and p is the minimum of 31 and s + n, where n is the largest integral part result of any argument. Conversion errors are possible if the sum of s + n is greater than 31.
    For example, SALARY + VALUE(COMMISSION,0) results in the sum of SALARY and COMMISSION if COMMISSION is not the null value, or the sum of SALARY and 0 if COMMISSION contains the null value.
  • VARGRAPHIC
    Use the VARGRAPHIC function to convert SBCS (Single-Byte Character Set) and MIXED strings to VARGRAPHIC.
    In SQL, string comparisons are strictly byte-for-byte, so predicates involving MIXED strings may not give the desired results. For instance, a string with the SBCS version of XYZ does not compare as equal to a string with a Shift-Out, then the DBCS version of XYZ, then a Shift-In. You can use the VARGRAPHIC scalar function to normalize both strings into VARGRAPHIC data types before doing the comparison.
    When SBCS strings are converted, each SBCS character is paired with a X'42' to form the double-byte character. In MIXED strings, the SBCS characters are converted, and Shift-In and Shift-Out characters are removed. FOR BIT DATA operands are not allowed.
  • YEAR
    Use the YEAR function to obtain the year part of a value. The result is an integer representing a year. The sign of the result is negative only if the value of its expression is a negative duration. Its argument must be a date, timestamp, or DECIMAL(8,0) number interpreted as a date-duration.
    For example, if BIRTHDATE is March 25, 1945, that is to say, 19450325, then YEAR(BIRTHDATE) results in 1945.

Character Functions

Following is the syntax diagram for character-level scalar functions:

►►─┬─── INSERT (insert_operands) ────────────────────────────────┬─────►◄

   ├─── LOCATE (locate_operands) ────────────────────────────────┤

   ├─── LOCATE_IN_STRING (locate_in_string_operands) ────────────┤

   ├─┬─ LOWER ─────┬─ (expression) ──────────────────────────────┤
   │ └─ LOWERCASE ─┘                                             │
   ├─ LTRIM(expression) ─────────────────────────────────────────┤
   ├─ POSITION (position_operands) ──────────────────────────────┤ 

   ├─ POSSTR(posstr_operands) ───────────────────────────────────┤

   ├─ REPLACE (replace_operands) ────────────────────────────────┤

   ├─ RTRIM(expression) ─────────────────────────────────────────┤
   ├─ SQUEEZE(expression) ───────────────────────────────────────┤

   ├─ STRIP (strip_operands) ────────────────────────────────────┤
   ├─ TRIM (trim_operands) ──────────────────────────────────────┤ 

   └─┬─ UPPER ─────┬─ (expression) ──────────────────────────────┘
     └─ UPPERCASE ─┘   

  • INSERT (insert_operands)

    The INSERT character function returns a NULLable VARCHAR value where insert_string has been inserted, beginning at start and length characters have been deleted, in source_string.   

    If the source_string parameter is NULL, the result is NULL. Search_string and source_string must be CHAR or VARCHAR. Start and length must be INTEGER or SMALL INT. The units parameter is strictly for compatibility.

    The insert_operands are as follows:

    ►►─ INSERT(source_string, start, length,insert_string ─────────┬─ ) ─────►◄
                                                           ├─ , CHARACTERS ─┤ 

                                                           └─ OCTETS ─┘

    • source_string
      This parameter specifies the source string.
    • start
      This parameter specifies the starting position where the deletion of bytes and insertion of another string within source_string +1. Start must be 1 to the length of source_string.
    • length
      This parameter specifies the number of bytes to be cleared, beginning at start.
    • insert_string
      This parameter specifies the input string to be inserted at start in source_string.
    • CHARACTERS or OCTETS
      Both keywords specify the result position is in bytes. The default position is also in bytes, so these keywords are only for compatibility.

    Following is an example of using the INSERT function:

    SELECT INSERT(state, 3, 7, 'xas', OCTETS) FROM customer_names

    • Given state 
      'Tennessee'
    • Resulting output is 
      'Texas'
  • LOCATE (locate_operands)   

    The LOCATE character function returns the starting position in bytes of the first occurrence of the search_string within the source_string. The search is case-sensitive.  

    If either parameter is NULL, the result is NULL. If the search_string is found, the result is a number from 1 to the actual length of the source_string. If the search_string is not found the result is 0.   
    If the search_string is zero length varchar, the result is 1, (even when source_string is zero length varchar). If the source_string is zero length varchar (and search_string is not zero length varchar), the result is zero.   
    Search_string and source_string must be CHAR or VARCHAR. The units parameter is strictly for compatibility.  

The locate_operands are as follows:

►►─ LOCATE_IN_STRING (search_string, source_string ─┬──►

                                                    └─ start ─┘

─────────┬─ ) ─────►◄
   ├─ , CHARACTERS ─┤ 
   └─ OCTETS ─┘

    • search_string  
      This parameter specifies the string for which to search in the source_string.  
    • source_string,  
      This parameter specifies the input string to be searched.
    • start  
      This parameter specifies the starting position of the search. The default position is 1. A value of zero is considered a value of 1.  
    • CHARACTERS or OCTETS  
      Both keywords specify the result position is in bytes. The default position is also in bytes, so these keywords are only for compatibility.  

Following is an example of using the LOCATE function:

SELECT LOCATE('n', state, 4, OCTETS) FROM customer_names

      • Given state
        'Indiana '
      • Resulting output is
        6

  • LOCATE_IN_STRING (locate_in_string_operands)  
    The LOCATE_IN_STRING character function returns the starting position in bytes of the instance occurrence of the search_string within the source_string. The search is case-sensitive.  
    If either parameter is NULL, the result is NULL. If the search_string is found, the result is a number from 1 to the actual length of the source_string. If the search_string is not found the result is 0.   
    When start is negative, the search begins start bytes from the end of the source_string, and the search is backwards.  
    If the search_string is zero length varchar, the result is 1, (even when source_string is zero length varchar). If the source_string is zero length varchar (and search_string is not zero length varchar), the result is zero.   
    Search_string and source_string must be CHAR or VARCHAR. The units parameter is strictly for compatibility.  
    The locate_operands are as follows:

►►─ LOCATE_IN_STRING(source_string, search_string ─┬──────────┬─ ) ─────►◄
                                                   └─ start ─┘  ├─ , CHARACTERS ─┤ 

                                                               └─ , instance ─┘    └─ OCTETS ─┘

    • source_string,
      This parameter specifies the input string to be searched.
    • search_string
      This parameter specifies the string to search for in the source_string.
    • start
      This parameter specifies the starting position of the search. The default position is 1. A negative value specifies the postition to start from the end of the string, and the search is backwards. For example, -1 starts at the end of the string, and -length(source_string) starts with the first byte of the string. A value of zero is invalid.
    • instance
      This parameter specifies the instance of the search_string to be found.
    • CHARACTERS or OCTETS
      Both keywords specify the result position is in bytes. The default position is also in bytes, so these keywords are only for compatibility.

Following is an example of using the LOCATE_IN_STRING function:

SELECT LOCATE_IN_STRING(state, 'n', 1, 2), LOCATE_IN_STRING(state, 'n', -1, 2) FROM customer_names

    • Given state  
      'Indiana '
    • Resulting output is  
      6, 2
  • LOWER(expression) or LOWERCASE(expression)  
    This character function returns a copy of the result of the input expression that has been converted to lowercase characters. The input expression must resolve to the character data type and cannot consist of bit, mixed, or Katakana data. Bit and mixed data are rejected. Katakana data is processed, producing an unpredictable result string. The data type, length, and nullability of the result matches that of the input. 
    Following is an example of using the LOWER scalar function:

 SELECT LOWER(last_name) FROM customer_names

      • Given input of
        ' Smith '
      • Resulting output is
        ' smith '
  • LTRIM(expression)
    This character function returns a copy of the result of the input expression that has had leading blanks removed. The input expression must resolve to the character data type and may not consist of bit or mixed data. Katakana strings are processed as if they were EBCDIC. The result is VARCHAR with nullability matching that of the input. The length of the result is the trimmed (shortened) length.
    Following is an example of using the LTRIM scalar function:

     SELECT LTRIM(last_name) FROM customer_names

      • Given input of
        ' Smith '
      • Resulting output is
        'Smith '
  • POSITION(position_operands)

    The POSITION character function returns the starting position in bytes of the first occurrence of the search_string within the source_string. The search is case-sensitive.

    If the search_string is not found and neither argument is null, the result is 0. If the search_string is found, the result is a number from 1 to the actual length of the source_string. If either parameter is NULL, the result is NULL. Search_string and source_string must be CHAR or VARCHAR.

    The position_operands are as follows:

    ►►─ POSITION(search_string, source_string, OCTETS) ───────────────────────►◄

    • source_string,
      This parameter specifies the input string to be searched.
    • search_string
      This parameter specifies the string for which to search in the source_string.
    • OCTETS
      Required keyword that specifies the result position is in bytes.

    Following is an example of using the POSSTR function:

    SELECT POSITION('th', last_name, OCTETS) FROM customer_names

    • Given input of
      'Smith '
    • Resulting output is
      4
  • POSSTR(posstr_operands)

    The POSSTR character function returns the starting position of the first occurrence of the search_string within the source_string. The search is case-sensitive.

    If the search_string is not found and neither argument is null, the result is 0. If the search_string is found, the result is a number from 1 to the actual length of the source_string. If either parameter is NULL, the result is NULL. The parameters must be CHAR or VARCHAR.

    The posstr_operands are as follows:

    ►►─ POSSTR(source_string, search_string) ───────────────────────►◄

    source_string,

    This parameter specifies the input string to be searched.

    • search_string
      This parameter specifies the string for which to search in the source_string.
      Following is an example of using the POSSTR function:

      SELECT POSSTR(last_name, 'th') FROM customer_names

    • Given input of
      'Smith '
    • Resulting output is
      4
  • REPLACE(replace_operands)  
    The REPLACE character function replaces all occurrences of the search_string within the source_string with the replacement_string.The is function is case-sensitive. 
    The result is always VARCHAR with a maximum length of 4000 if the length of the source_string is less than 4000, or 32720 if the source_string is longer than 4000.  
    If any parameter is NULL, the result will be NULL. If the replacement_string is empty, the search_string is deleted.  
    If the replacement_string is too long to fit in the source_string, an SQLCODE -320 error is issued with the message: REPLACE FUNCTION RESULT STRING IS TOO LONG. The parameters must be CHAR or VARCHAR. The replace_operands are as follows:

►►─ REPLACE(source_string, search_string, replacement string) ───────────►◄

source_string,

This parameter specifies the input string to be searched.

    • search_string,
      This parameter specifies the string expression for which to search in the source_string.
    • replacement_string
      This parameter specifies the string expression that replaces the search_string.
      Following is an example of using the REPLACE function:

      SELECT REPLACE(last_name, 'Sm', 'Ke') FROM customer_names

      • Given input of
        'Smith '
      • Resulting output is
        'Keith '
  • RTRIM(expression)
    This character function returns a copy of the result of the input expression that has had trailing blanks removed. The input expression must resolve to the character data type and cannot consist of bit or mixed data. Katakana strings are processed as if they were EBCDIC. The result is VARCHAR with nullability matching that of the input. The length of the result is the trimmed (shortened) length.
    Following is an example of using the RTRIM scalar function:

     SELECT RTRIM(last_name) FROM customer_names

    • Given input of
      ' Smith '
    • Resulting output is
      ' Smith'
  • SQUEEZE(expression)
    This character function returns a copy of the result of the input expression that has had both leading and trailing white space (blanks, nulls, new lines (line feeds), carriage returns, horizontal tabs and form feeds (vertical tabs)) removed and has had any embedded white space converted to blanks. The input expression must resolve to the variable-length character (VARCHAR) data type and cannot consist of bit or mixed data. Katakana strings are processed as if they were EBCDIC. The data type and nullability of the result matches that of the input. The length of the result is the squeezed length.
    Following is an example of using the SQUEEZE scalar function:

     SELECT SQUEEZE(last_name) FROM customer_names

    • Given input of
      ' Smith '
    • Resulting output is
      'Smith'
  • STRIP(strip_operands)  
    The STRIP character function, provided for Db2 syntax compatibility, operates identically to the TRIM function described above in that STRIP removes extraneous characters from the start and/or end of a character string. For details, see the previously given TRIM description.

►►─ strip-source_expression ─┬──────────────────────────────────┬─────────────►◄
                             └─ , l_t_b ─┬────────────────────┬─┘
                                         └─ , strip-char_exp ─┘

    • strip-source_expression  
      This parameter supplies the input string to be operated upon.
      • l_t_b
        This parameter specifies where to remove unwanted characters.
        Specify LEADING or L if you want to remove unwanted characters from the start of the input source string.
        Specify TRAILING or T if you want to remove unwanted characters from the end of the input source string.
        Specify BOTH or B if you want to remove unwanted characters from both the start and the end of the input source string. The default is BOTH.
      • , strip-char_exp
        This strip character expression parameter specifies the character to be removed. The default is the blank character.

Following is an example of using the STRIP function:

 SELECT STRIP(last_name, BOTH, ' ') FROM customer_names

    • Given input of
      ' Smith '
    • Resulting output is
      'Smith'
  • TRIM(trim_operands)
    The TRIM character function removes extraneous characters from the start and/or end of a character string. The trim-source_expression must resolve to a CHAR, VARCHAR, or GRAPHIC data type and must be compatible with the data type of the trim-char_expression as shown in the following description. Katakana strings are processed as if they were EBCDIC. For CHAR and VARCHAR input, the result is VARCHAR. For GRAPHIC input, the result is VARGRAPHIC. Nullability of the result matches that of the input. The length of the result is the trimmed (shortened) length

►►─┬─────────────────────────────────────────┬─ trim-source_expression ───────►◄
   └─┬─────────┬─┬─────────────────┬ ─ FROM ─┘
     └─ l_t_b ─┘ └─ trim-char_exp ─┘

    • l_t_b  
      This parameter specifies where to remove unwanted characters.  
      Specify LEADING or L if you want to remove unwanted characters from the start of the input source string.  
      Specify TRAILING or T if you want to remove unwanted characters from the end of the input source string.  
      Specify BOTH or B if you want to remove unwanted characters from both the start and the end of the input source string. The default is BOTH.
    • trim-char_exp
      This trim character expression parameter specifies the character to be removed. The default is the blank character.
    • trim-source_expression
      This parameter supplies the input string to be operated upon.

Following is an example of using the TRIM function:

 SELECT TRIM(BOTH ' ' FROM last_name) FROM customer_names

    • Given input of
      ' Smith '
    • Resulting output is
      'Smith'
  • UPPER(expression) or UPPERCASE(expression)
    This character function returns a copy of the result of the input expression that has been converted to uppercase characters. The input expression must resolve to the character data type and cannot consist of bit, mixed, or Katakana data. Bit and mixed data are rejected. Katakana data is processed, producing an unpredictable result string. The data type, length, and nullability of the result matches that of the input.
    Following is an example of using the UPPER scalar function:

     SELECT UPPER(last_name) FROM customer_names

      • Given input of
        ' Smith '
      • Resulting output is
        ' SMITH '

Bit-Level Functions

Following is the syntax diagram for bit-level scalar functions:

►►─┬─ BIT_ADD(expression, expression) ─┬──────────────────────────────────────►◄
   ├─ BIT_AND(expression, expression) ─┤
   ├─ BIT_NOT(expression) ─────────────┤
   ├─ BIT_OR(expression, expression) ──┤
   └─ BIT_XOR(expression, expression) ─┘

The following rules define the input and output of each bit-level function, that is to say, all of these rules apply to every function.

    • The expression that represents each parameter must resolve to INTEGER, SMALLINT, CHAR, or VARCHAR data. In this case, CA Datacom® operates on character values of any length and rejects input parameters containing mixed data (mixed single-byte/double-byte). Though not required, we recommend using the FOR BIT DATA specification in the CREATE TABLE statement for columns that are going to use bit-level functions.
    • For functions that receive two parameters, character and numeric parameters cannot be used in the same function call (numeric means INTEGER or SMALLINT in this context).
    • The data type, length, and nullability of the result matches that of the input if there is either only one parameter or all parameters are of identical data type, length, and nullability. The attributes of the result are otherwise determined as follows:
      • The result is nullable (that is, it is not NOT NULL) if either of the parameters are nullable.
      • The length of the result matches the length of the longer parameter.
      • If both parameters are numeric, the result is INTEGER if at least one of the parameters is INTEGER, or SMALLINT if neither of the parameters is INTEGER.
      • If both parameters are character (VARCHAR is character) the data type of the result matches that of the first operand. This allows you to control the data type of the result when the data types of the parameters differ.
    • BIT_ADD(expression, expression)
      This bit-level function returns the logical sum of the results of the input expressions. The logical sum is obtained by using logical addition and discarding any arithmetic overflow that is generated.
      Following is an example of using BIT_ADD to construct a web address for a computer that is being turned on.

      SELECT BIT_ADD(web_addrs_company_prefix,web_addrs_assigned_suffix) FROM web_addrses

      • Given input of
        A web_addrs_company_prefix of 127.255.0.0 as an integer representation or 0x7FFF0000 in C-style notation and a web_addrs_assigned_suffix of 0.0.255.254 as an integer representation or 0x0000FFEE in C-style notation
      • Resulting output is
        An integer representation of 127.255.255.254 or 0x7FFFFFFE in C-style notation
    • BIT_AND(expression, expression)
      This bit-level function returns the logical AND of the results of the input expressions consisting of a (1) bit in the result for every input bit-pair of (1,1) and a (0) bit for all other bit-pair value combinations.

      Note: A single 1 or 0 digit inside parentheses, that is a (1) or a (0), is used here to represent a single bit value. The term bit-pair refers to the value of a bit taken from the first input parameter and that of a bit taken from the corresponding position in the second input parameter. For example, a bit-pair of (1,0) refers to a 1 bit somewhere in the first parameter and a 0 bit in the corresponding position of the second parameter.

      Following is an example of using BIT_AND to find what area of the web a browser is pointed to (that is, get the high-level portion of the web address).

      SELECT BIT_AND(:bits_to_extract, web_addrs), user_name FROM web_addrses

      • Given input of
        A bits_to_extract of 127.255.0.0 as an integer representation or 0x7FFF0000 in C-style notation, used to denote the bits you want to extract from the web address (here, bits_to_extract has a colon (:) in front of it to show it can be a host variable from a theoretical user program) and a web_addrs of 127.255.1.1 as an integer representation or 0x7FFF0101 in C-style notation
      • Resulting output is
        An integer representation of 127.255.0.0 or 0x7FFF0000 in C-style notation
    • BIT_NOT(expression)
      This bit-level function returns the logical NOT (the complement) of the results of the input expression. Each (1) bit in the input parameter becomes a (0) bit in the result, and each (0) bit becomes a (1) bit.

      Note: A single 1 or 0 digit inside parentheses, that is a (1) or a (0), is used here to represent a single bit value.

      Following is an example of using BIT_NOT to find out which status flags are not set.

       SELECT BIT_NOT(status_bits) from system_status

      • Given input of
        A status_bits of 0x7F010101 in C-style notation
      • Resulting output is
        0x80FEFEFE in C-style notation
    • BIT_OR(expression, expression)
      This bit-level function returns the logical OR of the results of the input expressions. Each input bit-pair of (0,0) becomes a (0) bit in the result, and all other bit-pair value combinations become (1) bits.

      Note: A single 1 or 0 digit inside parentheses, that is a (1) or a (0), is used here to represent a single bit value. The term bit-pair refers to the value of a bit taken from the first input parameter and that of a bit taken from the corresponding position in the second input parameter. For example, a bit-pair of (1,0) refers to a 1 bit somewhere in the first parameter and a 0 bit in the corresponding position of the second parameter.

      Following is an example of using BIT_OR to construct a web address for a computer being turned on.

      SELECT BIT_OR(web_addrs_company_prefix, web_addrs_assigned_suffix) from web_addrses

      • Given input of
        A web_addrs_company_prefix of 127.255.0.0 in an integer representation or 0x7FFF0000 in C-style notation and a web_addrs_assigned_suffix of 0.0.255.254 in an integer representation or 0x0000FFFE in C-style notation
      • Resulting output is
        An integer representation of 127.255.255.254 or 0x7FFFFFFE in C-style notation.
    • BIT_XOR(expression, expression)
      This bit-level function returns the logical exclusive-OR of the results of the input expressions. Each bit-pair containing exactly one (1) bit becomes a (1) bit in the result. That is to say, each input bit-pair of (0,1) or (1,0) becomes a (1) bit in the result, and all other bit-pair value combinations, (0,0) or (1,1), become (0) bits.

      Note: A single 1 or 0 digit inside parentheses, that is a (1) or a (0), is used here to represent a single bit value. The term bit-pair refers to the value of a bit taken from the first input parameter and that of a bit taken from the corresponding position in the second input parameter. For example, a bit-pair of (1,0) refers to a 1 bit somewhere in the first parameter and a 0 bit in the corresponding position of the second parameter.

      Following is an example of using BIT_XOR to find out which system status flags do not match a required value.

       SELECT BIT_XOR(status_bits, required_status_bits) from system_status

      • Given input of
        A status_bits of 0x7F010101 in C-style notation and a required_status_bits of 0x7F111110 in C-style notation
      • Resulting output is:
        0x00101011 in C-style notation, giving the bits that do not match

Byte-Level Function

Following is the syntax diagram for byte-level scalar functions:

►►─ INTEXTRACT(expression, expression) ───────────────────────────────────────►◄

    • INTEXTRACT(expression, expression)
      This byte-level function is used to extract the binary value of a single byte of a data value. The function returns an INTEGER result, hence the name INTEXTRACT (integer extract). The first parameter, meaning the first expression in INTEXTRACT(expression, expression), supplies the data value, and the second parameter (the second expression) specifies which byte is wanted.
      For example, if variable web_addrs in a C-language program contains the value (in C-style notation) 0x11223344, then INTEXTRACT(web_addrs, 2) returns the value 0x22 in C-style notation or 34 in decimal-style notation, extracted from the second byte from the high-order (left-hand) side of the value, returning an INTEGER result.
      • The first expression
        Representing the first parameter must resolve to INTEGER, SMALLINT, CHAR (non-mixed data only, that is to say, mixed DBCS/SBCS only), or VARCHAR (non-mixed data only). The length of the first parameter is limited only to the SQL-imposed limits for each data type. Though not required, we recommend use of the FOR BIT DATA specification in the CREATE TABLE statement for columns that are going to use byte-level functions.
      • The second expression
        Representing the second parameter must resolve to INTEGER or SMALLINT data.

      Following is an example of using INTEXTRACT to get a single node of a web address:

       SELECT INTEXTRACT(web_addrs, 2) FROM web_addresses

      • Given input of
        A web_addrs of 0x11223344 in C-style notation.
      • Resulting output is
        An integer containing 0x00000022 in C-style notation or 34 in decimal-style notation.

XML Functions

The Extensible Markup Language (XML) functions described in the following sections allow you to externalize relational data as XML data. The CA Datacom®/DB implementation of XML includes support for the following XML functions:

    • XMLELEMENT (see the following description)
    • XMLATTRIBUTES (valid within use of XMLELEMENT only)
    • XMLFOREST (see XMLFOREST)
    • XMLSERIALIZE (see XMLSERIALIZE)
    • XMLCONCAT (see XMLCONCAT)

The XMLELEMENT, XMLATTRIBUTES, XMLFOREST, and XMLCONCAT functions operate on relational or XML data to produce XML output. The XMLSERIALIZE function is an ANSI-compliant method for returning XML values into user applications that expect string result types such as VARCHAR. An XML value is defined as a well-formed XML document or a document fragment consisting of well-formed XML content.

Descriptions of Functions

Following are descriptions of the supported XML functions.

XMLELEMENT

This function builds and returns an XML value given the following:

    • An XML element name,
    • An optional list of XML attributes, and
    • An optional list of values as the content of the new element.
Note: The XML namespace declaration is not supported.

XMLATTRIBUTES

This function builds a list of attributes to be included in the XML element generated by the XMLELEMENT function. XMLATTRIBUTES is valid only within an XMLELEMENT function.

Following is the syntax diagram for XMLELEMENT and XMLATTRIBUTE:

►►─ XMLELEMENT ─ (NAME ─ identifier ──────────────────────────────────────────►

 ►─┬───────────────────────────────────────────────┬──────────────────────────►
   │                      ┌─ , ─────────────┐      │
   └─ ,XMLATTRIBUTES ─ ( ─▼─ xml-attribute ─┴ ─ ) ─┘

   ┌─────────────────────────┐
 ►─▼─┬─────────────────────┬─┴─┬───────────────────────────────┬─ ) ──────────►◄
     └─ ,value-expression ─┘   └─ OPTION ─ xml-content-option ─┘

Expansion of Where xml-attribute is as follows

├── value-expression ─┬───────────────────┬────────────────────────────────────┤
                      └─ AS ─ identifier ─┘

Expansion of Where xml-content-option is as follows

├──┬─ EMPTY ON NULL ◄ ───┬─────────────────────────────────────────────────────┤
   ├─ NULL ON NULL ──────┤
   ├─ ABSENT ON NULL ────┤
   ├─ NIL ON NULL ───────┤
   └─ NIL ON NO CONTENT ─┘

The xml-content-option defines the XML value that is produced when the value-expression list, representing the content of the element, is either missing or evaluates entirely to NULLs. If no content is supplied, then any supplied ON NO CONTENT specification is applied. If content is supplied but every supplied item evaluates to NULL, the ON NULL option applies. In the XMLELEMENT function, EMPTY ON NULL is the default. In XMLFOREST, NULL ON NULL is the default. In all other cases, an element is generated using whatever non-NULL values were supplied.

    • NULL ON NULL
      Produces a NULL rather than an element.
    • EMPTY ON NULL
      Produces an element with no content (subject to change or removal).
    • ABSENT ON NULL
      Produces a zero-length result (subject to change or removal).
    • NIL ON NULL and NIL ON NO CONTENT
      Produce elements with no content but containing attributes that read "nil=true" when serialized.

The following example produces a Customer element for each customer, with customer number and name attributes:

SELECT XMLSERIALIZE(CONTENT

                     XMLELEMENT(NAME "Customer",

                                XMLATTRIBUTES(CustNo,

                                              SurName as LastName,

                                              FirstName)

                               )

                    AS VARCHAR(200)) AS "CustomerList"

  FROM customers;

Note: The XMLSERIALIZE function (see XMLSERIALIZE) converts the XML output of XMLELEMENT to VARCHAR in this example.

The result of the previous example follows:

CustomerList

VARCHAR(200)

---------------------------------------------------------------------------------

<-Customer CustNo="000001" LastName="Sturlasson" FirstName="Snorri"><-/Customer>

<-Customer CustNo="000002" LastName="Skallagrimsson" FirstName="Eigil"><-/Customer>

---------------------------------------------------------------------------------

XMLFOREST

This function returns an XML value consisting of a forest, or collection, of XML elements, given a list of "forest elements." Each forest element generates an XML element using the referenced column name or, if provided, the forest element name (the identifier in the syntax diagram that follows) as the XML element name and the forest element value (the value expression in the following diagram) as the element content.

Following is the syntax diagram for XMLFOREST:

                   ┌─ , ──────────────┐
├── XMLFOREST ─ ( ─▼─ forest-element ─┴───────────────────────────────────────►

 ►─┬───────────────────────────────┬─ ) ───────────────────────────────────────┤
   └─ OPTION ─ xml-content-option ─┘

Expansion of Where forest-element is as follows

├── value-expression ─┬───────────────────┬────────────────────────────────────┤
                      └─ AS ─ identifier ─┘

Expansion of Where xml-content-option is as follows

├──┬─ NULL ON NULL ◄ ────┬─────────────────────────────────────────────────────┤
   ├─ EMPTY ON NULL ─────┤
   ├─ ABSENT ON NULL ────┤
   ├─ NIL ON NULL ───────┤
   └─ NIL ON NO CONTENT ─┘

The xml-content-option in the XMLFOREST function is applied separately to each forest-element. In XMLFOREST, EMPTY ON NULL is the default. For a further description of the xml-content-option, see the paragraph following the XMLELEMENT syntax diagram in XMLATTRIBUTES.

The following example generates a "Vendor" element for each vendor. The name of the vendor is used as an attribute, and two sub-elements are created from columns contactName and contactPhone using the XMLFOREST function.

SELECT vendorId,
       XMLSERIALIZE(CONTENT
                    XMLELEMENT(NAME "Vendor",
                               XMLATTRIBUTES(v.vendorDBA AS DBA),
                               XMLFOREST (v.contactName,
                                          v.contactPhone AS phone)
                              )
                    AS VARCHAR(300)) AS "vendorContacts"
  FROM vendors v;

The result of the previous example follows:

vendorId  vendorContacts
INTEGER   VARCHAR(300)
--------  ---------------------------------------------
       1  <-Vendor DBA="Best Office Supplies">
              <-contactName>Joeseph Dudely<-/contactName>
              <-phone>123-456-7890<-/phone>
           <-/Vendor>
       2  <-Vendor DBA="Widgets R Us">
              <-contactName>Mary Doeright<-/contactName>
              <-phone>123-456-1313<-/phone>
          <-/Vendor>
-------------------------------------------------------

XMLSERIALIZE

This function converts an XML value into the corresponding representation in an alternative character-string data-type. XMLSERIALIZE converts XML types to string types for export to user host-variables.

Note: When XMLSERIALIZE is used to externalize floating point data, 15 is the maximum number of significant digits produced.

Following is the syntax diagram for XMLSERIALIZE:

├── XMLSERIALIZE ─ ( ─┬─ DOCUMENT ─┬─ xml-value-expression ─ AS ─ data-type ──►
                      └─ CONTENT ──┘

 ►─ ) ─────────────────────────────────────────────────────────────────────────┤

    • DOCUMENT
      Specifies that the result of the xml-value-expression is a validly formed XML document.
    • CONTENT
      Specifies well-formed XML content.
    • xml-value-expression
      Any expression whose result is an XML value, such as XMLELEMENT (see XMLELEMENT), XMLCONCAT (see XMLCONCAT), or XMLFOREST (see XMLFOREST).
    • data-type
      Must specify some character-string type. If XMLAGG or XMLTEXT is used, VARCHAR must be used.

The following example is a repetition of our XMLELEMENT example and produces a Customer element for each customer, with customer number and name attributes:

SELECT XMLSERIALIZE(CONTENT

                    XMLELEMENT(NAME "Customer",
                               XMLATTRIBUTES(CustNo,
                                             surName as LastName,
                                             FirstName)
                              )
                    AS VARCHAR(200)) AS "CustomerList"
  FROM customers

The result of the previous example follows:

CustomerList
VARCHAR(200)
---------------------------------------------------------------------------------

<-Customer CustNo="000001" LastName="Sturlasson" FirstName="Snorri"><-/Customer>
<-Customer CustNo="000002" LastName="Skallagrimsson" FirstName="Eigil"><-/Customer>
---------------------------------------------------------------------------------

XMLCONCAT

This function returns an XML value that is the concatenation of a list of XML values.

Following is the syntax diagram for XMLCONCAT:

                   ┌─ , ────────────────────┐
├── XMLCONCAT ─ ( ─▼─ xml-value-expression ─┴─ ) ──────────────────────────────┤

    • xml-value-expression
      Any expression whose result is an XML value, such as XMLELEMENT (see XMLELEMENT), XMLCONCAT (see XMLCONCAT), or XMLFOREST (see XMLFOREST).

The following example (a repetition of the XMLELEMENT example) produces a Customer element for each customer, with customer number and name attributes:

SELECT XMLSERIALIZE(CONTENT
                    XMLCONCAT(XMLELEMENT(NAME "contact',v.contactName),
                              XMLELEMENT(NAME "phone",v.contactPhone)
                             )
                    AS VARCHAR(300)) AS "vendorContacts"
  FROM vendors v;

The result of the previous example follows:

vendorContacts
VARCHAR(300)
------------------------------------------------------------

<-contact>Joeseph Dudely<-/contact><-phone>123-456-7890<-/phone>
<-contact>Mary Doeright<-/contact><-phone>123-456-1313<-/phone>
------------------------------------------------------------

Was this helpful?

Please log in to post comments.