Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
tree: 7e824d2287
Fetching contributors…

Cannot retrieve contributors at this time

260 lines (212 sloc) 7.989 kb
//metadoc MySQL copyright Min-hee Hong, 2007
//metadoc MySQL license MIT License
//metadoc MySQL category Databases
/*metadoc MySQL description
<a href="http://www.mysql.com/">MySQL</a> is a fast, multi-threaded,
multi-user SQL database server. IoMySQL is a MySQL binding for Io,
by <a href="http://dahlia.pe.kr/">Min-hee Hong</a>.
<pre><code>
my := MySQL establish(&quot;localhost&quot;, &quot;user&quot;, &quot;password&quot;, &quot;database&quot;)
# Get rows by Map
my queryThenMap(&quot;SELECT * FROM rel&quot;) foreach(at(&quot;col&quot;) println)
# Get rows by List
my query(&quot;SELECT * FROM rel&quot;) foreach(at(0) println)
my close
</code></pre>
*/
#include "IoMySQL.h"
#include "IoMessage.h"
#include "IoState.h"
#include "IoNumber.h"
#include "IoSeq.h"
#include "IoList.h"
#include "IoMap.h"
#define DATA(self) ((IoMySQLData*) IoObject_dataPointer(self))
static const char *protoId = "MySQL";
IoTag* IoMySQL_newTag(void* state) {
IoTag* tag = IoTag_newWithName_(protoId);
IoTag_state_(tag, state);
IoTag_freeFunc_(tag, (IoTagFreeFunc*) IoMySQL_free);
IoTag_cloneFunc_(tag, (IoTagCloneFunc*) IoMySQL_rawClone);
return tag;
}
IoObject* IoMySQL_proto(void* state) {
IoObject* self = IoObject_new(state);
IoObject_tag_(self, IoMySQL_newTag(state));
IoObject_setDataPointer_(self, calloc(1, sizeof(IoMySQLData)));
IoState_registerProtoWithFunc_(state, self, IoMySQL_proto);
{
IoMethodTable methodTable[] = {
{"establish", IoMySQL_establish},
{"connect", IoMySQL_connect},
{"connected", IoMySQL_connected},
{"close", IoMySQL_close},
{"query", IoMySQL_query},
{"lastInsertRowId", IoMySQL_lastInsertRowId},
{NULL, NULL}
};
IoObject_addMethodTable_(self, methodTable);
}
return self;
}
IoObject* IoMySQL_rawClone(IoObject* proto) {
IoObject* self = IoObject_rawClonePrimitive(proto);
IoObject_setDataPointer_(self, calloc(1, sizeof(IoMySQLData)));
return self;
}
IoObject* IoMySQL_new(void* state)
{
IoObject* proto = IoState_protoWithId_(state, protoId);
return IOCLONE(proto);
}
void IoMySQL_free(IoObject* self)
{
if(DATA(self)->connected)
mysql_close(&DATA(self)->connection);
free(IoObject_dataPointer(self));
}
/* ----------------------------------------------------------- */
IoObject* IoMySQL_establish(IoObject* self, IoObject* locals, IoMessage* m) {
/*doc MySQL establish
Establish a connection to a MySQL database.
*/
IoObject* result = IoMySQL_new(IOSTATE);
IoMySQL_connect(result, locals, m);
return result;
}
IoObject* IoMySQL_connect(IoObject* self, IoObject* locals, IoMessage* m) {
IoObject *host = NULL, *user = NULL, *password = NULL, *database = NULL, *port = NULL, *socket = NULL, *ssl = NULL;
/*doc MySQL connect(host, user, password, database, port, unixSocket, useSSL)
Connect to a MySQL database.
*/
switch(IoMessage_argCount(m)) {
case 7: ssl = IoMessage_locals_quickValueArgAt_(m, locals, 6);
case 6: socket = IoMessage_locals_quickValueArgAt_(m, locals, 5);
case 5: port = IoMessage_locals_quickValueArgAt_(m, locals, 4);
case 4: database = IoMessage_locals_quickValueArgAt_(m, locals, 3);
case 3: password = IoMessage_locals_quickValueArgAt_(m, locals, 2);
case 2: user = IoMessage_locals_quickValueArgAt_(m, locals, 1);
case 1: host = IoMessage_locals_quickValueArgAt_(m, locals, 0);
}
if(DATA(self)->connected)
{
mysql_close(&DATA(self)->connection);
DATA(self)->connected = 0;
}
if(mysql_real_connect(
&DATA(self)->connection,
host && ISSEQ(host) ? IoSeq_asCString(host) : NULL,
user && ISSEQ(user) ? IoSeq_asCString(user) : NULL,
password && ISSEQ(password) ? IoSeq_asCString(password) : NULL,
database && ISSEQ(database) ? IoSeq_asCString(database) : NULL,
port && ISNUMBER(port) ? (unsigned) IoNumber_asInt(port) : 0,
socket && ISSEQ(socket) ? IoSeq_asCString(socket) : NULL,
ssl && ISFALSE(ssl) ? 0 : CLIENT_SSL
)) {
DATA(self)->connected = 1;
IoObject_setSlot_to_(self, IOSYMBOL("host"), host ? host : IONIL(self));
IoObject_setSlot_to_(self, IOSYMBOL("user"), user ? user : IONIL(self));
IoObject_setSlot_to_(self, IOSYMBOL("password"), password ? password : IONIL(self));
IoObject_setSlot_to_(self, IOSYMBOL("database"), database ? database : IONIL(self));
IoObject_setSlot_to_(self, IOSYMBOL("port"), port ? port : IONIL(self));
IoObject_setSlot_to_(self, IOSYMBOL("socket"), socket ? socket : IONIL(self));
IoObject_setSlot_to_(self, IOSYMBOL("usingSSL"), ssl ? IOBOOL(self, ISTRUE(ssl)) : IOFALSE(self));
}
else
IoState_error_(IOSTATE, m, "connection error(%d): %s", mysql_errno(&DATA(self)->connection), mysql_error(&DATA(self)->connection));
return self;
}
IoObject* IoMySQL_connected(IoObject* self, IoObject* locals, IoMessage* m)
{
/*doc MySQL connected
Returns true if connected to the database, false otherwise.
*/
return IOBOOL(self, DATA(self)->connected);
}
IoObject* IoMySQL_close(IoObject* self, IoObject* locals, IoMessage* m)
{
/*doc MySQL close
Closes a previously opened connection.
*/
if(DATA(self)->connected)
{
mysql_close(&DATA(self)->connection);
DATA(self)->connected = 0;
}
/*
IoObject_removeSlot_(self, IOSYMBOL("host"));
IoObject_removeSlot_(self, IOSYMBOL("user"));
IoObject_removeSlot_(self, IOSYMBOL("password"));
IoObject_removeSlot_(self, IOSYMBOL("database"));
IoObject_removeSlot_(self, IOSYMBOL("port"));
IoObject_removeSlot_(self, IOSYMBOL("socket"));
IoObject_removeSlot_(self, IOSYMBOL("usingSSL"));
*/
return self;
}
IoObject* IoMySQL_query(IoObject* self, IoObject* locals, IoMessage* m)
{
/*doc MySQL query(aQueryString)
Perform a SQL query and return a list of results.
<pre>
db query("SELECT * FROM accounts") foreach(println)
</pre>
*/
IoObject * queryString = 0x0;
bool useMap;
MYSQL* conn = &DATA(self)->connection;
MYSQL_RES* result;
MYSQL_ROW row;
MYSQL_FIELD* column;
char** columnNames;
unsigned c, colLength;
unsigned long* colLengths;
IoObject *list, *rowObject; //, *tmpObject;
if(IoMessage_argCount(m) < 1 || !ISSEQ(queryString = IoMessage_locals_quickValueArgAt_(m, locals, 0)))
IoState_error_(IOSTATE, m, "argument 0 to method 'query' must be a Sequence");
useMap = IoMessage_argCount(m) > 1 && ISTRUE(IoMessage_locals_quickValueArgAt_(m, locals, 1));
if(!DATA(self)->connected) //printf("not connected?\n");
IoState_error_(IOSTATE, m, "not connected yet");
if(mysql_real_query(conn, CSTRING(queryString), IOSEQ_LENGTH(queryString)))
IoState_error_(IOSTATE, m, "query error(%d): %s", mysql_errno(&DATA(self)->connection), mysql_error(&DATA(self)->connection));
if((result = mysql_store_result(conn)) && (colLength = mysql_num_fields(result))) {
list = IoList_new(IOSTATE);
if(useMap) {
columnNames = (char**) malloc(colLength * sizeof(char*));
for(c = 0; c < colLength && (column = mysql_fetch_field(result)); ++c)
columnNames[c] = column->name;
while((row = mysql_fetch_row(result)))
{
colLengths = mysql_fetch_lengths(result);
rowObject = IoMap_new(IOSTATE);
for(c = 0; c < colLength; ++c)
IoMap_rawAtPut(rowObject, IOSYMBOL(columnNames[c]), IOSEQ((unsigned char *)row[c], (size_t)colLengths[c]));
IoList_rawAppend_(list, rowObject);
}
free(columnNames);
}
else
{
while((row = mysql_fetch_row(result))) {
colLengths = mysql_fetch_lengths(result);
rowObject = IoList_new(IOSTATE);
for(c = 0; c < colLength; ++c)
IoList_rawAppend_(rowObject, IOSEQ((unsigned char *)row[c], (size_t)colLengths[c]));
IoList_rawAppend_(list, rowObject);
}
}
mysql_free_result(result);
return list;
}
else
return IONUMBER(mysql_affected_rows(conn));
}
IoObject* IoMySQL_lastInsertRowId(IoObject* self, IoObject* locals, IoMessage* m) {
/*doc MySQL lastInsertRowId
Returns the value generated for an AUTO_INCREMENT column by the previous INSERT or UPDATE statement.
*/
if(DATA(self)->connected)
return IONUMBER(mysql_insert_id(&DATA(self)->connection));
else
return IOSTATE->ioNil;
}
Jump to Line
Something went wrong with that request. Please try again.