/*-< CLI.H >---------------------------------------------------------*--------*
 * GigaBASE                  Version 1.0         (c) 1999  GARRET    *     ?  *
 * (Post Relational Database Management System)                      *   /\|  *
 *                                                                   *  /  \  *
 *                          Created:     13-Jan-2000 K.A. Knizhnik   * / [] \ *
 *                          Last update: 13-Jan-2000 K.A. Knizhnik   * GARRET *
 *-------------------------------------------------------------------*--------*
 * Call level interface to GigaBASE server
 *-------------------------------------------------------------------*--------*/

#ifndef __CLI_H__
#define __CLI_H__

#ifndef GIGABASE_DLL_ENTRY
#ifdef GIGABASE_DLL
#ifdef INSIDE_GIGABASE
#define GIGABASE_DLL_ENTRY __declspec(dllexport)
#else
#define GIGABASE_DLL_ENTRY __declspec(dllimport)
#endif
#else
#define GIGABASE_DLL_ENTRY
#endif
#endif

#ifdef __cplusplus
extern "C" {
#endif

enum cli_result_code {
    cli_ok = 0,
    cli_bad_address = -1,
    cli_connection_refused = -2,
    cli_database_not_found = -3,
    cli_bad_statement = -4,
    cli_parameter_not_found = -5,
    cli_unbound_parameter = -6,
    cli_column_not_found = -7,
    cli_incompatible_type = -8,
    cli_network_error = -9,
    cli_runtime_error = -10,
    cli_bad_descriptor = -11,
    cli_unsupported_type = -12,
    cli_not_found        = -13,
    cli_not_update_mode  = -14,
    cli_table_not_found  = -15,
    cli_not_all_columns_specified = -16,
    cli_not_fetched = -17, 
    cli_already_updated = -18, 
    cli_login_failed = -19
};

enum cli_var_type {
    cli_oid,
    cli_bool,
    cli_int1,
    cli_int2,
    cli_int4,
    cli_int8,
    cli_real4,
    cli_real8,
    cli_decimal, 
    cli_asciiz,   /* zero terminated string */
    cli_pasciiz,  /* pointer to zero terminated string */
    cli_cstring,  /* string with counter */
    cli_array_of_oid,
    cli_array_of_bool,
    cli_array_of_int1,
    cli_array_of_int2,
    cli_array_of_int4,
    cli_array_of_int8,
    cli_array_of_real4,
    cli_array_of_real8, 
    cli_array_of_decimal, 
    cli_array_of_string, /* array of pointers to zero terminated strings */ 
    cli_any,     /* use the same type for column as stored in the database */
    cli_datetime, /* time in seconds since 00:00:00 UTC, January 1, 1970. */
    cli_autoincrement, /* column od int4 type automatically assigned value during record insert */
    cli_unknown
};

typedef char         cli_bool_t;
typedef signed char  cli_int1_t;
typedef signed short cli_int2_t;
typedef signed int   cli_int4_t;
typedef float        cli_real4_t;
typedef double       cli_real8_t;

#ifndef __STDTP_H__
#ifdef UNICODE
typedef wchar_t char_t;
#define STRLEN(x)     wcslen(x)
#define STRCMP(x, y)  wcscmp(x, y)
#define STRCPY(x, y)  wcscpy(x, y)
#define STRNCPY(x,y,z) wcsncpy(x, y, z)
#define STRCOLL(x, y) wcscoll(x, y)
#define STRNCMP(x,y,z) wcsncmp(x, y, z)
#define STRLITERAL(x) (wchar_t*)L##x
#define PRINTF        wprintf
#define FPRINTF       fwprintf
#define SPRINTF       swprintf
#define VFPRINTF      vfwprintf
#define FSCANF        fwscanf
#define SSCANF        swscanf
#define GETC(x)       getwc(x)
#define UNGETC(x, y)  ungetwc(x, y)
#define TOLOWER(x)    towlower((x) & 0xFFFF)
#define TOUPPER(x)    towlower((x) & 0xFFFF)
#define ISALNUM(x)    iswalnum((x) & 0xFFFF)
#define STRSTR(x, y)  wcsstr(x, y)
#define STRXFRM(x,y,z) wcsxfrm(x, y, z)
#define STRFTIME(a,b,c,d) wcsftime(a,b,c,d)
#ifndef _T
#define _T(x) L##x
#endif
#else
typedef char char_t;
#define STRLEN(x)     strlen(x)
#define STRCMP(x, y)  strcmp(x, y)
#define STRCPY(x, y)  strcpy(x, y)
#define STRNCPY(x,y,z) strncpy(x, y, z)
#define STRCOLL(x, y) strcoll(x, y)
#define STRNCMP(x,y,z) strncmp(x, y, z)
#define PRINTF        printf
#define FPRINTF       fprintf
#define SPRINTF       sprintf
#define VFPRINTF      vfprintf
#define FSCANF        fscanf
#define SSCANF        sscanf
#define GETC(x)       getc(x)
#define UNGETC(x, y)  ungetc(x, y)
#define TOLOWER(x)    tolower((x) & 0xFF)
#define TOUPPER(x)    toupper((x) & 0xFF)
#define ISALNUM(x)    isalnum((x) & 0xFF)
#define STRSTR(x, y)  strstr(x, y)
#define STRXFRM(x,y,z) strxfrm(x, y, z)
#define STRFTIME(a,b,c,d) strftime(a,b,c,d)
#ifndef _T
#define _T(x) x
#endif
#endif
#else
USE_GIGABASE_NAMESPACE
#endif

typedef struct cli_cstring_t { 
    int     len;
    char_t* ptr;
} cli_cstring_t;


#if defined(_WIN32)
typedef __int64      cli_int8_t;
#else
#if SIZEOF_LONG == 8
typedef signed long  cli_int8_t;
#else
typedef signed long long cli_int8_t;
#endif
#endif

#ifndef CLI_OID_DEFINED
typedef long cli_oid_t;
#endif

/*********************************************************************
 * cli_open
 *     Establish connection with the server
 * Parameters:
 *     server_url - zero terminated string with server address and port,
 *                  for example "localhost:5101", "195.239.208.240:6100",...
 *     max_connect_attempts  - number of attempts to establish connection
 *     reconnect_timeout_sec - timeput in seconds between connection attempts
 *     user_name - user name for login
 *     password  - password for login
 *     pooled_connection - if not 0, then connection will be allocated from the connection pool
 * Returns:
 *     >= 0 - connectiondescriptor to be used in all other cli calls
 *     <  0 - error code as described in cli_result_code enum
 */
int GIGABASE_DLL_ENTRY cli_open(char const*   server_url,
				int           max_connect_attempts,
				int           reconnect_timeout_sec, 
				char_t const* user_name,
				char_t const* password,
				int           pooled_connection);

/*********************************************************************
 * cli_close
 *     Close session
 * Parameters:
 *     session - session descriptor returned by cli_open
 * Returns:
 *     result code as described in cli_result_code enum
 */
int GIGABASE_DLL_ENTRY cli_close(int session);

/*********************************************************************
 * cli_clear_connection_pool
 *     Close all released connection in connection pool
 */
void GIGABASE_DLL_ENTRY cli_clear_connection_pool();

/*********************************************************************
 * cli_statement
 *     Specify SubSQL statement to be executed at server
 *     Binding to the parameters and columns can be established
 * Parameters:
 *     session - session descriptor returned by cli_open
 *     stmt    - zero terminated string with SubSQL statement
 * Returns:
 *     >= 0 - statement descriptor
 *     <  0 - error code as described in cli_result_code enum
 */
int GIGABASE_DLL_ENTRY cli_statement(int session, char_t const* stmt);

/*********************************************************************
 * cli_parameter
 *     Bind parameter to the statement
 * Parameters:
 *     statement  - statememt descriptor returned by cli_statement
 *     param_name - zero terminated string with parameter name
 *                  Paramter name should start with '%'
 *     var_type   - type of variable as described in cli_var_type enum.
 *                  Only scalar and zero terminated string types are supported.
 *     var_ptr    - pointer to the variable
 * Returns:
 *     result code as described in cli_result_code enum
 */
int GIGABASE_DLL_ENTRY cli_parameter(int           statement,
				     char_t const* param_name,
				     int           var_type,
				     void*         var_ptr);

/*********************************************************************
 * cli_column
 *     Bind extracted column of select or insert statement
 * Parameters:
 *     statement   - statememt descriptor returned by cli_statement
 *     column_name - zero terminated string with column name
 *     var_type    - type of variable as described in cli_var_type enum
 *     var_len     - pointer to the variable to hold length of array variable.
 *                   This variable should be assigned the maximal length
 *                   of the array/string buffer, pointed by var_ptr.
 *                   After the execution of the statement it is assigned the
 *                   real length of the fetched array/string. If it is large
 *                   than length of the buffer, then only part of the array
 *                   will be placed in the buffer, but var_len still will
 *                   contain the actual array length.
 *     var_ptr     - pointer to the variable
 * Returns:
 *     result code as described in cli_result_code enum
 */
int GIGABASE_DLL_ENTRY cli_column(int           statement,
				  char_t const* column_name,
				  int           var_type,
				  int*          var_len,
				  void*         var_ptr);


typedef void* (*cli_column_set)(int var_type, void* var_ptr, int len);
typedef void* (*cli_column_get)(int var_type, void* var_ptr, int* len);

typedef void* (*cli_column_set_ex)(int var_type, void* var_ptr, int len, 
				   char_t const* column_name, int statement);
typedef void* (*cli_column_get_ex)(int var_type, void* var_ptr, int* len, 
				   char_t const* column_name, int statemen);

/*********************************************************************
 * cli_array_column
 *     Specify get/set functions for the array column
 * Parameters:
 *     statement   - statememt descriptor returned by cli_statement
 *     column_name - zero terminated string with column name
 *     var_type    - type of variable as described in cli_var_type enum
 *     var_ptr     - pointer to the variable
 *     set         - function which will be called to construct fetched
 *                   field. It receives pointer to the variable,
 *                   length of the fetched array and returns pointer to th
 *                   array's elements
 *     get         - function which will be called to update the field in the
 *                   database. Given pointer to the variable, it should return
 *                   pointer to the array elements and store length of the
 *                   array to the variable pointer by len parameter
 * Returns:
 *     result code as described in cli_result_code enum
 */
int GIGABASE_DLL_ENTRY cli_array_column(int            statement,
					char_t const*  column_name,
					int            var_type,
					void*          var_ptr,
					cli_column_set set,
					cli_column_get get);

int GIGABASE_DLL_ENTRY cli_array_column_ex(int               statement,
					   char_t const*     column_name, 
					   int               var_type,
					   void*             var_ptr,
					   cli_column_set_ex set,
					   cli_column_get_ex get);
    

enum {
    cli_view_only,
    cli_for_update
};

/*********************************************************************
 * cli_fetch
 *     Execute select statement.
 * Parameters:
 *     statement  - statememt descriptor returned by cli_statement
 *     for_update - not zero if fetched rows will be updated
 * Returns:
 *     >= 0 - success, for select statements number of fetched rows is returned
 *     <  0 - error code as described in cli_result_code enum
 */
int GIGABASE_DLL_ENTRY cli_fetch(int statement, int for_update);

/*********************************************************************
 * cli_insert
 *     Execute insert statement.
 * Parameters:
 *     statement  - statememt descriptor returned by cli_statement
 *     oid        - object identifier of created record.
 * Returns:
 *     status code as described in cli_result_code enum
 */
int GIGABASE_DLL_ENTRY cli_insert(int statement, cli_oid_t* oid);

/*********************************************************************
 * cli_get_first
 *     Get first row of the selection.
 * Parameters:
 *     statement  - statememt descriptor returned by cli_statement
 * Returns:
 *     result code as described in cli_result_code enum
 */
int GIGABASE_DLL_ENTRY cli_get_first(int statement);

/*********************************************************************
 * cli_get_last
 *     Get last row of the selection.
 * Parameters:
 *     statement  - statememt descriptor returned by cli_statement
 * Returns:
 *     result code as described in cli_result_code enum
 */
int GIGABASE_DLL_ENTRY cli_get_last(int statement);

/*********************************************************************
 * cli_get_next
 *     Get next row of the selection. If get_next records is called
 *     exactly after cli_fetch function call, is will fetch the first record
 *     in selection.
 * Parameters:
 *     statement  - statememt descriptor returned by cli_statement
 * Returns:
 *     result code as described in cli_result_code enum
 */
int GIGABASE_DLL_ENTRY cli_get_next(int statement);

/*********************************************************************
 * cli_get_prev
 *     Get previous row of the selection. If get_next records is called
 *     exactly after cli_fetch function call, is will fetch the last record
 *     in selection.
 * Parameters:
 *     statement  - statememt descriptor returned by cli_statement
 * Returns:
 *     result code as described in cli_result_code enum
 */
int GIGABASE_DLL_ENTRY cli_get_prev(int statement);

/*********************************************************************
 * cli_get_oid
 *     Get object identifier of the current record
 * Parameters:
 *     statement  - statememt descriptor returned by cli_statement
 * Returns:
 *     object identifier or 0 if no object is seleected
 */
cli_oid_t GIGABASE_DLL_ENTRY cli_get_oid(int statement);

/*********************************************************************
 * cli_update
 *     Update the current row in the selection. You have to set
 *     for_update parameter of cli_fetch to 1 in order to be able
 *     to perform updates. Updated value of row fields will be taken
 *     from bound column variables.
 * Parameters:
 *     statement   - statememt descriptor returned by cli_statement
 * Returns:
 *     result code as described in cli_result_code enum
 */
int GIGABASE_DLL_ENTRY cli_update(int statement);

/*********************************************************************
 * cli_remove
 *     Remove all selected records. You have to set
 *     for_update parameter of cli_fetch to 1 in order to be able
 *     to remove records.
 * Parameters:
 *     statement   - statememt descriptor returned by cli_statement
 * Returns:
 *     result code as described in cli_result_code enum
 */
int GIGABASE_DLL_ENTRY cli_remove(int statement);

/*********************************************************************
 * cli_free
 *     Deallocate statement and all associated data
 * Parameters:
 *     statement   - statememt descriptor returned by cli_statement
 * Returns:
 *     result code as described in cli_result_code enum
 */
int GIGABASE_DLL_ENTRY cli_free(int statement);

/*********************************************************************
 * cli_commit
 *     Commit current database transaction
 * Parameters:
 *     session - session descriptor as returned by cli_open
 * Returns:
 *     result code as described in cli_result_code enum
 */
int GIGABASE_DLL_ENTRY cli_commit(int session);

/*********************************************************************
 * cli_precommit
 *     Release all locks set by transaction. This methods allows other clients
 *     to proceed, but it doesn't flush transaction to the disk.
 * Parameters:
 *     session - session descriptor as returned by cli_open
 * Returns:
 *     result code as described in cli_result_code enum
 */
int GIGABASE_DLL_ENTRY cli_precommit(int session);

/*********************************************************************
 * cli_abort
 *     Abort current database transaction
 * Parameters:
 *     session - session descriptor as returned by cli_open
 * Returns:
 *     result code as described in cli_result_code enum
 */
int GIGABASE_DLL_ENTRY cli_abort(int session);


typedef struct cli_field_descriptor { 
    enum cli_var_type type;
    char_t const*     name;
} cli_field_descriptor;

/*********************************************************************
 * cli_describe
 *     Describe fileds of specified table
 * Parameters:
 *     session - session descriptor as returned by cli_open
 *     table   - name of the table
 *     fields  - adress of the pointer to the array of fields descriptors, 
 *               this array should be later deallocated by application by free()
 * Returns:
 *     >= 0 - number of fields in the table
 *     < 0  - result code as described in cli_result_code enum
 */
int GIGABASE_DLL_ENTRY cli_describe(int session, char_t const* table, cli_field_descriptor** fields);


typedef struct cli_table_descriptor {
    char_t const*       name;
} cli_table_descriptor;

/*********************************************************************
 * cli_show_tables
 *     Show all tables of specified database
 * Parameters:
 *     session - session descriptor as returned by cli_open
 *     tables  - address of the pointer to the array of tables descriptors,
 *               this array should be later deallocated by application by free()
 * Returns:
 *     >= 0 - number of tables in the database (Metatable is not returned/counted)
 *     < 0  - result code as described in cli_result_code enum
 */
int GIGABASE_DLL_ENTRY cli_show_tables(int session, cli_table_descriptor** tables);

#ifdef __cplusplus
}
#endif

#endif


