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