DBD-mysql

 view release on metacpan or  search on metacpan

mysql.xs  view on Meta::CPAN

/* Hej, Emacs, this is -*- C -*- mode!

   Copyright (c) 2003      Rudolf Lippan
   Copyright (c) 1997-2003 Jochen Wiedmann

   You may distribute under the terms of either the GNU General Public
   License or the Artistic License, as specified in the Perl README file.

*/


#include "dbdimp.h"
#include "constants.h"

#include <errno.h>
#include <string.h>

#define ASYNC_CHECK_XS(h)\
    if(imp_dbh->async_query_in_flight) {\
        do_error(h, 2000, "Calling a synchronous function on an asynchronous handle", "HY000");\
        XSRETURN_UNDEF;\
    }


DBISTATE_DECLARE;


MODULE = DBD::mysql	PACKAGE = DBD::mysql

INCLUDE: mysql.xsi

MODULE = DBD::mysql	PACKAGE = DBD::mysql

double
constant(name, arg)
    char* name
    char* arg
  CODE:
    RETVAL = mysql_constant(name, arg);
  OUTPUT:
    RETVAL

SV*
client_version(pkg)
  CODE:
    RETVAL = my_ulonglong2sv(aTHX_ mysql_get_client_version());
  OUTPUT:
    RETVAL

MODULE = DBD::mysql	PACKAGE = DBD::mysql::dr

void
_ListDBs(drh, host=NULL, port=NULL, user=NULL, password=NULL)
    SV *        drh
    char *	host
    char *      port
    char *      user
    char *      password
  PPCODE:
{
    MYSQL mysql;
    mysql.net.fd = -1;
    MYSQL* sock = mysql_dr_connect(drh, &mysql, NULL, host, port, user, password,
				   NULL, NULL);
    if (sock != NULL)
    {
      MYSQL_ROW cur;
      MYSQL_RES* res = mysql_list_dbs(sock, NULL);
      if (!res)
      {
        do_error(drh, mysql_errno(sock), mysql_error(sock), mysql_sqlstate(sock));
      }
      else
      {
	EXTEND(sp, mysql_num_rows(res));
	while ((cur = mysql_fetch_row(res)))
        {
	  PUSHs(sv_2mortal((SV*)newSVpvn(cur[0], strlen(cur[0]))));
	}
	mysql_free_result(res);
      }
      mysql_close(sock);
    }
}


MODULE = DBD::mysql    PACKAGE = DBD::mysql::db


void
type_info_all(dbh)
  SV* dbh
  PPCODE:
{
  /* 	static AV* types = NULL; */
  /* 	if (!types) { */
  /* 	    D_imp_dbh(dbh); */
  /* 	    if (!(types = dbd_db_type_info_all(dbh, imp_dbh))) { */
  /* 	        croak("Cannot create types array (out of memory?)"); */
  /* 	    } */
  /* 	} */
  /* 	ST(0) = sv_2mortal(newRV_inc((SV*) types)); */
  D_imp_dbh(dbh);
  ASYNC_CHECK_XS(dbh);
  ST(0) = sv_2mortal(newRV_noinc((SV*) dbd_db_type_info_all(dbh,
                                                            imp_dbh)));
  XSRETURN(1);
}


void
_ListDBs(dbh)
  SV*	dbh
  PPCODE:
  MYSQL_RES* res;
  MYSQL_ROW cur;

  D_imp_dbh(dbh);

  ASYNC_CHECK_XS(dbh);

  res = mysql_list_dbs(imp_dbh->pmysql, NULL);
  if (!res  &&
      (!mysql_db_reconnect(dbh)  ||
       !(res = mysql_list_dbs(imp_dbh->pmysql, NULL))))
{
  do_error(dbh, mysql_errno(imp_dbh->pmysql),
           mysql_error(imp_dbh->pmysql), mysql_sqlstate(imp_dbh->pmysql));
}
else
{
  EXTEND(sp, mysql_num_rows(res));
  while ((cur = mysql_fetch_row(res)))
  {
    PUSHs(sv_2mortal((SV*)newSVpvn(cur[0], strlen(cur[0]))));
  }
  mysql_free_result(res);
}


