Unicode Data and Server Code Pages

Extended Stored Procedure Programming

Extended Stored Procedure Programming

Unicode Data and Server Code Pages

Open Data Services APIs are enabled for Unicode data; however, they are not enabled for Unicode meta data. The #define Unicode directive does not have any effect on the Open Data Services API.

All meta data returned by, or provided to Open Data Services by your Open Data Services application is assumed to be in the multibyte code page of the server. The default code page of an Open Data Services server application is the ANSI code page of the computer on which the application is running, which can be obtained by calling srv_pfield with the field parameter set to SRV_SPROC_CODEPAGE.

If your Open Data Services application is Unicode-enabled, you must convert your Unicode meta data column names, error messages, and so on to multibyte data before passing this data to the Open Data Services API.

Example

The following extended stored procedure provides an example of the Unicode conversions discussed. Note that:

  • Column data is passed as Unicode data to srv_describe because the column is described to be SRVNVARCHAR.

  • Column name meta data is passed to srv_describe as multibyte data.

    The extended stored procedure calls srv_pfield with the field parameter set to SRV_SPROC_CODEPAGE to obtain the multibyte code page of Microsoft® SQL Server™.

  • Error messages are passed to srv_sendmsg as multibyte data.
__declspec(dllexport) RETCODE proc1 (SRV_PROC *srvproc)
{
    #define MAX_COL_NAME_LEN 25
    #define MAX_COL_DATA_LEN 50
    #define MAX_ERR_MSG_LEN 250
    #define MAX_SERVER_ERROR 20000
    #define XP_ERROR_NUMBER MAX_SERVER_ERROR+1

    int retval;
    UINT serverCodePage;
    CHAR *szServerCodePage;

    WCHAR unicodeColumnName[MAX_COL_NAME_LEN];
    CHAR multibyteColumnName[MAX_COL_NAME_LEN];

    WCHAR unicodeColumnData[MAX_COL_DATA_LEN];

    WCHAR unicodeErrorMessage[MAX_ERR_MSG_LEN];
    CHAR  multibyteErrorMessage[MAX_ERR_MSG_LEN];

    lstrcpyW (unicodeColumnName, L"column1");
    lstrcpyW (unicodeColumnData, L"column1 data");
    lstrcpyW (unicodeErrorMessage, L"No Error!");

    // Obtain server code page.
    //
    szServerCodePage = srv_pfield (srvproc, SRV_SPROC_CODEPAGE, NULL);    
    if (NULL != szServerCodePage)
        serverCodePage = atol(szServerCodePage);
    else 
    {   // Problem situation exists.
        srv_senddone(srvproc, (SRV_DONE_ERROR | SRV_DONE_MORE), 0, 0);
        return 1;
    }

    // Convert column name for Unicode to multibyte using the 
    // server code page.
    //
    retval = WideCharToMultiByte(  
        serverCodePage,                 // code page
        0,                              // default
        unicodeColumnName,              // wide-character string
        -1,                             // string is null terminated
        multibyteColumnName,            // address of buffer for new
                                        //   string
        sizeof (multibyteColumnName),   // size of buffer
        NULL, NULL);

    if (0 == retval)
    {
        lstrcpyW (unicodeErrorMessage, L"Conversion to multibyte
        failed.");
        goto Error;
    }

    retval = srv_describe (srvproc, 1, multibyteColumnName,
    SRV_NULLTERM, 
      SRVNVARCHAR, MAX_COL_DATA_LEN*sizeof(WCHAR), // destination
        SRVNVARCHAR, lstrlenW(unicodeColumnData)*sizeof(WCHAR),
        unicodeColumnData); //source
    if (FAIL == retval)
    {
        lstrcpyW (unicodeErrorMessage, L"srv_describe failed.");
        goto Error;
    }

   retval = srv_sendrow(srvproc);
    if (FAIL == retval)
    {
        lstrcpyW (unicodeErrorMessage, L"srv_sendrow failed.");
        goto Error;
    }
    
    retval = srv_senddone (srvproc, SRV_DONE_MORE|SRV_DONE_COUNT, 0, 1);
    if (FAIL == retval)
    {
        lstrcpyW (unicodeErrorMessage, L"srv_senddone failed.");
        goto Error;
    }

    return 0;
Error:
    // convert error message from Unicode to multibyte.
    retval = WideCharToMultiByte(  
        serverCodePage,                 // code page
        0,                              // default
        unicodeErrorMessage,            // wide-character string
        -1,                             // string is null terminated
        multibyteErrorMessage,          // address of buffer for new
                                        //   string
        sizeof (multibyteErrorMessage), // size of buffer
        NULL, NULL);

srv_sendmsg(srvproc, SRV_MSG_ERROR, XP_ERROR_NUMBER, SRV_INFO, 1,
            NULL, 0, __LINE__, 
            multibyteErrorMessage,
            SRV_NULLTERM);

    srv_senddone(srvproc, (SRV_DONE_ERROR | SRV_DONE_MORE), 0, 0);

    return 1;
}