⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mysql.cpp

📁 Shorthand是一个强大的脚本语言
💻 CPP
📖 第 1 页 / 共 2 页
字号:
#ifdef WIN32
#include <windows.h>
#endif

#define array sql_array
//extern "C" {
#include <my_global.h>
#include <my_sys.h>
#include <mysql.h>
#ifdef WIN32
#undef _L
#undef _S
#endif
//}

#undef  array 
#undef  bool

#include "nodes.h"
#include "shsql.h"

MYSQL g_mysql;
bool g_mysql_initialized = false;



/**
 * Database Driver.
 * 
 * This class defines "service provider interface" (SPI) and is intended
 * only for developers of database drivers and ShortHand core.
 *
 * Database Access Objects (ShhDbSession, ShhSQL, ShhDML, etc) are
 * consumers of actual implementations. 
 */
class MySQLDriver : public ShhDbDriver
{
public:

    MySQLDriver() 
    {
    }

    void throwSQL(const char* format, ...)
    {
        va_list args; va_start(args, format);
        throw new ShhObjectException(format, args);
    }

    /**
     * Returns true if driver implementation recognizes
     * specified driver name as supported by itself.
     */
    bool spi_RecognizeDriverName(const char* driverName)
    {
        string name(driverName);
        return name.ieq("mysql");
    }

    /**
     * Returns 3-character driver prefix used in error
     * messages and warnings ('MYQ','PRG','ORA','IFX', ...)
     */
    const char* spi_GetDriverPrefix()
    {
        return "MSQ";
    }
    
    /**
     * Puts long driver description. For example "Oracle (OCI8)"
     *
     * The size of supplied buffer is 255 characters, 
     * not counting terminating zero.
     */
    int spi_GetDriverDescription(string& driverDescription)
    {
        driverDescription = "MySQL Native Driver";
        return driverDescription.length();
    }
    
    /**
     * Tries to open connection using connection string as
     * parameter. Interpretation of connection string completely
     * depends on implementation. ShortHand framework does not
     * perform validation or translation of connection string.
     * 
     * Upon success, driver returns an instance of object 
     * implementing <a href="ShhDbHandle.html">ShhDbHandle</a> 
     * interface.
     * If connection fails, this method throws exception derived
     * from ShhObjectException
     * 
     * @param connString driver-specific connection string
     * @return connection handle if connection has been established.
     * @throws ShhObjectException if connection fails. 
     */
    virtual ShhDbHandle spi_Connect(const char* connString)
    {
        
        //  connection string has the following format:
        //  "driver={mysql}; database=yourdatabase;server=server;uid=username;pwd=password;option=16386;"
        //  and is stored in the "STRING" property

        if (!g_mysql_initialized)
        {
            mysql_init(&g_mysql);
            g_mysql_initialized = true;
        }

        string host, user, passwd, db, port, flags;

        char* tok_start = (char*)(connString);
        char* tok_end = NULL;
        while((tok_end = strchr(tok_start, ';')) != NULL)
        {
            *tok_end = '\0';
            char* name = tok_start;
            while(*name && isspace(*name)) name++;
       
            char* eq = strchr(tok_start, '=');
            if (eq != NULL)
            {
                *eq = '\0';
                char* value = eq + 1;
                while(*value && isspace(*value)) value++;
            
                if (stricmp(name, "server") == 0)
                    host = value;
                else if (stricmp(name, "database") == 0)
                    db = value;
                else if (stricmp(name, "uid") == 0)
                    user = value;
                else if (stricmp(name, "pwd") == 0)
                    passwd = value;
                else if (stricmp(name, "port") == 0)
                    port = value;
                else if (stricmp(name, "option") == 0)
                    flags = value;
            }
            tok_start = tok_end+1;
        }


        if (host.is_empty()) host = ".";

        MYSQL* session = mysql_real_connect(&g_mysql, 
            host.nv(), user.nv(), passwd.nv(), db.nv(), atoi(port), NULL, 0
        );

        if (session == NULL) 
            throw new ShhObjectException("MySQL connection to '%s' failed: %s", host.cstr(), mysql_error(&g_mysql));

        if (mysql_select_db(session, db) != 0)
        {
            char* e = mysql_error(session);
            mysql_close(session);
            throw new ShhObjectException("MySQL connection to '%s' (database '%s') failed: %s", host.cstr(), db.cstr(), e);
        }
        TRACE((5, "connected to MySQL\n"));
        return (ShhDbHandle) session;
    }