void
do(dbh, statement, attr=Nullsv, ...)
  SV *        dbh
  SV *	statement
  SV *        attr
  PROTOTYPE: $$;$@
  CODE:
{
  D_imp_dbh(dbh);
  int num_params= 0;
  int retval;
  struct imp_sth_ph_st* params= NULL;
  MYSQL_RES* result= NULL;
  SV* async = NULL;
  int next_result_rc;
  STRLEN slen;
  char            *str_ptr, *buffer;
  int             has_binded;
  int             buffer_length;
  int             buffer_type= 0;
  int             use_server_side_prepare= 0;
  int             disable_fallback_for_server_prepare= 0;
  MYSQL_STMT      *stmt= NULL;
  MYSQL_BIND      *bind= NULL;
    ASYNC_CHECK_XS(dbh);
    if ((!DBIc_has(imp_dbh, DBIcf_ACTIVE)) &&
        (!mysql_db_reconnect(dbh)))
      XSRETURN_UNDEF;
    while (mysql_next_result(imp_dbh->pmysql)==0)
    {
      MYSQL_RES* res = mysql_use_result(imp_dbh->pmysql);
      if (res)
        mysql_free_result(res);
      }

mysql.xs  view on Meta::CPAN

            if (DBIc_DBISTATE(imp_dbh)->debug >= 2)
              PerlIO_printf(DBIc_LOGPIO(imp_dbh),
                            "\t<- do() ERROR: %s\n",
                            mysql_error(imp_dbh->pmysql));

              do_error(dbh, mysql_errno(imp_dbh->pmysql),
                       mysql_error(imp_dbh->pmysql),
                       mysql_sqlstate(imp_dbh->pmysql));
              retval= -2;
          }
    }
  /* remember that dbd_st_execute must return <= -2 for error	*/
  if (retval == 0)		/* ok with no rows affected	*/
    XST_mPV(0, "0E0");	/* (true but zero)		*/
  else if (retval < -1)	/* -1 == unknown number of rows	*/
    XST_mUNDEF(0);		/* <= -2 means error   		*/
  else
    XST_mIV(0, retval);	/* typically 1, rowcount or -1	*/
}


SV*
ping(dbh)
    SV* dbh;
  PROTOTYPE: $
  CODE:
    {
      int retval;
/* MySQL 5.7 below 5.7.18 is affected by Bug #78778.
 * MySQL 5.7.18 and higher (including 8.0.3) is affected by Bug #89139.
 *
 * Once Bug #89139 is fixed we can adjust the upper bound of this check.
 *
 * https://bugs.mysql.com/bug.php?id=78778
 * https://bugs.mysql.com/bug.php?id=89139 */
      unsigned long long insertid;

      D_imp_dbh(dbh);
      ASYNC_CHECK_XS(dbh);
      insertid = mysql_insert_id(imp_dbh->pmysql);
      retval = (mysql_ping(imp_dbh->pmysql) == 0);
      if (!retval) {
	if (mysql_db_reconnect(dbh)) {
	  retval = (mysql_ping(imp_dbh->pmysql) == 0);
	}
      }
      imp_dbh->pmysql->insert_id = insertid;
      RETVAL = boolSV(retval);
    }
  OUTPUT:
    RETVAL



void
quote(dbh, str, type=NULL)
    SV* dbh
    SV* str
    SV* type
  PROTOTYPE: $$;$
  PPCODE:
    {
        SV* quoted;

        D_imp_dbh(dbh);
        ASYNC_CHECK_XS(dbh);

        quoted = dbd_db_quote(dbh, str, type);
	ST(0) = quoted ? sv_2mortal(quoted) : str;
	XSRETURN(1);
    }

void mysql_fd(dbh)
    SV* dbh
  PPCODE:
    {
        D_imp_dbh(dbh);
        if(imp_dbh->pmysql->net.fd != -1) {
            XSRETURN_IV(imp_dbh->pmysql->net.fd);
        } else {
            XSRETURN_UNDEF;
        }
    }

void mysql_async_result(dbh)
    SV* dbh
  PPCODE:
    {
        int retval;

        retval = mysql_db_async_result(dbh, NULL);

        if(retval > 0) {
            XSRETURN_IV(retval);
        } else if(retval == 0) {
            XSRETURN_PV("0E0");
        } else {
            XSRETURN_UNDEF;
        }
    }

void mysql_async_ready(dbh)
    SV* dbh
  PPCODE:
    {
        int retval;

        retval = mysql_db_async_ready(dbh);
        if(retval > 0) {
            XSRETURN_YES;
        } else if(retval == 0) {
            XSRETURN_NO;
        } else {
            XSRETURN_UNDEF;
        }
    }

void _async_check(dbh)
    SV* dbh
  PPCODE:
    {
        D_imp_dbh(dbh);
        ASYNC_CHECK_XS(dbh);
        XSRETURN_YES;
    }

MODULE = DBD::mysql    PACKAGE = DBD::mysql::st

int
more_results(sth)
    SV *	sth
    CODE:
{
  D_imp_sth(sth);
  if (dbd_st_more_results(sth, imp_sth))
  {
    RETVAL=1;
  }
  else
  {
    RETVAL=0;
  }
}
    OUTPUT:
      RETVAL

int
dataseek(sth, pos)
    SV* sth
    int pos
  PROTOTYPE: $$
  CODE:
{
  D_imp_sth(sth);
  if (imp_sth->use_server_side_prepare)
  {
    if (imp_sth->use_mysql_use_result || 1)
    {
      if (imp_sth->result && imp_sth->stmt)
      {
        mysql_stmt_data_seek(imp_sth->stmt, pos);
        imp_sth->fetch_done=0;
        RETVAL = 1;
      }
      else
      {
        RETVAL = 0;
        do_error(sth, JW_ERR_NOT_ACTIVE, "Statement not active" ,NULL);
      }
    }
    else
    {
      RETVAL = 0;
      do_error(sth, JW_ERR_NOT_ACTIVE, "No result set" ,NULL);
    }
  }
  else
  {
  if (imp_sth->result) {
    mysql_data_seek(imp_sth->result, pos);
    RETVAL = 1;
  } else {
    RETVAL = 0;
    do_error(sth, JW_ERR_NOT_ACTIVE, "Statement not active" ,NULL);
  }
  }
}
  OUTPUT:
    RETVAL

void
rows(sth)
    SV* sth
  CODE:
    D_imp_sth(sth);
    char buf[64];
    D_imp_dbh_from_sth;
    if(imp_dbh->async_query_in_flight) {
        if(mysql_db_async_result(sth, &imp_sth->result) < 0) {
            XSRETURN_UNDEF;
        }
    }

  /* fix to make rows able to handle errors and handle max value from 
     affected rows.
     if mysql_affected_row returns an error, it's value is 18446744073709551614,
     while a (my_ulonglong)-1 is  18446744073709551615, so we have to add 1 to
     imp_sth->row_num to know if there's an error
  */
  if (imp_sth->row_num+1 ==  (my_ulonglong) -1)
    sprintf(buf, "%d", -1);
  else
    sprintf(buf, "%lu", imp_sth->row_num);

  ST(0) = sv_2mortal(newSVpvn(buf, strlen(buf)));

int mysql_async_result(sth)
    SV* sth
  CODE:
    {
        D_imp_sth(sth);
        int retval;

        retval= mysql_db_async_result(sth, &imp_sth->result);

        if(retval > 0) {
            imp_sth->row_num = retval;
            XSRETURN_IV(retval);
        } else if(retval == 0) {
            imp_sth->row_num = retval;
            XSRETURN_PV("0E0");
        } else {
            XSRETURN_UNDEF;
        }
    }
  OUTPUT:
    RETVAL

void mysql_async_ready(sth)
    SV* sth
  PPCODE:
    {
        int retval;

        retval = mysql_db_async_ready(sth);
        if(retval > 0) {
            XSRETURN_YES;
        } else if(retval == 0) {
            XSRETURN_NO;
        } else {
            XSRETURN_UNDEF;
        }
    }

void _async_check(sth)
    SV* sth
  PPCODE:
    {
        D_imp_sth(sth);
        D_imp_dbh_from_sth;
        ASYNC_CHECK_XS(sth);
        XSRETURN_YES;
    }


MODULE = DBD::mysql    PACKAGE = DBD::mysql::GetInfo

# This probably should be grabed out of some ODBC types header file
#define SQL_CATALOG_NAME_SEPARATOR 41
#define SQL_CATALOG_TERM 42
#define SQL_DBMS_VER 18
#define SQL_IDENTIFIER_QUOTE_CHAR 29
#define SQL_MAXIMUM_STATEMENT_LENGTH 105
#define SQL_MAXIMUM_TABLES_IN_SELECT 106
#define SQL_MAX_TABLE_NAME_LEN 35
#define SQL_SERVER_NAME 13
#define SQL_ASYNC_MODE 10021
#define SQL_MAX_ASYNC_CONCURRENT_STATEMENTS 10022

#define SQL_AM_NONE       0
#define SQL_AM_CONNECTION 1
#define SQL_AM_STATEMENT  2


#  dbd_mysql_getinfo()
#  Return ODBC get_info() information that must needs be accessed from C
#  This is an undocumented function that should only
#  be used by DBD::mysql::GetInfo.

void
dbd_mysql_get_info(dbh, sql_info_type)
    SV* dbh
    SV* sql_info_type
  CODE:
    D_imp_dbh(dbh);
    IV type = 0;
    SV* retsv=NULL;

    if (SvMAGICAL(sql_info_type))
        mg_get(sql_info_type);

    if (SvOK(sql_info_type))
    	type = SvIV(sql_info_type);
    else
    	croak("get_info called with an invalied parameter");
    
    switch(type) {
    	case SQL_CATALOG_NAME_SEPARATOR:
	    /* (dbc->flag & FLAG_NO_CATALOG) ? WTF is in flag ? */
	    retsv = newSVpvn(".",1);
	    break;
	case SQL_CATALOG_TERM:
	    /* (dbc->flag & FLAG_NO_CATALOG) ? WTF is in flag ? */
	    retsv = newSVpvn("database",8);
	    break;
	case SQL_DBMS_VER:
	    retsv = newSVpvn(



( run in 0.741 second using v1.01-cache-2.11-cpan-71847e10f99 )