DBD-MariaDB

 view release on metacpan or  search on metacpan

dbdimp.c  view on Meta::CPAN

  }
#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)))

dbdimp.c  view on Meta::CPAN

            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)

dbdimp.c  view on Meta::CPAN

{
  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 )