VALUE do_postgres_cConnection_initialize(VALUE self, VALUE uri) { rb_iv_set(self, "@using_socket", Qfalse); VALUE r_host = rb_funcall(uri, rb_intern("host"), 0); if (r_host != Qnil) { rb_iv_set(self, "@host", r_host); } VALUE r_user = rb_funcall(uri, rb_intern("user"), 0); if (r_user != Qnil) { rb_iv_set(self, "@user", r_user); } VALUE r_password = rb_funcall(uri, rb_intern("password"), 0); if (r_password != Qnil) { rb_iv_set(self, "@password", r_password); } VALUE r_path = rb_funcall(uri, rb_intern("path"), 0); if (r_path != Qnil) { rb_iv_set(self, "@path", r_path); } VALUE r_port = rb_funcall(uri, rb_intern("port"), 0); if (r_port != Qnil) { r_port = rb_funcall(r_port, rb_intern("to_s"), 0); rb_iv_set(self, "@port", r_port); } // Pull the querystring off the URI VALUE r_query = rb_funcall(uri, rb_intern("query"), 0); rb_iv_set(self, "@query", r_query); const char *encoding = data_objects_get_uri_option(r_query, "encoding"); if (!encoding) { encoding = data_objects_get_uri_option(r_query, "charset"); if (!encoding) { encoding = "UTF-8"; } } rb_iv_set(self, "@encoding", rb_str_new2(encoding)); PGconn *db = NULL; do_postgres_full_connect(self, db); rb_iv_set(self, "@uri", uri); return Qtrue; }
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)); }