void data_objects_raise_error(VALUE self, const struct errcodes *errors, int errnum, const char *message, VALUE query, VALUE state) { const char *exception_type = "SQLError"; const struct errcodes *e; VALUE uri, exception; for (e = errors; e->error_name; e++) { if (e->error_no == errnum) { // return the exception type for the matching error exception_type = e->exception; break; } } uri = rb_funcall(rb_iv_get(self, "@connection"), rb_intern("to_s"), 0); exception = rb_funcall( data_objects_const_get(mDO, exception_type), DO_ID_NEW, 5, rb_str_new2(message), INT2NUM(errnum), state, query, uri ); rb_exc_raise(exception); }
void do_postgres_full_connect(VALUE self, PGconn *db) { VALUE r_host; char *host = NULL; if ((r_host = rb_iv_get(self, "@host")) != Qnil) { host = StringValuePtr(r_host); } VALUE r_user; char *user = NULL; if ((r_user = rb_iv_get(self, "@user")) != Qnil) { user = StringValuePtr(r_user); } VALUE r_password; char *password = NULL; if ((r_password = rb_iv_get(self, "@password")) != Qnil) { password = StringValuePtr(r_password); } VALUE r_port; const char *port = "5432"; if ((r_port = rb_iv_get(self, "@port")) != Qnil) { port = StringValuePtr(r_port); } VALUE r_path; char *path = NULL; char *database = NULL; if ((r_path = rb_iv_get(self, "@path")) != Qnil) { path = StringValuePtr(r_path); database = strtok(path, "/"); } if (!database || !*database) { database = NULL; } VALUE r_query = rb_iv_get(self, "@query"); const char *search_path = data_objects_get_uri_option(r_query, "search_path"); db = PQsetdbLogin( host, port, NULL, NULL, database, user, password ); if (PQstatus(db) == CONNECTION_BAD) { rb_raise(eDO_ConnectionError, "%s", PQerrorMessage(db)); } PGresult *result; if (search_path) { char *search_path_query; if (!(search_path_query = calloc(256, sizeof(char)))) { rb_memerror(); } snprintf(search_path_query, 256, "set search_path to %s;", search_path); r_query = rb_str_new2(search_path_query); result = do_postgres_cCommand_execute(Qnil, self, db, r_query); if (PQresultStatus(result) != PGRES_COMMAND_OK) { free(search_path_query); do_postgres_raise_error(self, result, r_query); } free(search_path_query); } const char *backslash_off = "SET backslash_quote = off"; const char *standard_strings_on = "SET standard_conforming_strings = on"; const char *warning_messages = "SET client_min_messages = warning"; const char *date_format = "SET datestyle = ISO"; VALUE r_options; r_options = rb_str_new2(backslash_off); result = do_postgres_cCommand_execute(Qnil, self, db, r_options); if (PQresultStatus(result) != PGRES_COMMAND_OK) { rb_warn("%s", PQresultErrorMessage(result)); } r_options = rb_str_new2(standard_strings_on); result = do_postgres_cCommand_execute(Qnil, self, db, r_options); if (PQresultStatus(result) != PGRES_COMMAND_OK) { rb_warn("%s", PQresultErrorMessage(result)); } r_options = rb_str_new2(warning_messages); result = do_postgres_cCommand_execute(Qnil, self, db, r_options); if (PQresultStatus(result) != PGRES_COMMAND_OK) { rb_warn("%s", PQresultErrorMessage(result)); } r_options = rb_str_new2(date_format); result = do_postgres_cCommand_execute(Qnil, self, db, r_options); if (PQresultStatus(result) != PGRES_COMMAND_OK) { rb_warn("%s", PQresultErrorMessage(result)); } VALUE encoding = rb_iv_get(self, "@encoding"); #ifdef HAVE_PQSETCLIENTENCODING VALUE pg_encoding = rb_hash_aref(data_objects_const_get(mDO_PostgresEncoding, "MAP"), encoding); if (pg_encoding != Qnil) { if (PQsetClientEncoding(db, rb_str_ptr_readonly(pg_encoding))) { rb_raise(eDO_ConnectionError, "Couldn't set encoding: %s", rb_str_ptr_readonly(encoding)); } else { #ifdef HAVE_RUBY_ENCODING_H rb_iv_set(self, "@encoding_id", INT2FIX(rb_enc_find_index(rb_str_ptr_readonly(encoding)))); #endif rb_iv_set(self, "@pg_encoding", pg_encoding); } } else { rb_warn("Encoding %s is not a known Ruby encoding for PostgreSQL\n", rb_str_ptr_readonly(encoding)); rb_iv_set(self, "@encoding", rb_str_new2("UTF-8")); #ifdef HAVE_RUBY_ENCODING_H rb_iv_set(self, "@encoding_id", INT2FIX(rb_enc_find_index("UTF-8"))); #endif rb_iv_set(self, "@pg_encoding", rb_str_new2("UTF8")); } #endif rb_iv_set(self, "@connection", Data_Wrap_Struct(rb_cObject, 0, 0, db)); }
void do_mysql_full_connect(VALUE self, MYSQL *db) { VALUE r_host = rb_iv_get(self, "@host"); const char *host = "localhost"; if (r_host != Qnil) { host = StringValuePtr(r_host); } VALUE r_user = rb_iv_get(self, "@user"); const char *user = "******"; if (r_user != Qnil) { user = StringValuePtr(r_user); } VALUE r_password = rb_iv_get(self, "@password"); char *password = NULL; if (r_password != Qnil) { password = StringValuePtr(r_password); } VALUE r_port = rb_iv_get(self, "@port"); int port = 3306; if (r_port != Qnil) { port = NUM2INT(r_port); } VALUE r_path = rb_iv_get(self, "@path"); char *path = NULL; char *database = NULL; if (r_path != Qnil) { path = StringValuePtr(r_path); database = strtok(path, "/"); // not threadsafe } if (!database || !*database) { rb_raise(eConnectionError, "Database must be specified"); } VALUE r_query = rb_iv_get(self, "@query"); char *socket = NULL; // Check to see if we're on the db machine. If so, try to use the socket if (strcasecmp(host, "localhost") == 0) { socket = data_objects_get_uri_option(r_query, "socket"); if (socket) { rb_iv_set(self, "@using_socket", Qtrue); } } #ifdef HAVE_MYSQL_SSL_SET char *ssl_client_key, *ssl_client_cert, *ssl_ca_cert, *ssl_ca_path, *ssl_cipher; VALUE r_ssl; if (rb_obj_is_kind_of(r_query, rb_cHash)) { r_ssl = rb_hash_aref(r_query, rb_str_new2("ssl")); if (rb_obj_is_kind_of(r_ssl, rb_cHash)) { ssl_client_key = data_objects_get_uri_option(r_ssl, "client_key"); ssl_client_cert = data_objects_get_uri_option(r_ssl, "client_cert"); ssl_ca_cert = data_objects_get_uri_option(r_ssl, "ca_cert"); ssl_ca_path = data_objects_get_uri_option(r_ssl, "ca_path"); ssl_cipher = data_objects_get_uri_option(r_ssl, "cipher"); data_objects_assert_file_exists(ssl_client_key, "client_key doesn't exist"); data_objects_assert_file_exists(ssl_client_cert, "client_cert doesn't exist"); data_objects_assert_file_exists(ssl_ca_cert, "ca_cert doesn't exist"); mysql_ssl_set(db, ssl_client_key, ssl_client_cert, ssl_ca_cert, ssl_ca_path, ssl_cipher); } else if (r_ssl != Qnil) { rb_raise(rb_eArgError, "ssl must be passed a hash"); } } #endif unsigned long client_flags = 0; MYSQL *result = mysql_real_connect( db, host, user, password, database, port, socket, client_flags ); if (!result) { do_mysql_raise_error(self, db, Qnil); } #ifdef HAVE_MYSQL_GET_SSL_CIPHER const char *ssl_cipher_used = mysql_get_ssl_cipher(db); if (ssl_cipher_used) { rb_iv_set(self, "@ssl_cipher", rb_str_new2(ssl_cipher_used)); } #endif #ifdef MYSQL_OPT_RECONNECT my_bool reconnect = 1; mysql_options(db, MYSQL_OPT_RECONNECT, &reconnect); #endif // We only support encoding for MySQL versions providing mysql_set_character_set. // Without this function there are potential issues with mysql_real_escape_string // since that doesn't take the character set into consideration when setting it // using a SET CHARACTER SET query. Since we don't want to stimulate these possible // issues we simply ignore it and assume the user has configured this correctly. #ifdef HAVE_MYSQL_SET_CHARACTER_SET // Set the connections character set VALUE encoding = rb_iv_get(self, "@encoding"); VALUE my_encoding = rb_hash_aref(data_objects_const_get(mEncoding, "MAP"), encoding); if (my_encoding != Qnil) { int encoding_error = mysql_set_character_set(db, rb_str_ptr_readonly(my_encoding)); if (encoding_error != 0) { do_mysql_raise_error(self, db, Qnil); } else { #ifdef HAVE_RUBY_ENCODING_H rb_iv_set(self, "@encoding_id", INT2FIX(rb_enc_find_index(rb_str_ptr_readonly(encoding)))); #endif rb_iv_set(self, "@my_encoding", my_encoding); } } else { rb_warn("Encoding %s is not a known Ruby encoding for MySQL\n", rb_str_ptr_readonly(encoding)); rb_iv_set(self, "@encoding", rb_str_new2("UTF-8")); #ifdef HAVE_RUBY_ENCODING_H rb_iv_set(self, "@encoding_id", INT2FIX(rb_enc_find_index("UTF-8"))); #endif rb_iv_set(self, "@my_encoding", rb_str_new2("utf8")); } #endif // Disable sql_auto_is_null do_mysql_cCommand_execute(Qnil, self, db, rb_str_new2("SET sql_auto_is_null = 0")); // removed NO_AUTO_VALUE_ON_ZERO because of MySQL bug http://bugs.mysql.com/bug.php?id=42270 // added NO_BACKSLASH_ESCAPES so that backslashes should not be escaped as in other databases // For really anscient MySQL versions we don't attempt any strictness #ifdef HAVE_MYSQL_GET_SERVER_VERSION //4.x versions do not support certain session parameters if (mysql_get_server_version(db) < 50000) { do_mysql_cCommand_execute(Qnil, self, db, rb_str_new2("SET SESSION sql_mode = 'ANSI,NO_DIR_IN_CREATE,NO_UNSIGNED_SUBTRACTION'")); } else { do_mysql_cCommand_execute(Qnil, self, db, rb_str_new2("SET SESSION sql_mode = 'ANSI,NO_BACKSLASH_ESCAPES,NO_DIR_IN_CREATE,NO_ENGINE_SUBSTITUTION,NO_UNSIGNED_SUBTRACTION,TRADITIONAL'")); } #endif rb_iv_set(self, "@connection", Data_Wrap_Struct(rb_cObject, 0, 0, db)); }
void data_objects_common_init(void) { rb_require("bigdecimal"); rb_require("rational"); rb_require("date"); rb_require("data_objects"); // Needed by data_objects_const_get DO_ID_CONST_GET = rb_intern("const_get"); // Get references classes needed for Date/Time parsing rb_cDate = data_objects_const_get(rb_mKernel, "Date"); rb_cDateTime = data_objects_const_get(rb_mKernel, "DateTime"); rb_cBigDecimal = data_objects_const_get(rb_mKernel, "BigDecimal"); DO_ID_NEW = rb_intern("new"); #ifdef RUBY_LESS_THAN_186 DO_ID_NEW_DATE = rb_intern("new0"); #else DO_ID_NEW_DATE = rb_intern("new!"); #endif DO_ID_CONST_GET = rb_intern("const_get"); DO_ID_RATIONAL = rb_intern("Rational"); DO_ID_ESCAPE = rb_intern("escape_sql"); DO_ID_STRFTIME = rb_intern("strftime"); DO_ID_LOG = rb_intern("log"); // Get references to the Extlib module mExtlib = data_objects_const_get(rb_mKernel, "Extlib"); rb_cByteArray = data_objects_const_get(mExtlib, "ByteArray"); // Get references to the DataObjects module and its classes mDO = data_objects_const_get(rb_mKernel, "DataObjects"); cDO_Quoting = data_objects_const_get(mDO, "Quoting"); cDO_Connection = data_objects_const_get(mDO, "Connection"); cDO_Command = data_objects_const_get(mDO, "Command"); cDO_Result = data_objects_const_get(mDO, "Result"); cDO_Reader = data_objects_const_get(mDO, "Reader"); cDO_Logger = data_objects_const_get(mDO, "Logger"); cDO_Logger_Message = data_objects_const_get(cDO_Logger, "Message"); cDO_Extension = data_objects_const_get(mDO, "Extension"); eDO_ConnectionError = data_objects_const_get(mDO, "ConnectionError"); eDO_DataError = data_objects_const_get(mDO, "DataError"); rb_global_variable(&DO_ID_NEW_DATE); rb_global_variable(&DO_ID_RATIONAL); rb_global_variable(&DO_ID_CONST_GET); rb_global_variable(&DO_ID_ESCAPE); rb_global_variable(&DO_ID_LOG); rb_global_variable(&DO_ID_NEW); rb_global_variable(&rb_cDate); rb_global_variable(&rb_cDateTime); rb_global_variable(&rb_cBigDecimal); rb_global_variable(&rb_cByteArray); rb_global_variable(&mDO); rb_global_variable(&cDO_Logger_Message); rb_global_variable(&eDO_ConnectionError); rb_global_variable(&eDO_DataError); tzset(); }