    virtual int spi_GetLastError(ShhDbHandle conn, string& message)
    {
        int code = mysql_errno((MYSQL*) conn);
        message = mysql_error((MYSQL*) conn);
        return code;
    }

    /**
     * Closes database connection and releases connection handle
     * (and frees the structure if connection handle is a pointer
     * to the session structor).
     * Connection handle value cannot be used after this operation.
     *
     * @param conn valid database connection handle.
     */
    virtual void spi_Disconnect(ShhDbHandle conn)
    {
        mysql_close((MYSQL*) conn);
    }

    virtual ShhCursorHandle spi_PrepareSQL(ShhDbHandle conn, const char* sql)
    {
        return NULL; // "prepare" is not supported for MySQL
    }

    virtual void spi_CloseCursor(ShhCursorHandle cursor)
    {
        // TODO        
    }
    
    virtual void spi_CloseResult(ShhResultHandle resultSet)
    {
        if (resultSet != 0)
        {
            mysql_free_result((MYSQL_RES*) resultSet);
        }
    }

    virtual int spi_ExecuteImmediate(ShhDbHandle dbHandle, const char* sql)
    {
        if (mysql_real_query((MYSQL*)dbHandle, sql, strlen(sql)) != 0)
        {
            int code = mysql_errno((MYSQL*)dbHandle);
            const char* msg = mysql_error((MYSQL*)dbHandle);
	    throwSQL("SQL Query failed: MySQL error %d: %s", code, msg);
        }
        return 0;
    }

    /**
     * Executes (prepared) cursor.
     */
    virtual ShhResultHandle spi_ExecuteCursor(ShhDbHandle dbHandle, ShhCursorHandle cursor, const char* sql)
    {
        MYSQL* session = (MYSQL*) dbHandle;
        if (mysql_real_query(session, sql, strlen(sql)) != 0)
        {
            int code = mysql_errno(session);
            const char* msg = mysql_error(session);
	    throwSQL("SQL Query failed: MySQL error %d: %s", code, msg);
        }

        MYSQL_RES* result = mysql_store_result(session);
        if (result == NULL)
        {
            return 0;
        } 
        else
        {
            return (ShhResultHandle) result;
        }
    }
       

    /**
     * Returns number of fields in the result set.
     */
    virtual int spi_GetFieldCount(ShhResultHandle resultHandle)
    {
        if (resultHandle == 0) return 0;
        else return mysql_num_fields((MYSQL_RES*) resultHandle);
    }

    /**
     * Returns number of rows in the result set.
     */
    virtual int spi_GetRowCount(ShhResultHandle resultHandle)
    {
        if (resultHandle == 0) return 0;
        else return (int) mysql_num_rows((MYSQL_RES*) resultHandle);
    }

    virtual int spi_GetFieldName(ShhResultHandle resultHandle, int fieldNumber, string& fieldName)
    {
        if (resultHandle == 0) { fieldName = ""; return 0; }
        MYSQL_FIELD* field = mysql_fetch_field_direct((MYSQL_RES*) resultHandle, fieldNumber);
        fieldName = field->name;
        return fieldName.length();
    }

    virtual ShhRowHandle spi_Fetch(ShhResultHandle resultSet)
    {
        MYSQL_ROW row = mysql_fetch_row((MYSQL_RES*) resultSet);
        return (ShhRowHandle) row;
    }

    virtual int spi_GetStringValue(ShhResultHandle resultHandle, ShhRowHandle rowHandle, int fieldNumber, string& value)
    {
        MYSQL_ROW row = (MYSQL_ROW) rowHandle;
        unsigned long* lengths = mysql_fetch_lengths((MYSQL_RES*) resultHandle);
        unsigned int length = lengths[fieldNumber];
        if (length > 0)
        {
            value.set(row[fieldNumber], length);
        }
        else
        {
            value.clear();
        }
        return value.length();
    }

    /**
     * Returns number of rows affected by last executed statement,
     * if applicable. If implementation doesn't support this function, 
     * it throws ShhObjectException.
     */
    virtual int
        spl_GetAffectedRows(ShhCursorHandle connection)
    {
        return (int) mysql_affected_rows((MYSQL*) connection);
    }

    virtual void
        spi_CloseRow(ShhRowHandle rowHandle)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -