/************** MyConn C++ Program Source Code File (.CPP) **************/ /* PROGRAM NAME: MYCONN */ /* ------------- */ /* Version 1.9 */ /* */ /* COPYRIGHT: */ /* ---------- */ /* (C) Copyright to the author Olivier BERTRAND 2007-2017 */ /* */ /* WHAT THIS PROGRAM DOES: */ /* ----------------------- */ /* Implements a connection to MySQL. */ /* It can optionally use the embedded MySQL library. */ /* */ /* WHAT YOU NEED TO COMPILE THIS PROGRAM: */ /* -------------------------------------- */ /* */ /* REQUIRED FILES: */ /* --------------- */ /* MYCONN.CPP - Source code */ /* MYCONN.H - MYCONN class declaration file */ /* GLOBAL.H - Global declaration file */ /* */ /* REQUIRED LIBRARIES: */ /* ------------------- */ /* Large model C library */ /* */ /* REQUIRED PROGRAMS: */ /* ------------------ */ /* IBM, Borland, GNU or Microsoft C++ Compiler and Linker */ /* */ /************************************************************************/ #include"my_global.h" #if !defined(MYSQL_PREPARED_STATEMENTS) #include"my_sys.h" #include"mysqld_error.h" #endif// !MYSQL_PREPARED_STATEMENTS #ifdefined(_WIN32) //#include <windows.h> #else// !_WIN32 #include"osutil.h" #endif// !_WIN32
#include"global.h" #include"plgdbsem.h" #include"plgcnx.h"// For DB types #include"resource.h" //#include "value.h" //#include "valblk.h" #include"xobject.h" #define DLL_EXPORT // Items are exported from this DLL #include"myconn.h"
//extern "C" int zconv; int GetConvSize(void); extern MYSQL_PLUGIN_IMPORT uint mysqld_port; extern MYSQL_PLUGIN_IMPORT char *mysqld_unix_port;
DllExport void PushWarning(PGLOBAL, THD*, int level = 1);
// Returns the current used port
uint GetDefaultPort(void)
{ return mysqld_port;
} // end of GetDefaultPort
/************************************************************************/ /* MyColumns: constructs the result blocks containing all columns */ /* of a MySQL table or view. */ /* info = TRUE to get catalog column information. */ /************************************************************************/
PQRYRES MyColumns(PGLOBAL g, THD *thd, constchar *host, constchar *db, constchar *user, constchar *pwd, constchar *table, constchar *colpat, int port, bool info)
{ int buftyp[] = {TYPE_STRING, TYPE_SHORT, TYPE_STRING, TYPE_INT,
TYPE_STRING, TYPE_SHORT, TYPE_SHORT, TYPE_SHORT,
TYPE_STRING, TYPE_STRING, TYPE_STRING, TYPE_STRING,
TYPE_STRING};
XFLD fldtyp[] = {FLD_NAME, FLD_TYPE, FLD_TYPENAME, FLD_PREC,
FLD_KEY, FLD_SCALE, FLD_RADIX, FLD_NULL,
FLD_REM, FLD_NO, FLD_DEFAULT, FLD_EXTRA,
FLD_CHARSET}; //unsigned int length[] = {0, 4, 16, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0}; unsignedint length[] = {0, 4, 0, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0};
PCSZ fmt; char *fld, *colname, *chset, v, buf[BUF_SIZE+1], uns[NUM_SIZE+1], zero[NUM_SIZE+1]; int i, n, nf = 0, ncol = sizeof(buftyp) / sizeof(int); int len, type, prec, rc; bool b;
PQRYRES qrp;
PCOLRES crp;
MYSQLC myc;
if (!port)
port = mysqld_port;
if (!info) { /********************************************************************/ /* Open the connection with the MySQL server. */ /********************************************************************/ if (myc.Open(g, host, db, user, pwd, port)) return NULL;
/********************************************************************/ /* Do an evaluation of the result size. */ /********************************************************************/
STRING cmd(g, 64, "SHOW FULL COLUMNS FROM ");
b = cmd.Append('`');
b |= cmd.Append((PSZ)table);
b |= cmd.Append('`');
b |= cmd.Append(" FROM ");
b |= cmd.Append((PSZ)(db ? db : PlgGetUser(g)->DBName));
if (colpat) {
b |= cmd.Append(" LIKE ");
b |= cmd.Append((PSZ)colpat);
} // endif colpat
if (b) {
strcpy(g->Message, "Out of memory"); return NULL;
} // endif b
if (trace(1))
htrc("MyColumns: cmd='%s'\n", cmd.GetStr());
if ((n = myc.GetResultSize(g, cmd.GetStr())) < 0) {
myc.Close(); return NULL;
} // endif n
/********************************************************************/ /* Get the size of the name and default columns. */ /********************************************************************/
length[0] = myc.GetFieldLength(0); // length[10] = myc.GetFieldLength(5);
} else {
n = 0;
length[0] = 128;
} // endif info
/**********************************************************************/ /* Allocate the structures used to refer to the result set. */ /**********************************************************************/ if (!(qrp = PlgAllocResult(g, ncol, n, IDS_COLUMNS + 3,
buftyp, fldtyp, length, false, true))) return NULL;
/**********************************************************************/ /* Now get the results into blocks. */ /**********************************************************************/ for (i = 0; i < n; /*i++*/) { if ((rc = myc.Fetch(g, -1)) == RC_FX) {
myc.Close(); return NULL;
} elseif (rc == RC_EF) break;
// Get column name
colname = myc.GetCharField(0);
crp = qrp->Colresp; // Column_Name
crp->Kdata->SetValue(colname, i);
// Get type, type name, precision, unsigned and zerofill
chset = myc.GetCharField(2);
fld = myc.GetCharField(1);
prec = 0;
len = 0; // v = (chset && !strcmp(chset, "binary")) ? 'B' : 0;
v = 0;
*uns = 0;
*zero = 0;
b = false;
if (!strnicmp(fld, "enum", 4)) { char *p2, *p1 = fld + 6; // to skip enum('
while (true) {
p2 = strchr(p1, '\'');
len = MY_MAX(len, (int)(p2 - p1)); if (*++p2 != ',') break;
p1 = p2 + 2;
} // endwhile
for (i = 0; i < n; i++) if (vbp->GetIntValue(i))
vbp->SetValue(k, i);
} // endif k #endif// 0
/**********************************************************************/ /* Close MySQL connection. */ /**********************************************************************/
myc.Close();
/**********************************************************************/ /* Return the result pointer for use by GetData routines. */ /**********************************************************************/ return qrp;
} // end of MyColumns
/************************************************************************/ /* SrcColumns: constructs the result blocks containing all columns */ /* resulting from an SQL source definition query execution. */ /************************************************************************/
PQRYRES SrcColumns(PGLOBAL g, constchar *host, constchar *db, constchar *user, constchar *pwd, constchar *srcdef, int port)
{ char *query; int w;
MYSQLC myc;
PQRYRES qrp = NULL; constchar *p;
if ((p= strstr(srcdef, "%s")))
{ /* Replace %s with 1=1 */
snprintf(query, query_sz, "%.*s1=1%s",
(int) (p - srcdef), srcdef, p + 2); // dummy where clause
} else
safe_strcpy(query, query_sz, srcdef);
if (!strnicmp(srcdef, "select ", 7))
safe_strcat(query, query_sz, " LIMIT 0");
} else
query = (char *)srcdef;
// Open a MySQL connection for this table if (myc.Open(g, host, db, user, pwd, port)) return NULL;
// Send the source command to MySQL if (myc.ExecSQL(g, query, &w) == RC_OK)
qrp = myc.GetResult(g, true);
myc.Close(); return qrp;
} // end of SrcColumns
/* -------------------------- Class MYSQLC --------------------------- */
/***********************************************************************/ /* Implementation of the MYSQLC class. */ /***********************************************************************/
MYSQLC::MYSQLC(void)
{
m_DB = NULL; #ifdefined (MYSQL_PREPARED_STATEMENTS)
m_Stmt = NULL; #endif// MYSQL_PREPARED_STATEMENTS
m_Res = NULL;
m_Rows = -1;
m_Row = NULL;
m_Fields = -1;
N = 0;
m_Use = false;
} // end of MYSQLC constructor
/***********************************************************************/ /* Get the number of lines of the result set. */ /* Currently we send the Select command and return m_Rows */ /* Perhaps should we use Select count(*) ... (?????) */ /* No because here we execute only one query instead of two */ /* (the select count(*) plus the normal query) */ /***********************************************************************/ int MYSQLC::GetResultSize(PGLOBAL g, PSZ sql)
{ if (m_Rows < 0) if (ExecSQL(g, sql) != RC_OK) return -1;
return m_Rows;
} // end of GetResultSize
/***********************************************************************/ /* Open a MySQL (remote) connection. */ /***********************************************************************/ int MYSQLC::Open(PGLOBAL g, constchar *host, constchar *db, constchar *user, constchar *pwd, int pt, constchar *csname)
{ constchar *pipe = NULL; //uint cto = 10, nrt = 20;
my_bool my_true= 1;
my_bool my_false= 0;
m_DB = mysql_init(NULL);
if (!m_DB) {
strcpy(g->Message, "mysql_init failed: no memory"); return RC_FX;
} // endif m_DB
if (trace(1))
htrc("MYSQLC Open: m_DB=%.4X size=%d\n", m_DB, (int)sizeof(*m_DB));
// Removed to do like FEDERATED does //mysql_options(m_DB, MYSQL_READ_DEFAULT_GROUP, "client-mariadb"); //mysql_options(m_DB, MYSQL_OPT_USE_REMOTE_CONNECTION, NULL); //mysql_options(m_DB, MYSQL_OPT_CONNECT_TIMEOUT, &cto); //mysql_options(m_DB, MYSQL_OPT_READ_TIMEOUT, &nrt); //mysql_options(m_DB, MYSQL_OPT_WRITE_TIMEOUT, ...);
/***********************************************************************/ /* BUG# 17044 Federated Storage Engine is not UTF8 clean */ /* Add set names to whatever charset the table is at open of table */ /* this sets the csname like 'set names utf8'. */ /***********************************************************************/ if (csname)
mysql_options(m_DB, MYSQL_SET_CHARSET_NAME, csname);
// Don't know what this one do but FEDERATED does it
mysql_options(m_DB, MYSQL_OPT_USE_THREAD_SPECIFIC_MEMORY, &my_true);
mysql_options(m_DB, MYSQL_OPT_SSL_VERIFY_SERVER_CERT, &my_false);
/***********************************************************************/ /* Returns true if the connection is still alive. */ /***********************************************************************/ bool MYSQLC::Connected(void)
{ //int rc;
if (!m_DB) returnFALSE; //else if ((rc = mysql_ping(m_DB)) == CR_SERVER_GONE_ERROR) // return FALSE; else returnTRUE;
} // end of Connected
#if0// Not used /***********************************************************************/ /* Returns the thread ID of the current MySQL connection. */ /***********************************************************************/
ulong MYSQLC::GetThreadID(void)
{ return (m_DB) ? mysql_thread_id(m_DB) : 0;
} // end of GetThreadID
/***********************************************************************/ /* Returns a string that represents the server version number. */ /***********************************************************************/ constchar *MYSQLC::ServerInfo(void)
{ return (m_DB) ? mysql_get_server_info(m_DB) : NULL;
} // end of ServerInfo
/***********************************************************************/ /* Returns the version number of the server as a number that */ /* represents the MySQL server version in this format: */ /* major_version*10000 + minor_version *100 + sub_version */ /***********************************************************************/
ulong MYSQLC::ServerVersion(void)
{ return (m_DB) ? mysql_get_server_version(m_DB) : 0;
} // end of ServerVersion #endif// 0
/**************************************************************************/ /* KillQuery: Send MySQL a Kill Query command. */ /**************************************************************************/ int MYSQLC::KillQuery(ulong id)
{ char kill[20];
#ifdefined (MYSQL_PREPARED_STATEMENTS) /***********************************************************************/ /* Prepare the SQL statement used to insert into a MySQL table. */ /***********************************************************************/ int MYSQLC::PrepareSQL(PGLOBAL g, constchar *stmt)
{ if (!m_DB) {
strcpy(g->Message, "MySQL not connected"); return -4;
} elseif (m_Stmt) return -1; // should not append
#ifdefined(ALPHA) if (!(m_Stmt = mysql_prepare(m_DB, stmt, strlen(stmt)))) {
// Return the parameter count from the statement return mysql_param_count(m_Stmt); #else// !ALPHA if (!(m_Stmt = mysql_stmt_init(m_DB))) {
strcpy(g->Message, "mysql_stmt_init(), out of memory"); return -2;
} // endif m_Stmt
// Check the total number of affected rows if (mysql_stmt_affected_rows(m_Stmt) != 1) {
snprintf(g->Message, sizeof(g->Message), "Invalid affected rows by MySQL"); return RC_FX;
} // endif affected_rows
return RC_OK;
} // end of ExecStmt #endif// MYSQL_PREPARED_STATEMENTS
/***********************************************************************/ /* Exec the Select SQL command and get back the result size in rows. */ /***********************************************************************/ int MYSQLC::ExecSQL(PGLOBAL g, constchar *query, int *w)
{ int rc = RC_OK;
if (!m_DB) {
strcpy(g->Message, "MySQL not connected"); return RC_FX;
} // endif m_DB
if (!(m_Res = mysql_store_result(m_DB))) return -3;
// Get the resulting count value
m_Rows = (int)mysql_num_rows(m_Res); // Should be 1
if (m_Rows && (m_Row = mysql_fetch_row(m_Res))) return atoi(*m_Row);
return -4;
} // end of GetTableSize
/***********************************************************************/ /* Move to a specific row and column */ /***********************************************************************/ void MYSQLC::DataSeek(my_ulonglong row)
{
MYSQL_ROWS *tmp = 0; //DBUG_PRINT("info",("mysql_data_seek(%ld)",(long) row));
if (m_Res->data) for (tmp = m_Res->data->data; row-- && tmp; tmp = tmp->next) ;
m_Res->current_row = 0;
m_Res->data_cursor = tmp;
} // end of DataSeek
/***********************************************************************/ /* Fetch one result line from the query result set. */ /***********************************************************************/ int MYSQLC::Fetch(PGLOBAL g, int pos)
{ if (!m_DB) {
strcpy(g->Message, "MySQL not connected"); return RC_FX;
} // endif m_DB
if (!m_Res) { // Result set was not initialized
strcpy(g->Message, MSG(FETCH_NO_RES)); return RC_FX;
} else
N++;
if (pos >= 0) // mysql_data_seek(m_Res, (my_ulonglong)pos);
DataSeek((my_ulonglong)pos);
m_Row = mysql_fetch_row(m_Res); return (m_Row) ? RC_OK : RC_EF;
} // end of Fetch
/***********************************************************************/ /* Get one field of the current row. */ /***********************************************************************/ char *MYSQLC::GetCharField(int i)
{ if (m_Res && m_Row) { #ifdefined(_DEBUG) // MYSQL_FIELD *fld = mysql_fetch_field_direct(m_Res, i); #endif// _DEBUG
MYSQL_ROW row = m_Row + i;
/***********************************************************************/ /* Get the max length of the field. */ /***********************************************************************/ int MYSQLC::GetFieldLength(int i)
{ if (m_Res) { // MYSQL_FIELD *fld = mysql_fetch_field_direct(m_Res, i); // return fld->max_length; return (m_Res)->fields[i].max_length;
} else return0;
} // end of GetFieldLength
/***********************************************************************/ /* Return next field of the query results. */ /***********************************************************************/
MYSQL_FIELD *MYSQLC::GetNextField(void)
{ return (m_Res->current_field >= m_Res->field_count) ? NULL
: &m_Res->fields[m_Res->current_field++];
} // end of GetNextField
/***********************************************************************/ /* Make a CONNECT result structure from the MySQL result. */ /***********************************************************************/
PQRYRES MYSQLC::GetResult(PGLOBAL g, bool pdb)
{
PCSZ fmt; char *name, v= 0; int n; bool uns;
PCOLRES *pcrp, crp;
PQRYRES qrp;
MYSQL_FIELD *fld;
MYSQL_ROW row;
if ((crp->Type = MYSQLtoPLG(fld->type, &v)) == TYPE_ERROR) {
snprintf(g->Message, sizeof(g->Message), "Type %d not supported for column %s",
fld->type, crp->Name); return NULL;
} elseif (crp->Type == TYPE_DATE && !pdb) // For direct MySQL connection, display the MySQL date string
crp->Type = TYPE_STRING; else
crp->Var = v;
/*********************************************************************/ /* Now fill the allocated result structure. */ /*********************************************************************/ for (n = 0; n < m_Rows; n++) { if (!(m_Row = mysql_fetch_row(m_Res))) {
snprintf(g->Message, sizeof(g->Message), "Missing row %d from result", n + 1); return NULL;
} // endif m_Row
for (crp = qrp->Colresp; crp; crp = crp->Next) { if ((row = m_Row + (crp->Ncol - 1))) { if (*row)
crp->Kdata->SetValue((PSZ)*row, n); else { if (!*row && crp->Nulls)
crp->Nulls[n] = '*'; // Null value
crp->Kdata->Reset(n);
} // endelse *row
}
} // endfor crp
} // endfor n
qrp->Nblin = n; return qrp;
} // end of GetResult
/***********************************************************************/ /* Free the current result. */ /***********************************************************************/ void MYSQLC::FreeResult(void)
{ if (m_Res) {
mysql_free_result(m_Res);
m_Res = NULL;
} // endif m_Res
// Reset the connection
m_Row = NULL;
m_Rows = -1;
m_Fields = -1;
N = 0;
} // end of FreeResult
/***********************************************************************/ /* Place the cursor at the beginning of the result set. */ /***********************************************************************/ int MYSQLC::Rewind(PGLOBAL g, PSZ sql)
{ int rc = RC_OK;
if (m_Res)
DataSeek(0); elseif (sql)
rc = ExecSQL(g, sql);
return rc;
} // end of Rewind
/***********************************************************************/ /* Exec the Select SQL command and return ncol or afrws (TDBMYEXC). */ /***********************************************************************/ int MYSQLC::ExecSQLcmd(PGLOBAL g, constchar *query, int *w)
{ int rc = RC_OK;
if (!m_DB) {
strcpy(g->Message, "MySQL not connected"); return RC_FX;
} else
*w = 0;
//*w = mysql_warning_count(m_DB);
*w = m_DB->warning_count; return rc;
} // end of ExecSQLcmd
/***********************************************************************/ /* Close the connection. */ /***********************************************************************/ void MYSQLC::Close(void)
{
FreeResult();
if (trace(1))
htrc("MYSQLC Close: m_DB=%.4X\n", m_DB);
mysql_close(m_DB);
m_DB = NULL;
} // end of Close
#if0// not used yet /***********************************************************************/ /* Discard additional results from a stored procedure. */ /***********************************************************************/ void MYSQLC::DiscardResults(void)
{
MYSQL_RES *res;
while (!mysql_next_result(m_DB)) {
res = mysql_store_result(m_DB);
mysql_free_result(res);
} // endwhile next result
} // end of DiscardResults #endif// 0
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.26 Sekunden
(vorverarbeitet am 2026-10-08)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.