Author: wyoung
Date: Mon Oct 27 21:49:52 2008
New Revision: 2380

URL: http://svn.gna.org/viewcvs/mysqlpp?rev=2380&view=rev
Log:
- Added SQLTypeAdapter ctor for Null<String>, to allow SSQLS with NULL
  BLOB columns.  Patch by Russell Robinson <[EMAIL PROTECTED]>
- Reworked the load_jpeg and cgi_jpeg examples to test this, and put
  both in dtest; also, changed images.data to allow NULL in resetdb
- cgi_jpeg can now take command line overrides to the hard-coded DB
  connection parameters, allowing it to be called via dtest.

Added:
    trunk/examples/images.h
Modified:
    trunk/   (props changed)
    trunk/Wishlist
    trunk/bmark.txt
    trunk/dtest
    trunk/examples/cgi_jpeg.cpp
    trunk/examples/load_jpeg.cpp
    trunk/examples/resetdb.cpp
    trunk/lib/stadapter.cpp
    trunk/lib/stadapter.h

Propchange: trunk/
------------------------------------------------------------------------------
--- svn:ignore (original)
+++ svn:ignore Mon Oct 27 21:49:52 2008
@@ -49,4 +49,5 @@
 transaction
 usequery
 
+last-insert-id.txt
 tags

Modified: trunk/Wishlist
URL: 
http://svn.gna.org/viewcvs/mysqlpp/trunk/Wishlist?rev=2380&r1=2379&r2=2380&view=diff
==============================================================================
--- trunk/Wishlist (original)
+++ trunk/Wishlist Mon Oct 27 21:49:52 2008
@@ -125,10 +125,6 @@
 
       http://lists.mysql.com/plusplus/7999
 
-    o Methods like Query::insert() do not work with Null<>-wrapped
-      SSQLS because they're not accessing SSQLS members through the
-      wrapper's 'data' member.  Add additional overloads to cope.
-
 
 v4.0 or Later
 -------------

Modified: trunk/bmark.txt
URL: 
http://svn.gna.org/viewcvs/mysqlpp/trunk/bmark.txt?rev=2380&r1=2379&r2=2380&view=diff
==============================================================================
--- trunk/bmark.txt (original)
+++ trunk/bmark.txt Mon Oct 27 21:49:52 2008
@@ -181,3 +181,13 @@
 select * from stock where weight = 1.5 and price = 8.7899999999999991
 ================ END ssqls5 OUTPUT ================
 
+---------------- BEGIN load_jpeg OUTPUT ----------------
+Inserted "NULL" into images table, 0 bytes, ID 1
+================ END load_jpeg OUTPUT ================
+
+---------------- BEGIN cgi_jpeg OUTPUT ----------------
+Content-type: text/plain
+
+No image content!
+================ END cgi_jpeg OUTPUT ================
+

Modified: trunk/dtest
URL: 
http://svn.gna.org/viewcvs/mysqlpp/trunk/dtest?rev=2380&r1=2379&r2=2380&view=diff
==============================================================================
--- trunk/dtest (original)
+++ trunk/dtest Mon Oct 27 21:49:52 2008
@@ -26,6 +26,9 @@
 echo " $count tests succeeded"
 echo 'All unit tests passed' >> $TMP
 
+# Assume AUTO_INCREMENT id column in images table will get 1 in
+# load_jpeg call below, since we reset the DB before doing it.
+export QUERY_STRING=id=1
 
 # Now run examples to test high-level behavior.  The repeated use of
 # resetdb is intentional!  It's run after each example that changes
@@ -35,7 +38,8 @@
 for t in \
        resetdb simple[0-9] store_if for_each multiquery tquery1 \
        resetdb tquery[2-9] \
-       resetdb ssqls[0-9]
+       resetdb ssqls[0-9] \
+       load_jpeg cgi_jpeg
 do
        if [ -x $t ]
        then

Modified: trunk/examples/cgi_jpeg.cpp
URL: 
http://svn.gna.org/viewcvs/mysqlpp/trunk/examples/cgi_jpeg.cpp?rev=2380&r1=2379&r2=2380&view=diff
==============================================================================
--- trunk/examples/cgi_jpeg.cpp (original)
+++ trunk/examples/cgi_jpeg.cpp Mon Oct 27 21:49:52 2008
@@ -27,21 +27,26 @@
  USA
 ***********************************************************************/
 
