driver/myutil.h (398 lines of code) (raw):

// Copyright (c) 2001, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // // This program is designed to work with certain software (including // but not limited to OpenSSL) that is licensed under separate terms, as // designated in a particular file or component or in included license // documentation. The authors of MySQL hereby grant you an additional // permission to link the program and your derivative works with the // separately licensed software that they have either included with // the program or referenced in the documentation. // // Without limiting anything contained in the foregoing, this file, // which is part of Connector/ODBC, is also subject to the // Universal FOSS Exception, version 1.0, a copy of which can be found at // https://oss.oracle.com/licenses/universal-foss-exception. // // This program is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. // See the GNU General Public License, version 2.0, for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA /*************************************************************************** * MYUTIL.H * * * * @description: Prototype definations needed by the driver * * * * @author : MySQL AB(monty@mysql.com, venu@mysql.com) * * @date : 2001-Sep-22 * * @product : myodbc3 * * * ****************************************************************************/ #ifndef __MYUTIL_H__ #define __MYUTIL_H__ /* Utility macros */ #define if_forward_cache(st) ((st)->stmt_options.cursor_type == SQL_CURSOR_FORWARD_ONLY && \ (st)->dbc->ds.opt_NO_CACHE) #define is_connected(dbc) ((dbc)->mysql && (dbc)->mysql->net.vio) #define trans_supported(db) ((db)->mysql->server_capabilities & CLIENT_TRANSACTIONS) #define autocommit_on(db) ((db)->mysql->server_status & SERVER_STATUS_AUTOCOMMIT) #define is_no_backslashes_escape_mode(db) ((db)->mysql->server_status & SERVER_STATUS_NO_BACKSLASH_ESCAPES) #define reset_ptr(x) {if (x) x= 0;} #define digit(A) ((int) (A - '0')) #define MYLOG_QUERY(A,B) {if ((A)->dbc->ds.opt_LOG_QUERY) \ query_print((A)->dbc->query_log,(char*) B);} #define MYLOG_DBC_QUERY(A,B) {if((A)->ds.opt_LOG_QUERY) \ query_print((A)->query_log,(char*) B);} /* A few character sets we care about. */ #define ASCII_CHARSET_NUMBER 11 #define BINARY_CHARSET_NUMBER 63 #define UTF8_CHARSET_NUMBER 33 /* truncation types in SQL_NUMERIC_STRUCT conversions */ #define SQLNUM_TRUNC_FRAC 1 #define SQLNUM_TRUNC_WHOLE 2 /* Conversion to SQL_TIMESTAMP_STRUCT errors(str_to_ts) */ #define SQLTS_NULL_DATE -1 #define SQLTS_BAD_DATE -2 /* Sizes of buffer for converion of 4 and 8 bytes integer values*/ #define MAX32_BUFF_SIZE 11 #define MAX64_BUFF_SIZE 21 #define my_int2str(val, dst, radix, upcase) \ myodbc_int10_to_str((val), (dst), (radix)) #if LIBMYSQL_VERSION_ID >= 50100 typedef unsigned char * DYNAMIC_ELEMENT; #else typedef char * DYNAMIC_ELEMENT; #endif // Handle the removal of `def` and `def_length` // from MYSQL_FIELD struct in MySQL 8.3.0 // (see WL#16221 and WL#16383) #if LIBMYSQL_VERSION_ID == 80300 #define MYSQL_FIELD_DEF #define MYSQL_FIELD_DEF_LENGTH #else #define MYSQL_FIELD_DEF NullS, #define MYSQL_FIELD_DEF_LENGTH 0, #endif /* Same us MYODBC_FIELD_STRING(name, NAME_LEN, flags) */ # define MYODBC_FIELD_NAME(name, flags) \ {(char*)(name), (char*)(name), NullS, NullS, NullS, NullS, MYSQL_FIELD_DEF \ NAME_LEN, 0, 0, 0, 0, 0, 0, 0, MYSQL_FIELD_DEF_LENGTH \ (flags), 0, UTF8_CHARSET_NUMBER, MYSQL_TYPE_VAR_STRING, NULL} # define MYODBC_FIELD_STRING(name, len, flags) \ {(char*)(name), (char*)(name), NullS, NullS, NullS, NullS, MYSQL_FIELD_DEF \ (len*SYSTEM_CHARSET_MBMAXLEN), 0, 0, 0, 0, 0, 0, 0, MYSQL_FIELD_DEF_LENGTH \ (flags), 0, UTF8_CHARSET_NUMBER, MYSQL_TYPE_VAR_STRING, NULL} # define MYODBC_FIELD_SHORT(name, flags) \ {(char*)(name), (char*)(name), NullS, NullS, NullS, NullS, MYSQL_FIELD_DEF \ 5, 5, 0, 0, 0, 0, 0, 0, MYSQL_FIELD_DEF_LENGTH \ (flags), 0, 0, MYSQL_TYPE_SHORT, NULL} # define MYODBC_FIELD_LONG(name, flags) \ {(char*)(name), (char*)(name), NullS, NullS, NullS, NullS, MYSQL_FIELD_DEF \ 11, 11, 0, 0, 0, 0, 0, 0, MYSQL_FIELD_DEF_LENGTH \ (flags), 0, 0, MYSQL_TYPE_LONG, NULL} # define MYODBC_FIELD_LONGLONG(name, flags) \ {(char*)(name), (char*)(name), NullS, NullS, NullS, NullS, MYSQL_FIELD_DEF \ 20, 20, 0, 0, 0, 0, 0, 0, MYSQL_FIELD_DEF_LENGTH \ (flags), 0, 0, MYSQL_TYPE_LONGLONG, NULL} /* Utility function prototypes that share among files */ SQLRETURN my_SQLPrepare (SQLHSTMT hstmt, SQLCHAR *szSqlStr, SQLINTEGER cbSqlStr, bool reset_select_limit, bool force_prepare); SQLRETURN my_SQLExecute (STMT * stmt); SQLRETURN SQL_API my_SQLFreeStmt (SQLHSTMT hstmt,SQLUSMALLINT fOption); SQLRETURN SQL_API my_SQLFreeStmtExtended(SQLHSTMT hstmt, SQLUSMALLINT fOption, SQLUSMALLINT fExtra); SQLRETURN SQL_API my_SQLAllocStmt (SQLHDBC hdbc,SQLHSTMT *phstmt); SQLRETURN do_query (STMT *stmt, std::string query); SQLRETURN insert_params (STMT *stmt, SQLULEN row, std::string &finalquery); void myodbc_link_fields (STMT *stmt,MYSQL_FIELD *fields,uint field_count); void fix_row_lengths (STMT *stmt, const long* fix_rules, uint row, uint field_count); void fix_result_types (STMT *stmt); char * fix_str (char *to,const char *from,int length); char * dupp_str (char *from,int length); SQLRETURN my_pos_delete_std (STMT *stmt,STMT *stmtParam, SQLUSMALLINT irow, std::string &str); SQLRETURN my_pos_update_std (STMT *stmt,STMT *stmtParam, SQLUSMALLINT irow, std::string &str); char * check_if_positioned_cursor_exists (STMT *stmt, STMT **stmtNew); SQLRETURN insert_param (STMT *stmt, MYSQL_BIND *bind, DESC *apd, DESCREC *aprec, DESCREC *iprec, SQLULEN row); SQLRETURN set_sql_select_limit(DBC *dbc, SQLULEN new_value, my_bool reqLock); SQLRETURN exec_stmt_query(STMT *stmt, const char *query, SQLULEN query_length, my_bool reqLock); SQLRETURN exec_stmt_query_std(STMT *stmt, const std::string &str, bool reqLock); SQLRETURN copy_ansi_result(STMT *stmt, SQLCHAR *result, SQLLEN result_bytes, SQLLEN *used_bytes, MYSQL_FIELD *field, char *src, unsigned long src_bytes); SQLRETURN copy_binary_result(STMT *stmt, SQLCHAR *result, SQLLEN result_bytes, SQLLEN *used_bytes, MYSQL_FIELD *field, char *src, unsigned long src_bytes); template <typename T> SQLRETURN copy_binhex_result(STMT *stmt, T *rgbValue, SQLINTEGER cbValueMax, SQLLEN *pcbValue, char *src, ulong src_length); SQLRETURN copy_bit_result(STMT *stmt, SQLCHAR *result, SQLLEN result_bytes, SQLLEN *used_bytes, MYSQL_FIELD *field, char *src, unsigned long src_bytes); SQLRETURN wcopy_bit_result(STMT *stmt, SQLWCHAR *result, SQLLEN result_bytes, SQLLEN *used_bytes, MYSQL_FIELD *field, char *src, unsigned long src_bytes); SQLRETURN copy_wchar_result(STMT *stmt, SQLWCHAR *rgbValue, SQLINTEGER cbValueMax, SQLLEN *pcbValue, MYSQL_FIELD *field, char *src, long src_length); SQLRETURN set_desc_error (DESC *desc, char *state, const char *message, uint errcode); SQLRETURN handle_connection_error (STMT *stmt); my_bool is_connection_lost (uint errcode); void set_mem_error (MYSQL *mysql); void translate_error (char *save_state, myodbc_errid errid, uint mysql_err); SQLSMALLINT get_sql_data_type_from_str(const char *mysql_type_name); SQLSMALLINT compute_sql_data_type(STMT *stmt, SQLSMALLINT sql_type, char octet_length, size_t col_size); SQLSMALLINT get_sql_data_type (STMT *stmt, MYSQL_FIELD *field, char *buff); SQLULEN get_column_size (STMT *stmt, MYSQL_FIELD *field); SQLULEN get_column_size_from_str (STMT *stmt, const char *size_str); SQLULEN fill_column_size_buff (char *buff, STMT *stmt, MYSQL_FIELD *field); SQLSMALLINT get_decimal_digits (STMT *stmt, MYSQL_FIELD *field); SQLLEN get_transfer_octet_length (STMT *stmt, MYSQL_FIELD *field); SQLLEN fill_transfer_oct_len_buff (char *buff, STMT *stmt, MYSQL_FIELD *field); SQLLEN get_display_size (STMT *stmt, MYSQL_FIELD *field); SQLLEN fill_display_size_buff (char *buff, STMT *stmt, MYSQL_FIELD *field); SQLSMALLINT get_dticode_from_concise_type (SQLSMALLINT concise_type); SQLSMALLINT get_concise_type_from_datetime_code (SQLSMALLINT dticode); SQLSMALLINT get_concise_type_from_interval_code (SQLSMALLINT dticode); SQLSMALLINT get_type_from_concise_type (SQLSMALLINT concise_type); SQLLEN get_bookmark_value (SQLSMALLINT fCType, SQLPOINTER rgbValue); #define is_char_sql_type(type) \ ((type) == SQL_CHAR || (type) == SQL_VARCHAR || (type) == SQL_LONGVARCHAR) #define is_wchar_sql_type(type) \ ((type) == SQL_WCHAR || (type) == SQL_WVARCHAR || (type) == SQL_WLONGVARCHAR) #define is_binary_sql_type(type) \ ((type) == SQL_BINARY || (type) == SQL_VARBINARY || \ (type) == SQL_LONGVARBINARY) #define is_numeric_mysql_type(field) \ ((field)->type <= MYSQL_TYPE_NULL || (field)->type == MYSQL_TYPE_LONGLONG || \ (field)->type == MYSQL_TYPE_INT24 || \ ((field)->type == MYSQL_TYPE_BIT && (field)->length == 1) || \ (field)->type == MYSQL_TYPE_NEWDECIMAL) SQLRETURN SQL_API my_SQLBindParameter(SQLHSTMT hstmt,SQLUSMALLINT ipar, SQLSMALLINT fParamType, SQLSMALLINT fCType, SQLSMALLINT fSqlType, SQLULEN cbColDef, SQLSMALLINT ibScale, SQLPOINTER rgbValue, SQLLEN cbValueMax, SQLLEN *pcbValue); SQLRETURN SQL_API my_SQLExtendedFetch(SQLHSTMT hstmt, SQLUSMALLINT fFetchType, SQLLEN irow, SQLULEN *pcrow, SQLUSMALLINT *rgfRowStatus, my_bool upd_status); SQLRETURN SQL_API myodbc_single_fetch( SQLHSTMT hstmt, SQLUSMALLINT fFetchType, SQLLEN irow, SQLULEN *pcrow, SQLUSMALLINT *rgfRowStatus, my_bool upd_status); SQLRETURN SQL_API sql_get_data(STMT *stmt, SQLSMALLINT fCType, uint column_number, SQLPOINTER rgbValue, SQLLEN cbValueMax, SQLLEN *pcbValue, char *value, ulong length, DESCREC *arrec); SQLRETURN SQL_API sql_get_bookmark_data(STMT *stmt, SQLSMALLINT fCType, uint column_number, SQLPOINTER rgbValue, SQLLEN cbValueMax, SQLLEN *pcbValue, char *value, ulong length, DESCREC *arrec); void fix_padded_length(STMT *stmt, SQLSMALLINT fCType, SQLLEN cbValueMax, SQLLEN *pcbValue, ulong data_len, DESCREC *irrec); SQLRETURN SQL_API my_SQLSetPos(SQLHSTMT hstmt, SQLSETPOSIROW irow, SQLUSMALLINT fOption, SQLUSMALLINT fLock); int unireg_to_c_datatype (MYSQL_FIELD *field); int default_c_type (int sql_data_type); ulong bind_length (int sql_data_type,ulong length); my_bool str_to_date (SQL_DATE_STRUCT *rgbValue, const char *str, uint length, int zeroToMin); int str_to_ts (SQL_TIMESTAMP_STRUCT *ts, const char *str, int len, int zeroToMin, BOOL dont_use_set_locale); my_bool str_to_time_st (SQL_TIME_STRUCT *ts, const char *str); ulong str_to_time_as_long (const char *str,uint length); void init_getfunctions (void); void myodbc_init (void); void myodbc_ov_init (SQLINTEGER odbc_version); void myodbc_sqlstate2_init (void); void myodbc_sqlstate3_init (void); int check_if_server_is_alive (DBC *dbc); MYSQL *new_mysql (void); bool myodbc_append_quoted_name_std(std::string &str, const char *name); SQLRETURN set_handle_error (SQLSMALLINT HandleType, SQLHANDLE handle, myodbc_errid errid, const char *errtext, SQLINTEGER errcode); SQLRETURN set_env_error (ENV * env,myodbc_errid errid, const char *errtext, SQLINTEGER errcode); SQLRETURN copy_str_data (SQLSMALLINT HandleType, SQLHANDLE Handle, SQLCHAR *rgbValue, SQLSMALLINT cbValueMax, SQLSMALLINT *pcbValue,char *src); SQLRETURN SQL_API my_SQLAllocEnv (SQLHENV * phenv); SQLRETURN SQL_API my_SQLAllocConnect (SQLHENV henv, SQLHDBC *phdbc); SQLRETURN SQL_API my_SQLFreeConnect (SQLHDBC hdbc); SQLRETURN SQL_API my_SQLFreeEnv (SQLHENV henv); void myodbc_end(); my_bool set_dynamic_result (STMT *stmt); bool set_current_cursor_data (STMT *stmt,SQLUINTEGER irow); my_bool is_minimum_version (const char *server_version,const char *version); int myodbc_strcasecmp (const char *s, const char *t); int myodbc_casecmp (const char *s, const char *t, uint len); int reget_current_catalog (DBC *dbc); ulong myodbc_escape_string (STMT *stmt, char *to, ulong to_length, const char *from, ulong length, bool escape_id = false, bool esc_wildcard = false); DESCREC* desc_get_rec (DESC *desc, int recnum, my_bool expand); DESC* desc_alloc (STMT *stmt, SQLSMALLINT alloc_type, desc_ref_type ref_type, desc_desc_type desc_type); void desc_free (DESC *desc); int desc_find_dae_rec (DESC *desc); DESCREC * desc_find_outstream_rec (STMT *stmt, uint *recnum, uint *res_col_num); SQLRETURN stmt_SQLSetDescField (STMT *stmt, DESC *desc, SQLSMALLINT recnum, SQLSMALLINT fldid, SQLPOINTER val, SQLINTEGER buflen); SQLRETURN stmt_SQLGetDescField (STMT *stmt, DESC *desc, SQLSMALLINT recnum, SQLSMALLINT fldid, SQLPOINTER valptr, SQLINTEGER buflen, SQLINTEGER *strlen); SQLRETURN stmt_SQLCopyDesc(STMT *stmt, DESC *src, DESC *dest); void sqlnum_from_str (const char *numstr, SQL_NUMERIC_STRUCT *sqlnum, int *overflow_ptr); void sqlnum_to_str (SQL_NUMERIC_STRUCT *sqlnum, SQLCHAR *numstr, SQLCHAR **numbegin, SQLCHAR reqprec, SQLSCHAR reqscale, int *truncptr); void *ptr_offset_adjust (void *ptr, SQLULEN *bind_offset, SQLINTEGER bind_type, SQLINTEGER default_size, SQLULEN row); /* Functions used when debugging */ void query_print (FILE *log_file,char *query); FILE *init_query_log (void); void end_query_log (FILE *query_log); enum enum_field_types map_sql2mysql_type(SQLSMALLINT sql_type); /* proc_* functions - used to parse prcedures headers in SQLProcedureColumns */ char * proc_param_tokenize (char *str, int *params_num); char * proc_get_param_type (char *proc, int len, SQLSMALLINT *ptype); char * proc_get_param_name (char *proc, int len, char *cname); char * proc_get_param_dbtype (char *proc, int len, char *ptype); SQLUINTEGER proc_get_param_size (SQLCHAR *ptype, int len, int sql_type_index, SQLSMALLINT *dec); SQLLEN proc_get_param_octet_len (STMT *stmt, int sql_type_index, SQLULEN col_size, SQLSMALLINT decimal_digits, unsigned int flags, char * str_buff); SQLLEN proc_get_param_col_len (STMT *stmt, int sql_type_index, SQLULEN col_size, SQLSMALLINT decimal_digits, unsigned int flags, char * str_buff); int proc_get_param_sql_type_index (const char*ptype, int len); SQLTypeMap *proc_get_param_map_by_index (int index); char * proc_param_next_token (char *str, char *str_end); void set_row_count (STMT * stmt, my_ulonglong rows); const char *get_fractional_part (const char * str, int len, BOOL dont_use_set_locale, SQLUINTEGER * fraction); /* Convert MySQL timestamp to full ANSI timestamp format. */ char * complete_timestamp (const char * value, ulong length, char buff[21]); BOOL myodbc_isspace (myodbc::CHARSET_INFO* cs, const char * begin, const char *end); BOOL myodbc_isnum (myodbc::CHARSET_INFO* cs, const char * begin, const char *end); #define NO_OUT_PARAMETERS 0 #define GOT_OUT_PARAMETERS 1 #define GOT_OUT_STREAM_PARAMETERS 2 int got_out_parameters (STMT *stmt); const char get_identifier_quote(STMT *stmt); SQLULEN get_query_timeout(STMT *stmt); SQLRETURN set_query_timeout(STMT *stmt, SQLULEN new_value); int get_session_variable(STMT *stmt, const char *var, char *result, size_t buf_len); /* handle.c*/ void adjust_param_bind_array (STMT *stmt); /* Actions taken when connection is put to the pool. Used in connection freeing as well */ int reset_connection (DBC *dbc); /* Actions taken when connection is taken from the pool */ int wakeup_connection (DBC *dbc); #define WAKEUP_CONN_IF_NEEDED(dbc) if (dbc->need_to_wakeup && wakeup_connection(dbc)) return SQL_ERROR long long binary2ll(char* src, uint64 srcLen); unsigned long long binary2ull(char* src, uint64 srcLen); void fill_ird_data_lengths (DESC *ird, ulong *lengths, uint fields); /* Functions to work with prepared and regular statements */ #define IS_PS_OUT_PARAMS(_stmt) ((_stmt)->dbc->mysql->server_status & SERVER_PS_OUT_PARAMS) /* my_stmt.c */ BOOL ssps_used (STMT *stmt); BOOL returned_result (STMT *stmt); my_bool free_current_result (STMT *stmt); MYSQL_RES * get_result_metadata (STMT *stmt, BOOL force_use); int bind_result (STMT *stmt); int get_result (STMT *stmt); my_ulonglong affected_rows (STMT *stmt); my_ulonglong update_affected_rows(STMT *stmt); my_ulonglong num_rows (STMT *stmt); unsigned long* fetch_lengths (STMT *stmt); MYSQL_ROW_OFFSET row_seek (STMT *stmt, MYSQL_ROW_OFFSET offset); void data_seek (STMT *stmt, my_ulonglong offset); MYSQL_ROW_OFFSET row_tell (STMT *stmt); int next_result (STMT *stmt); SQLRETURN send_long_data (STMT *stmt, unsigned int param_num, DESCREC * aprec, const char *chunk, unsigned long length); #define IGNORE_THROW(A) try{ A; }catch(...){} int get_int (STMT *stmt, ulong column_number, char *value, ulong length); unsigned int get_uint (STMT *stmt, ulong column_number, char *value, ulong length); long long get_int64 (STMT *stmt, ulong column_number, char *value, ulong length); unsigned long long get_uint64(STMT * stmt, ulong column_number, char* value, ulong length); char * get_string (STMT *stmt, ulong column_number, char *value, ulong *length, char * buffer); double get_double (STMT *stmt, ulong column_number, char *value, ulong length); BOOL is_null (STMT *stmt, ulong column_number, char *value); SQLRETURN prepare (STMT *stmt, char * query, SQLINTEGER query_length, bool reset_sql_limit, bool force_prepare); inline void stmt_result_free(STMT * stmt) { if (!stmt->result) return; if (stmt->fake_result) { x_free(stmt->result); } else mysql_free_result(stmt->result); stmt->result = NULL; } /* scroller-related functions */ unsigned int calc_prefetch_number(unsigned int selected, SQLULEN app_fetchs, SQLULEN max_rows); BOOL scroller_exists (STMT * stmt); void scroller_create (STMT * stmt, const char *query, SQLULEN len); unsigned long long scroller_move (STMT * stmt); SQLRETURN scroller_prefetch (STMT * stmt); bool scrollable (STMT * stmt, const char * query, const char * query_end); /* my_prepared_stmt.c */ void ssps_init (STMT *stmt); BOOL ssps_get_out_params (STMT *stmt); int ssps_get_result (STMT *stmt); void ssps_close (STMT *stmt); SQLRETURN ssps_fetch_chunk (STMT *stmt, char *dest, unsigned long dest_bytes, unsigned long *avail_bytes); void free_result_bind (STMT *stmt); BOOL ssps_buffers_need_extending(STMT *stmt); template <typename T> T ssps_get_int64 (STMT *stmt, ulong column_number, char *value, ulong length); double ssps_get_double (STMT *stmt, ulong column_number, char *value, ulong length); char * ssps_get_string (STMT *stmt, ulong column_number, char *value, ulong *length, char * buffer); SQLRETURN ssps_send_long_data (STMT *stmt, unsigned int param_num, const char *chunk, unsigned long length); MYSQL_BIND * get_param_bind (STMT *stmt, unsigned int param_number, int reset); bool is_varlen_type(enum enum_field_types type); /* connect.c */ void free_connection_stmts(DBC *dbc); #ifdef __WIN__ #define cmp_database(A,B) myodbc_strcasecmp((const char *)(A),(const char *)(B)) #else #define cmp_database(A,B) strcmp((A),(B)) #endif /* Check if an octet_length_ptr is a data-at-exec field. WARNING: This macro evaluates the argument multiple times. */ #define IS_DATA_AT_EXEC(X) ((X) && \ (*(X) == SQL_DATA_AT_EXEC || \ *(X) <= SQL_LEN_DATA_AT_EXEC_OFFSET)) /* Macro evaluates SQLRETURN expression and in case of error pushes it up in callstack */ #define PUSH_ERROR(sqlreturn_expr) do\ {\ SQLRETURN lrc= (sqlreturn_expr);\ if (!SQL_SUCCEEDED(lrc))\ return lrc;\ } while(0) /* Same as previous, but remembers to given var2rec SQL_SUCCESS_WITH_INFO */ #define PUSH_ERROR_EXT(var2rec,sqlreturn_expr) do\ {\ SQLRETURN lrc= (sqlreturn_expr);\ if (!SQL_SUCCEEDED(lrc))\ return lrc;\ else if (lrc!=SQL_SUCCESS)\ var2rec= lrc;\ } while(0) /* Same as PUSH_ERROR but does not break execution in case of specified 'error' */ #define PUSH_ERROR_UNLESS(sqlreturn_expr, error) do\ {\ SQLRETURN lrc= (sqlreturn_expr);\ if (!SQL_SUCCEEDED(lrc)&&lrc!=error)\ return lrc;\ } while(0) /* Same as PUSH_ERROR_UNLESS but remembers to given var2rec SQL_SUCCESS_WITH_INFO */ #define PUSH_ERROR_UNLESS_EXT(var2rec, sqlreturn_expr, error) do\ {\ SQLRETURN lrc= (sqlreturn_expr);\ if (!SQL_SUCCEEDED(lrc)&&lrc!=error)\ return lrc;\ else if (lrc!=SQL_SUCCESS)\ var2rec= lrc;\ } while(0) #define GET_NAME_LEN(S, N, L) L = (L == SQL_NTS ? (N ? (SQLSMALLINT)strlen((char *)N) : 0) : L); \ if (L > NAME_LEN) \ return S->set_error("HY090", \ "One or more parameters exceed the maximum allowed name length", 0); #define CHECK_HANDLE(h) if (h == NULL) return SQL_INVALID_HANDLE #define CHECK_DATA_POINTER(S, D, C) if (D == NULL && C != 0 && C != SQL_DEFAULT_PARAM && C != SQL_NULL_DATA) \ return S->set_error("HY009", "Invalid use of NULL pointer", 0); #define CHECK_STRLEN_OR_IND(S, D, C) if (D != NULL && C < 0 && C != SQL_NTS && C != SQL_NULL_DATA) \ return S->set_error("HY090", "Invalid string or buffer length", 0); #define CHECK_ENV_OUTPUT(e) if(e == NULL) return SQL_ERROR #define CHECK_DBC_OUTPUT(e, d) if(d == NULL) return set_env_error((ENV *)e, MYERR_S1009, NULL, 0) #define CHECK_STMT_OUTPUT(d, s) if(s == NULL) return ((DBC *)d)->set_error(MYERR_S1009, NULL, 0) #define CHECK_DESC_OUTPUT(d, s) CHECK_STMT_OUTPUT(d, s) #define CHECK_DATA_OUTPUT(s, d) if(d == NULL) return ((STMT *)s)->set_error(MYERR_S1000, "Invalid output buffer", 0) #define IF_NOT_NULL(v, x) if (v != NULL) x #endif /* __MYUTIL_H__ */