DBD-MariaDB
view release on metacpan or search on metacpan
}
#endif
return 0;
}
/***************************************************************************
*
* Name: mariadb_dr_connect
*
* Purpose: Replacement for mysql_connect
*
* Input: dbh - database handle being connected
* imp_dbh_t *imp_dbh - Pointer to internal dbh structure
* char* mysql_socket - Name of a UNIX socket being used
* or NULL
* char* host - Host name being used or NULL for localhost
* unsigned int port - Port number being used or 0 for default
* char* user - User name being used or NULL
* char* password - Password being used or NULL
* char* dbname - Database name being used or NULL
*
* Returns: TRUE for success, FALSE otherwise; mariadb_dr_do_error will
* be called in the latter case
*
**************************************************************************/
static bool mariadb_dr_connect(
SV* dbh,
imp_dbh_t *imp_dbh,
char* mysql_socket,
char* host,
unsigned int port,
char* user,
char* password,
char* dbname)
{
unsigned int client_flag;
bool client_supports_utf8mb4;
bool connected;
unsigned int read_timeout, write_timeout;
MYSQL *sock;
dTHX;
D_imp_xxh(dbh);
SV *sv = DBIc_IMP_DATA(imp_dbh);
D_imp_drh_from_dbh;
#ifdef MARIADB_PACKAGE_VERSION
bool read_timeout_set = FALSE;
bool write_timeout_set = FALSE;
#endif
if (DBIc_TRACE_LEVEL(imp_xxh) >= 2)
PerlIO_printf(DBIc_LOGPIO(imp_xxh),
"imp_dbh->mariadb_dr_connect: host = |%s|, port = %u,"
" uid = %s, pwd = %s\n",
host ? host : "NULL", port,
user ? user : "NULL",
!password ? "NULL" : !password[0] ? "" : "****");
#if !defined(HAVE_EMBEDDED) && defined(HAVE_BROKEN_INIT)
if (imp_drh->non_embedded_finished)
{
mariadb_dr_do_error(dbh, CR_CONNECTION_ERROR, "Connection error: Method disconnect_all() was already called and library functions unloaded", "HY000");
return FALSE;
}
#endif
/* host=localhost means to connect via unix socket, host=embedded means to use embedded server, so do not allow specifying port */
if (port && host && (strcmp(host, "localhost") == 0 || strcmp(host, "embedded") == 0))
{
mariadb_dr_do_error(dbh, CR_CONNECTION_ERROR, "Connection error: port cannot be specified when host is localhost or embedded", "HY000");
return FALSE;
}
/* when connecting via unix socket do not allow specifying port or host != localhost */
if (mysql_socket && (port || (host && strcmp(host, "localhost") != 0)))
{
mariadb_dr_do_error(dbh, CR_CONNECTION_ERROR, "Connection error: host or port cannot be specified together with mariadb_socket", "HY000");
return FALSE;
}
if (host && strcmp(host, "embedded") == 0)
{
#ifndef HAVE_EMBEDDED
mariadb_dr_do_error(dbh, CR_CONNECTION_ERROR, "Connection error: Embedded server is not supported", "HY000");
return FALSE;
#endif
if (sv && SvROK(sv))
{
SV** svp;
SV *embedded_groups = NULL;
SV *embedded_args = NULL;
STRLEN options_len;
char * options;
int server_args_cnt= 0;
int server_groups_cnt= 0;
int rc= 0;
char ** server_args = NULL;
char ** server_groups = NULL;
HV* hv = (HV*) SvRV(sv);
if (SvTYPE(hv) != SVt_PVHV)
return FALSE;
if (imp_drh->instances == 0 && !imp_drh->non_embedded_started)
{
if ((svp = hv_fetchs(hv, "mariadb_embedded_groups", FALSE)) && *svp && SvTRUE(*svp))
{
embedded_groups = *svp;
options = SvPVutf8_nomg(embedded_groups, options_len);
if (strlen(options) != options_len)
{
error_nul_character(dbh, "mariadb_embedded_groups");
return FALSE;
}
if ((server_groups_cnt=count_embedded_options(options)))
{
/* number of server_groups always server_groups+1 */
server_groups = fill_out_embedded_options(options, 0, options_len, ++server_groups_cnt);
if (DBIc_TRACE_LEVEL(imp_xxh) >= 2)
{
PerlIO_printf(DBIc_LOGPIO(imp_xxh),
"Groups names passed to embedded server:\n");
print_embedded_options(DBIc_LOGPIO(imp_xxh), server_groups, server_groups_cnt);
}
}
}
if ((svp = hv_fetchs(hv, "mariadb_embedded_options", FALSE)) && *svp && SvTRUE(*svp))
{
embedded_args = *svp;
options = SvPVutf8_nomg(embedded_args, options_len);
if (strlen(options) != options_len)
{
if (server_groups_cnt)
free_embedded_options(server_groups, server_groups_cnt);
error_nul_character(dbh, "mariadb_embedded_options");
return FALSE;
}
if ((server_args_cnt=count_embedded_options(options)))
rc += abs(sv_cmp_flags(*svp, imp_drh->embedded_args, 0));
if (rc)
{
mariadb_dr_do_error(dbh, CR_CONNECTION_ERROR, "Connection error: Embedded server was already started, cannot pass different init parameters to embedded server", "HY000");
return FALSE;
}
}
else
{
mariadb_dr_do_error(dbh, CR_CONNECTION_ERROR, "Connection error: Unknown internal state (possible bug in driver)", "HY000");
return FALSE;
}
}
}
else
{
if (imp_drh->instances == 0 && !imp_drh->non_embedded_started)
{
/* negative value means to not start embedded server and just to initialize client library */
/* initializing client library is needed prior to any other mysql_* call from client library */
if (mysql_server_init(-1, NULL, NULL))
{
error_no_connection(dbh, "Connection error: Cannot initialize client library");
return FALSE;
}
imp_drh->non_embedded_started = TRUE;
}
}
sock = imp_dbh->pmysql = mysql_init(NULL);
if (!sock)
{
error_no_connection(dbh, "Connection error: Cannot initialize client structures");
mariadb_db_disconnect(dbh, imp_dbh);
return FALSE;
}
imp_drh->instances++;
client_flag = CLIENT_FOUND_ROWS | CLIENT_MULTI_RESULTS;
DBIc_set(imp_dbh, DBIcf_AutoCommit, TRUE);
if (sv && SvROK(sv))
{
HV* hv = (HV*) SvRV(sv);
HV* processed = newHV();
HE* he;
SV** svp;
sv_2mortal(newRV_noinc((SV *)processed)); /* Automatically free HV processed */
/* These options are already handled and processed */
(void)hv_stores(processed, "host", &PL_sv_yes);
(void)hv_stores(processed, "port", &PL_sv_yes);
(void)hv_stores(processed, "user", &PL_sv_yes);
(void)hv_stores(processed, "password", &PL_sv_yes);
(void)hv_stores(processed, "database", &PL_sv_yes);
(void)hv_stores(processed, "mariadb_socket", &PL_sv_yes);
#ifdef HAVE_EMBEDDED
if (host && strcmp(host, "embedded") == 0)
{
(void)hv_stores(processed, "mariadb_embedded_groups", &PL_sv_yes);
(void)hv_stores(processed, "mariadb_embedded_options", &PL_sv_yes);
mysql_options(sock, MYSQL_OPT_USE_EMBEDDED_CONNECTION, NULL);
imp_dbh->is_embedded = TRUE;
host = NULL;
}
else
{
mysql_options(sock, MYSQL_OPT_USE_REMOTE_CONNECTION, NULL);
}
#endif
/* thanks to Peter John Edwards for mysql_init_command */
(void)hv_stores(processed, "mariadb_init_command", &PL_sv_yes);
if ((svp = hv_fetchs(hv, "mariadb_init_command", FALSE)) && *svp && SvTRUE(*svp))
{
STRLEN len;
char* df = SvPVutf8_nomg(*svp, len);
if (strlen(df) != len)
{
error_nul_character(dbh, "mariadb_init_command");
mariadb_db_disconnect(dbh, imp_dbh);
return FALSE;
}
if (DBIc_TRACE_LEVEL(imp_xxh) >= 2)
PerlIO_printf(DBIc_LOGPIO(imp_xxh),
"imp_dbh->mariadb_dr_connect: Setting"
" init command (%s).\n", df);
mysql_options(sock, MYSQL_INIT_COMMAND, df);
}
(void)hv_stores(processed, "mariadb_compression", &PL_sv_yes);
if ((svp = hv_fetchs(hv, "mariadb_compression", FALSE)) && *svp && SvTRUE(*svp))
{
if (DBIc_TRACE_LEVEL(imp_xxh) >= 2)
PerlIO_printf(DBIc_LOGPIO(imp_xxh),
"imp_dbh->mariadb_dr_connect: Enabling"
" compression.\n");
mysql_options(sock, MYSQL_OPT_COMPRESS, NULL);
}
(void)hv_stores(processed, "mariadb_connect_timeout", &PL_sv_yes);
if ((svp = hv_fetchs(hv, "mariadb_connect_timeout", FALSE)) && *svp)
{
UV uv = SvUV(*svp);
unsigned int to = (uv <= UINT_MAX ? uv : UINT_MAX);
if (DBIc_TRACE_LEVEL(imp_xxh) >= 2)
PerlIO_printf(DBIc_LOGPIO(imp_xxh),
"imp_dbh->mariadb_dr_connect: Setting"
" connect timeout (%u).\n", to);
mysql_options(sock, MYSQL_OPT_CONNECT_TIMEOUT,
(const char *)&to);
}
(void)hv_stores(processed, "mariadb_write_timeout", &PL_sv_yes);
if ((svp = hv_fetchs(hv, "mariadb_write_timeout", FALSE)) && *svp)
{
UV uv = SvUV(*svp);
write_timeout = (uv <= UINT_MAX ? uv : UINT_MAX);
#ifdef MARIADB_PACKAGE_VERSION
write_timeout_set = TRUE;
#endif
if (DBIc_TRACE_LEVEL(imp_xxh) >= 2)
{
dTHX;
D_imp_drh_from_dbh;
PERL_UNUSED_ARG(dbh);
/* We assume that disconnect will always work */
/* since most errors imply already disconnected. */
mariadb_db_close_mysql(aTHX_ imp_drh, imp_dbh);
/* We don't free imp_dbh since a reference still exists */
/* The DESTROY method is the only one to 'free' memory. */
return 1;
}
/***************************************************************************
*
* Name: mariadb_dr_discon_all
*
* Purpose: Disconnect all database handles at shutdown time
*
* Input: dbh - database handle being disconnected
* imp_dbh - drivers private database handle data
*
* Returns: 1 for success, 0 otherwise
*
**************************************************************************/
int mariadb_dr_discon_all (SV *drh, imp_drh_t *imp_drh) {
dTHX;
int ret;
struct mariadb_list_entry *entry;
PERL_UNUSED_ARG(drh);
while ((entry = imp_drh->taken_pmysqls))
{
mariadb_dr_close_mysql(aTHX_ imp_drh, (MYSQL *)entry->data);
mariadb_list_remove(imp_drh->taken_pmysqls, entry);
}
while (imp_drh->active_imp_dbhs)
mariadb_db_close_mysql(aTHX_ imp_drh, (imp_dbh_t *)imp_drh->active_imp_dbhs->data);
ret = 1;
if (imp_drh->instances)
{
warn("DBD::MariaDB disconnect_all: %lu database handlers were not released (possible bug in driver)", imp_drh->instances);
ret = 0;
}
if (imp_drh->embedded_started)
{
warn("DBD::MariaDB disconnect_all: Embedded server was not properly stopped (possible bug in driver)");
ret = 0;
}
/* Some MariaDB and MySQL clients with Embedded server support have a bug which cause segfault
* when trying to call mysql_server_end() when Embedded server was not started. So do not call
* mysql_server_end() for normal connections when we have Embedded server support. */
#ifndef HAVE_EMBEDDED
if (imp_drh->non_embedded_started)
{
#if defined(HAVE_DEINITIALIZE_SSL) || !defined(HAVE_PROBLEM_WITH_OPENSSL)
#ifndef HAVE_BROKEN_INIT
warn("DBD::MariaDB disconnect_all: Client library was not properly deinitialized (possible bug in driver)");
ret = 0;
#else
mysql_server_end();
imp_drh->non_embedded_started = FALSE;
imp_drh->non_embedded_finished = TRUE;
#endif
#endif
}
#endif
if (imp_drh->embedded_args)
{
warn("DBD::MariaDB disconnect_all: mariadb_embedded_options was not released (possible bug in driver)");
ret = 0;
}
if (imp_drh->embedded_groups)
{
warn("DBD::MariaDB disconnect_all: mariadb_embedded_groups was not released (possible bug in driver)");
ret = 0;
}
return ret;
}
/****************************************************************************
*
* Name: mariadb_db_destroy
*
* Purpose: Our part of the dbh destructor
*
* Input: dbh - database handle being destroyed
* imp_dbh - drivers private database handle data
*
* Returns: Nothing
*
**************************************************************************/
void mariadb_db_destroy(SV* dbh, imp_dbh_t* imp_dbh) {
/*
* Being on the safe side never hurts ...
*/
if (DBIc_ACTIVE(imp_dbh))
{
if (!DBIc_has(imp_dbh, DBIcf_AutoCommit) && imp_dbh->pmysql)
if (mysql_rollback(imp_dbh->pmysql))
mariadb_dr_do_error(dbh, mysql_errno(imp_dbh->pmysql), mysql_error(imp_dbh->pmysql), mysql_sqlstate(imp_dbh->pmysql));
mariadb_db_disconnect(dbh, imp_dbh);
}
/* Tell DBI, that dbh->destroy must no longer be called */
DBIc_off(imp_dbh, DBIcf_IMPSET);
}
( run in 1.446 second using v1.01-cache-2.11-cpan-71847e10f99 )