-#include <mysql++.h>
-#include <ssqls.h>
+#include "cmdline.h"
+#include "images.h"
 
-#define IMG_DATABASE   "mysql_cpp_data"
-#define IMG_HOST               "localhost"
-#define IMG_USER               "root"
-#define IMG_PASSWORD   "nunyabinness"
+#define CRLF                   "\r\n"
+#define CRLF2                  "\r\n\r\n"
 
-sql_create_2(images,
-       1, 2,
-       mysqlpp::sql_int_unsigned, id,
-       mysqlpp::sql_blob, data)
+int
+main(int argc, char* argv[])
+{
+       // Get database access parameters from command line if present, else
+       // use hard-coded values for true CGI case.
+    const char* db = "mysql_cpp_data";
+       const char* server = "localhost";
+       const char* user = "root";
+       const char* pass = "nunyabinness";
+       if (!parse_command_line(argc, argv, &db, &server, &user, &pass)) {
+               return 1;
+       }
 
-int main()
-{
+       // Parse CGI query string environment variable to get image ID
        unsigned int img_id = 0;
        char* cgi_query = getenv("QUERY_STRING");
        if (cgi_query) {
@@ -71,33 +76,41 @@
                return 1;
        }
 
+       // Retrieve image from DB by ID
        try {
-               mysqlpp::Connection con(IMG_DATABASE, IMG_HOST, IMG_USER,
-                               IMG_PASSWORD);
+               mysqlpp::Connection con(db, server, user, pass);
                mysqlpp::Query query = con.query();
                query << "SELECT * FROM images WHERE id = " << img_id;
-               mysqlpp::UseQueryResult res = query.use();
-               if (res) {
-                       images img = res.fetch_row();
-                       std::cout << "Content-type: image/jpeg" << std::endl;
-                       std::cout << "Content-length: " << img.data.length() << 
"\n\n";
-                       std::cout << img.data;
+               mysqlpp::StoreQueryResult res = query.store();
+               if (res && res.num_rows()) {
+                       images img = res[0];
+                       if (img.data.is_null) {
+                               std::cout << "Content-type: text/plain" << 
CRLF2;
+                               std::cout << "No image content!" << CRLF;
+                       }
+                       else {
+                               std::cout << "X-Image-Id: " << img_id << CRLF; 
// for debugging
+                               std::cout << "Content-type: image/jpeg" << CRLF;
+                               std::cout << "Content-length: " <<
+                                               img.data.data.length() << CRLF2;
+                               std::cout << img.data;
+                       }
                }
                else {
-                       std::cout << "Content-type: text/plain" << std::endl << 
std::endl;
-                       std::cout << "ERROR: No such image with ID " << img_id 
<< std::endl;
+                       std::cout << "Content-type: text/plain" << CRLF2;
+                       std::cout << "ERROR: No image with ID " << img_id << 
CRLF;
                }
        }
        catch (const mysqlpp::BadQuery& er) {
                // Handle any query errors
-               std::cout << "Content-type: text/plain" << std::endl << 
std::endl;
-               std::cout << "QUERY ERROR: " << er.what() << std::endl;
+               std::cout << "Content-type: text/plain" << CRLF2;
+               std::cout << "QUERY ERROR: " << er.what() << CRLF;
                return 1;
        }
        catch (const mysqlpp::Exception& er) {
                // Catch-all for any other MySQL++ exceptions
-               std::cout << "Content-type: text/plain" << std::endl << 
std::endl;
-               std::cout << "GENERAL ERROR: " << er.what() << std::endl;
+               std::cout << "Content-type: text/plain" << CRLF2;
+               std::cout << "GENERAL ERROR: " << er.what() << CRLF;
                return 1;
        }
 

Added: trunk/examples/images.h
URL: 
http://svn.gna.org/viewcvs/mysqlpp/trunk/examples/images.h?rev=2380&view=auto
==============================================================================
--- trunk/examples/images.h (added)
+++ trunk/examples/images.h Mon Oct 27 21:49:52 2008
@@ -1,0 +1,32 @@
+/***********************************************************************
+ images.h - Declares the images table SSQLS.
+
+ Copyright (c) 2008 by Educational Technology Resources, Inc.
+ Others may also hold copyrights on code in this file.  See the
+ CREDITS file in the top directory of the distribution for details.
+
+ This file is part of MySQL++.
+
+ MySQL++ is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ MySQL++ is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
+ License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with MySQL++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+ USA
+***********************************************************************/
+
+#include <mysql++.h>
+#include <ssqls.h>
+
+sql_create_2(images,
+       1, 2,
+       mysqlpp::Null<mysqlpp::sql_int_unsigned>, id,
+       mysqlpp::Null<mysqlpp::sql_blob>, data)

Modified: trunk/examples/load_jpeg.cpp
URL: 
http://svn.gna.org/viewcvs/mysqlpp/trunk/examples/load_jpeg.cpp?rev=2380&r1=2379&r2=2380&view=diff
==============================================================================
--- trunk/examples/load_jpeg.cpp (original)
+++ trunk/examples/load_jpeg.cpp Mon Oct 27 21:49:52 2008
@@ -2,10 +2,10 @@
  load_jpeg.cpp - Example showing how to insert BLOB data into the
        database from a file.
 
- Copyright (c) 1998 by Kevin Atkinson, (c) 1999, 2000 and 2001 by
- MySQL AB, and (c) 2004-2007 by Educational Technology Resources, Inc.
- Others may also hold copyrights on code in this file.  See the CREDITS
- file in the top directory of the distribution for details.
+ Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and
+ (c) 2004-2008 by Educational Technology Resources, Inc.  Others may
+ also hold copyrights on code in this file.  See the CREDITS file in
+ the top directory of the distribution for details.
 
  This file is part of MySQL++.
 
@@ -26,9 +26,8 @@
 ***********************************************************************/
 
 #include "cmdline.h"
+#include "images.h"
 #include "printdata.h"
-
-#include <mysql++.h>
 
 #include <fstream>
 
@@ -43,11 +42,13 @@
 
 
 static bool
-is_jpeg(const unsigned char* img_data)
+is_jpeg(const char* img_data)
 {
-       return (img_data[0] == 0xFF) && (img_data[1] == 0xD8) &&
-                       ((memcmp(img_data + 6, "JFIF", 4) == 0) ||
-                        (memcmp(img_data + 6, "Exif", 4) == 0));
+       const unsigned char* idp =
+                       reinterpret_cast<const unsigned char*>(img_data);
+       return (idp[0] == 0xFF) && (idp[1] == 0xD8) &&
+                       ((memcmp(idp + 6, "JFIF", 4) == 0) ||
+                        (memcmp(idp + 6, "Exif", 4) == 0));
 }
 
 
@@ -65,24 +66,23 @@
                // Establish the connection to the database server.
                mysqlpp::Connection con(db, server, user, pass);
 
-               // Assume that the last command line argument is a file.  Try
-               // to read that file's data into img_data, and check it to see
-               // if it appears to be a JPEG file.  Bail otherwise.
-               string img_name, img_data;
+               // Try to create a new item in the images table, based on what
+               // we got on the command line.
+               images img(mysqlpp::null, mysqlpp::null);
+               const char* img_name = "NULL";
                if (argc - ag_optind >= 1) {
+                       // We received at least one non-option argument on the
+                       // command line, so treat it as a file name 
                        img_name = argv[ag_optind];
-                       ifstream img_file(img_name.c_str(), ios::ate);
+                       ifstream img_file(img_name, ios::ate);
                        if (img_file) {
                                size_t img_size = img_file.tellg();
                                if (img_size > 10) {
                                        img_file.seekg(0, ios::beg);
-                                       unsigned char* img_buffer = new 
unsigned char[img_size];
-                                       
img_file.read(reinterpret_cast<char*>(img_buffer),
-                                                       img_size);
+                                       char* img_buffer = new char[img_size];
+                                       img_file.read(img_buffer, img_size);
                                        if (is_jpeg(img_buffer)) {
-                                               img_data.assign(
-                                                               
reinterpret_cast<char*>(img_buffer),
-                                                               img_size);
+                                               img.data = 
mysqlpp::sql_blob(img_buffer, img_size);
                                        }
                                        else {
                                                cerr << '"' << img_file <<
@@ -94,25 +94,29 @@
                                        cerr << "File is too short to be a 
JPEG!" << endl;
                                }
                        }
+
+                       if (img.data.data.empty()) {
+                               // File name was bad, or file contents aren't 
JPEG.  
+                               print_usage(argv[0], "[jpeg_file]");
+                               return 1;
+                       }
                }
-               if (img_data.empty()) {
-                       print_usage(argv[0], "[jpeg_file]");
-                       return 1;
-               }
+               // else, no image given on command line, so insert SQL NULL
+               // instead of image data.  NULL BLOB columns in SSQLS is
+               // legal as of MySQL++ v3.0.7.
 
-               // Insert image data into the BLOB column in the images table.
-               // We're inserting it as an std::string instead of using the raw
-               // data buffer allocated above because we don't want the data
-               // treated as a C string, which would truncate the data at the
-               // first null character.
+               // Insert image data or SQL NULL into the images.data BLOB
+               // column.  By inserting it as an SSQLS with a mysqlpp::sql_blob
+               // member, we avoid truncating it at the first embedded C null
+               // character ('\0'), as would happen if we used the raw
+               // character buffer we allocated above.
                Query query = con.query();
-               query << "INSERT INTO images (data) VALUES(\"" <<
-                               mysqlpp::escape << img_data << "\")";
+               query.insert(img);
                SimpleResult res = query.execute();
 
-               // If we get here, insertion succeeded
+               // Report successful insertion
                cout << "Inserted \"" << img_name <<
-                               "\" into images table, " << img_data.size() <<
+                               "\" into images table, " << 
img.data.data.size() <<
                                " bytes, ID " << res.insert_id() << endl;
        }
        catch (const BadQuery& er) {

Modified: trunk/examples/resetdb.cpp
URL: 
http://svn.gna.org/viewcvs/mysqlpp/trunk/examples/resetdb.cpp?rev=2380&r1=2379&r2=2380&view=diff
==============================================================================
--- trunk/examples/resetdb.cpp (original)
+++ trunk/examples/resetdb.cpp Mon Oct 27 21:49:52 2008
@@ -175,7 +175,7 @@
                query.reset();          // forget template query info
                query << 
                                "CREATE TABLE images (" <<
-                               "  id INT UNSIGNED NOT NULL AUTO_INCREMENT, " <<
+                               "  id INT UNSIGNED AUTO_INCREMENT, " <<
                                "  data BLOB, " <<
                                "  PRIMARY KEY (id)" <<
                                ")";

Modified: trunk/lib/stadapter.cpp
URL: 
http://svn.gna.org/viewcvs/mysqlpp/trunk/lib/stadapter.cpp?rev=2380&r1=2379&r2=2380&view=diff
==============================================================================
--- trunk/lib/stadapter.cpp (original)
+++ trunk/lib/stadapter.cpp Mon Oct 27 21:49:52 2008
@@ -64,6 +64,13 @@
 SQLTypeAdapter::SQLTypeAdapter(const Null<string>& str, bool processed) :
 buffer_(new SQLBuffer(str.is_null ? null_str : str.data,
                str.is_null ? typeid(void) : typeid(str.data), str.is_null)),
+is_processed_(processed)
+{
+}
+
+SQLTypeAdapter::SQLTypeAdapter(const Null<String>& str, bool processed) :
+buffer_(new SQLBuffer(str.is_null ? null_str : str.data.data(),
+        str.is_null ? typeid(void) : typeid(str.data), str.is_null)),
 is_processed_(processed)
 {
 }

Modified: trunk/lib/stadapter.h
URL: 
http://svn.gna.org/viewcvs/mysqlpp/trunk/lib/stadapter.h?rev=2380&r1=2379&r2=2380&view=diff
==============================================================================
--- trunk/lib/stadapter.h (original)
+++ trunk/lib/stadapter.h Mon Oct 27 21:49:52 2008
@@ -284,6 +284,7 @@
        // Parallel interface for Null<>-wrapped versions of types we
        // support above.  No need for parallel documentation.
        SQLTypeAdapter(const Null<std::string>& str, bool processed = false);
+       SQLTypeAdapter(const Null<String>& str, bool processed = false);
        SQLTypeAdapter(Null<char> c);
        SQLTypeAdapter(Null<sql_tinyint> i);
        SQLTypeAdapter(Null<sql_tinyint_unsigned> i);


_______________________________________________
Mysqlpp-commits mailing list
[email protected]
https://mail.gna.org/listinfo/mysqlpp-commits

Reply via email to