|
From: <dav...@us...> - 2007-04-10 01:58:11
|
Revision: 1651
http://svn.sourceforge.net/frontierkernel/?rev=1651&view=rev
Author: davidgewirtz
Date: 2007-04-09 18:58:10 -0700 (Mon, 09 Apr 2007)
Log Message:
-----------
Added basic query verbs: compileQuery, clearQuery, fetchRow. Can successfully perform a query into a MySQL database.
Modified Paths:
--------------
Frontier/branches/mysql/Common/headers/langmysql.h
Frontier/branches/mysql/Common/resources/Mac/kernelverbs.r
Frontier/branches/mysql/Common/resources/Win32/kernelverbs.rc
Frontier/branches/mysql/Common/source/langmysql.c
Modified: Frontier/branches/mysql/Common/headers/langmysql.h
===================================================================
--- Frontier/branches/mysql/Common/headers/langmysql.h 2007-04-09 03:48:44 UTC (rev 1650)
+++ Frontier/branches/mysql/Common/headers/langmysql.h 2007-04-10 01:58:10 UTC (rev 1651)
@@ -27,14 +27,20 @@
/* prototypes */
-extern boolean mysqlinitverb (hdltreenode, tyvaluerecord *, bigstring); /* 2007-04-08 gewirtz */
+extern boolean mysqlinitverb (hdltreenode, tyvaluerecord *, bigstring); /* 2007-04-08 gewirtz */
-extern boolean mysqlconnectverb (hdltreenode, tyvaluerecord *, bigstring); /* 2007-04-08 gewirtz */
+extern boolean mysqlconnectverb (hdltreenode, tyvaluerecord *, bigstring); /* 2007-04-08 gewirtz */
-extern boolean mysqlcloseverb (hdltreenode, tyvaluerecord *, bigstring); /* 2007-04-08 gewirtz */
+extern boolean mysqlcompilequeryverb (hdltreenode, tyvaluerecord *, bigstring); /* 2007-04-09 gewirtz */
+extern boolean mysqlclearqueryverb (hdltreenode, tyvaluerecord *, bigstring); /* 2007-04-09 gewirtz */
+extern boolean mysqlfetchrowverb (hdltreenode, tyvaluerecord *, bigstring); /* 2007-04-09 gewirtz */
+extern boolean mysqlcloseverb (hdltreenode, tyvaluerecord *, bigstring); /* 2007-04-08 gewirtz */
+
+
+
extern boolean mysqlinitverbs (void); /* 2007-04-08 gewirtz */
/* boolean hmacmd5 (unsigned char *, int, unsigned char *, int, unsigned char *);*/ /* 2006-03-05 creedon */
Modified: Frontier/branches/mysql/Common/resources/Mac/kernelverbs.r
===================================================================
--- Frontier/branches/mysql/Common/resources/Mac/kernelverbs.r 2007-04-09 03:48:44 UTC (rev 1650)
+++ Frontier/branches/mysql/Common/resources/Mac/kernelverbs.r 2007-04-10 01:58:10 UTC (rev 1651)
@@ -1172,6 +1172,9 @@
"init",
"connect",
+ "compileQuery",
+ "clearQuery",
+ "fetchRow",
"close"
}
}
Modified: Frontier/branches/mysql/Common/resources/Win32/kernelverbs.rc
===================================================================
--- Frontier/branches/mysql/Common/resources/Win32/kernelverbs.rc 2007-04-09 03:48:44 UTC (rev 1650)
+++ Frontier/branches/mysql/Common/resources/Win32/kernelverbs.rc 2007-04-10 01:58:10 UTC (rev 1651)
@@ -1106,8 +1106,11 @@
1, // Number of "blocks" in this resource
"mysql\0", // Function Processor name
false, // Window required
- 3, // Count of verbs
+ 6, // Count of verbs
"init\0",
"connect\0",
+ "compileQuery\0",
+ "clearQuery\0",
+ "fetchRow\0",
"close\0"
END
Modified: Frontier/branches/mysql/Common/source/langmysql.c
===================================================================
--- Frontier/branches/mysql/Common/source/langmysql.c 2007-04-09 03:48:44 UTC (rev 1650)
+++ Frontier/branches/mysql/Common/source/langmysql.c 2007-04-10 01:58:10 UTC (rev 1651)
@@ -75,6 +75,9 @@
initfunc,
connectfunc,
+ compilequeryfunc,
+ clearqueryfunc,
+ fetchrowfunc,
closefunc,
ctmysqlverbs
} tymysqlverbtoken;
@@ -99,6 +102,21 @@
return (mysqlconnectverb (hp1, v, bserror));
} /* connectfunc */
+ case compilequeryfunc: { /* 2007-04-09 gewirtz: prepare a MySQL query */
+
+ return (mysqlcompilequeryverb (hp1, v, bserror));
+ } /* compilequeryfunc */
+
+ case clearqueryfunc: { /* 2007-04-09 gewirtz: clear a MySQL query from memory */
+
+ return (mysqlclearqueryverb (hp1, v, bserror));
+ } /* clearqueryfunc */
+
+ case fetchrowfunc: { /* 2007-04-09 gewirtz: get a full row from a query */
+
+ return (mysqlfetchrowverb (hp1, v, bserror));
+ } /* fetchrowfunc */
+
case closefunc: { /* 2007-04-08 gewirtz: close a MySQL db */
return (mysqlcloseverb (hp1, v, bserror));
@@ -153,10 +171,10 @@
long port; // TCP/IP port for the connection
//
- // mysql.connect (host, user, password, database, port)
+ // mysql.connect (dbid, host, user, password, database, port)
//
// Action: connects to a MySQL server and database, initializing the mySQL connection object
- // Params: the hostname, user id, password, existing database name, and port
+ // Params: dbid (the MySQL object) the hostname, user id, password, existing database name, and port
// Returns: a MySQL object handle or an error
// Usage: call in a try statement
//
@@ -203,30 +221,240 @@
boolean mysqlcloseverb (hdltreenode hparam1, tyvaluerecord *vreturned, bigstring bserror) {
MYSQL *dbid; // the MySQL object handle
- int returnCode; /* return code from SQLite call */
+ int returnCode; // return code from close call
+ //
+ // mysql.close(dbid)
+ //
+ // Action: close a MySQL session
+ // Params: dbid, the MySQL object
+ // Returns: nothing
+ // Usage: there doesn't appear to be a way to check for success or failure
+ //
+ // MySQL docs: http://dev.mysql.com/doc/refman/5.1/en/mysql-close.html
+ //
+
+ flnextparamislast = true; /* makes sure Frontier throws an error if more than one param is passed */
+
+ if (!getlongvalue (hparam1, 1, (long *) &dbid)) /* Get the long value, which becomes the db pointer */
+ return (false);
+
+ /* Process the SQLite sequence */
+ mysql_close(dbid);
+ returnCode = 0; // placeholder for debugging. mysql_close doesn't return anything.
+
+ return setlongvalue (returnCode, vreturned);
+
+} /* mysqlcloseverb */
+
+boolean mysqlcompilequeryverb (hdltreenode hparam1, tyvaluerecord *vreturned, bigstring bserror) {
+ Handle query; // the SQL query passed to the MySQL server
+ MYSQL *dbid; // the MySQL object handle
+ MYSQL_RES *queryid; // the returned MySQL query id
+ int returnCode; // return code from MySQL query
+
/*
- sqlite.close(dbid)
+ sqlite.compileQuery(dbid, query)
- Action: close an SQLite database
- Params: a database id
+ Action: compile an SQLite query
+ Params: a database id and a query string
+ Returns: a query id
+ Usage: call in a try statement
+ Notes: do not pass the opened database ID across threads.
+
+ SQLite docs: http://www.sqlite.org/capi3ref.html#sqlite3_prepare.
+
+ Code that is a good example of prepare in use:
+ http://souptonuts.sourceforge.net/code/eatblob.c.html
+ */
+
+ if (!getlongvalue (hparam1, 1, (long *) &dbid)) /* Get the long value, which becomes the db pointer */
+ return (false);
+
+ flnextparamislast = true; /* makes sure Frontier throws an error if more than one param is passed */
+
+ if (!getreadonlytextvalue (hparam1, 2, &query)) /* get the query param */
+ return (false);
+
+ // Null terminate strings
+ pushcharhandle (0x00, query);
+
+ /* Process the initial query sequence */
+ returnCode = mysql_query(dbid, *query);
+ if(returnCode != 0) {
+ langerrormessage ("\x21""Could not initialize MySQL query.");
+ return (false);
+ }
+
+ queryid = mysql_store_result(dbid);
+ if(mysql_errno(dbid) != 0) {
+ langerrormessage ("\x21""Could initialize MySQL query.");
+ return (false);
+ }
+
+ return (setlongvalue ((long) queryid, vreturned)); /* return the db address to the scripter */
+
+
+} /* mysqlcompilequeryverb */
+
+boolean mysqlclearqueryverb (hdltreenode hparam1, tyvaluerecord *vreturned, bigstring bserror) {
+ MYSQL_RES *queryid; // the returned MySQL query id
+ int returnCode;
+
+ /*
+ sqlite.clearQuery(queryid)
+
+ Action: clear an SQLite query
+ Params: a query id
Returns: an SQLite result code
- Usage: check result code for success or failure
Notes: do not pass the opened database ID across threads.
- SQLite docs: http://www.sqlite.org/capi3ref.html#sqlite3_close.
+ SQLite docs: http://www.sqlite.org/capi3ref.html#sqlite3_finalize.
*/
flnextparamislast = true; /* makes sure Frontier throws an error if more than one param is passed */
- if (!getlongvalue (hparam1, 1, (long *) &dbid)) /* Get the long value, which becomes the db pointer */
+ if (!getlongvalue (hparam1, 1, (long *) &queryid)) /* Get the long value, which becomes the queryid pointer */
return (false);
- /* Process the SQLite sequence */
- mysql_close(dbid);
- returnCode = 0; // placeholder for debugging. mysql_close doesn't return anything.
+ /* Process the MySQL sequence */
+ mysql_free_result(queryid);
+ returnCode = 0; // placeholder for debugging. mysql_free_result doesn't return anything.
return setlongvalue (returnCode, vreturned);
-} /* mysqlcloseverb */
+} /* mysqlclearqueryverb */
+boolean mysqlfetchrowverb (hdltreenode hparam1, tyvaluerecord *vreturned, bigstring bserror) {
+ long fieldNumber; /* field number */
+ unsigned int fieldCount; /* number of fields */
+ MYSQL_RES *queryid; /* query id */
+ MYSQL_ROW row;
+ MYSQL_FIELD *field;
+
+ hdllistrecord hlist;
+
+ int returnCode; /* return code from SQLite call */
+ double returnDouble; /* double value returned from SQLite call */
+ Handle returnH;
+ const unsigned char *column_text;
+
+ tyvaluerecord val;
+
+
+ /*
+ http://dev.mysql.com/doc/refman/5.1/en/c-api-datatypes.html
+
+ */
+
+ flnextparamislast = true; /* makes sure Frontier throws an error if more than one param is passed */
+
+ if (!getlongvalue (hparam1, 1, (long *) &queryid)) /* Get the long value, which becomes the queryid pointer */
+ return (false);
+
+ row = mysql_fetch_row(queryid);
+ if (row == NULL) {
+ // return 0, meaning no more rows
+ // **** NOTE THIS COULD ALSO MEAN AN ERROR, MIGHT BE GOOD TO CHECK
+ return (setlongvalue ((long) 0, vreturned));
+ }
+ fieldCount = mysql_num_fields(queryid);
+
+ if (fieldCount == 0) {
+ langerrormessage ("\x2F""MySQL.fetchRow requires a minimum of one field.");
+ return (false);
+ }
+ mysql_field_seek(queryid, 0); // restart gathering field data from the first field
+
+ if (!opnewlist (&hlist, false)) /* fail out if we can't create the list */
+ return (false);
+
+ for (fieldNumber=0; fieldNumber<fieldCount; ++fieldNumber) {
+
+ field = mysql_fetch_field(queryid);
+
+ switch(field->type) {
+
+ /*
+ The MySQL fetch_row function is interesting, in that it looks like
+ each field returned is returned as a string. This is great for Frontier,
+ since Frontier can't handle some of MySQL's bigger number types (like double),
+ but it can handle strings. So everything that's supported is returned as
+ a string to Frontier. The Frontier programmer can then do whatever
+ coercing is necessary.
+
+ The only formats we explicitly don't support are:
+
+ MYSQL_TYPE_BIT
+ MYSQL_TYPE_BLOB
+ MYSQL_TYPE_SET
+ MYSQL_TYPE_ENUM
+ MYSQL_TYPE_GEOMETRY
+ MYSQL_TYPE_NULL
+
+ Formats supported and returned as string:
+
+ MYSQL_TYPE_TINY
+ MYSQL_TYPE_SHORT
+ MYSQL_TYPE_LONG
+ MYSQL_TYPE_INT24
+ MYSQL_TYPE_LONGLONG
+ MYSQL_TYPE_DECIMAL
+ MYSQL_TYPE_NEWDECIMAL
+ MYSQL_TYPE_FLOAT
+ MYSQL_TYPE_DOUBLE
+ MYSQL_TYPE_TIMESTAMP
+ MYSQL_TYPE_DATE
+ MYSQL_TYPE_TIME
+ MYSQL_TYPE_DATETIME
+ MYSQL_TYPE_YEAR
+ MYSQL_TYPE_STRING
+ MYSQL_TYPE_VAR_STRING
+ */
+
+ case MYSQL_TYPE_TINY:
+ case MYSQL_TYPE_SHORT:
+ case MYSQL_TYPE_LONG:
+ case MYSQL_TYPE_INT24:
+ case MYSQL_TYPE_LONGLONG:
+ case MYSQL_TYPE_DECIMAL:
+ case MYSQL_TYPE_NEWDECIMAL:
+ case MYSQL_TYPE_FLOAT:
+ case MYSQL_TYPE_DOUBLE:
+ case MYSQL_TYPE_TIMESTAMP:
+ case MYSQL_TYPE_DATE:
+ case MYSQL_TYPE_TIME:
+ case MYSQL_TYPE_DATETIME:
+ case MYSQL_TYPE_YEAR:
+ case MYSQL_TYPE_STRING:
+ case MYSQL_TYPE_VAR_STRING:
+ {
+ column_text = row[fieldNumber];
+
+ /* Exit the verb, converting column_name back to Frontier handle */
+ if (!newfilledhandle ((ptrvoid) column_text, strlen (column_text), &returnH))
+ return false; /* Allocation failed */
+ if (!setheapvalue (returnH, stringvaluetype, &val)) /* convert handle to value */
+ goto error;
+ if (!langpushlistval (hlist, nil, &val))
+ goto error;
+ break;
+ }
+ default: {
+ /* SQLite spec says sqlite3_column_type only returns the above 5 types. But,
+ just in case it lied, this time we return a 0, so the rest of the fields
+ can be read properly. */
+ if (!langpushlistlong (hlist, (long) 0))
+ goto error;
+ }
+ } /* switch */
+ } /* for */
+
+ return (setheapvalue ((Handle) hlist, listvaluetype, vreturned));
+
+ error: {
+ opdisposelist (hlist);
+ return (false);
+ }
+
+} /* mysqlfetchrow */
\ No newline at end of file
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|