glom r1775 - in trunk: . glom glom/libglom/data_structure
- From: arminb svn gnome org
- To: svn-commits-list gnome org
- Subject: glom r1775 - in trunk: . glom glom/libglom/data_structure
- Date: Fri, 5 Dec 2008 17:05:10 +0000 (UTC)
Author: arminb
Date: Fri Dec 5 17:05:10 2008
New Revision: 1775
URL: http://svn.gnome.org/viewvc/glom?rev=1775&view=rev
Log:
2008-12-05 Armin Burgmeier <armin openismus com>
* glom/libglom/data_structure/glomconversions.h:
* glom/libglom/data_structure/glomconversions.cc: Replaced
get_escaped_binary_data by escape_binary_data_postgres() and
escape_binary_data_sqlite(). SQLite uses a different format for binary
data.
(get_text_for_gda_value): Allow DATE and TIME values to be strings,
and parse them always in ISO format. This is used for SQLite within
which we store dates and times as ISO-formatted strings.
* glom/libglom/data_structure/field.cc (glom_unescape_text): Don't
unescape double quotes, as they are not escaped in glom_escape_text
either.
(sql): Use the escape_binary_data_postgres or
escape_binary_data_sqlite functions from glomconversions, depending on
the preferred format.
(from_sql): Use the unescape_binary_data_postgres or
unescape_binary_data_sqlite functions from glomconversions, depending
on the preferred format.
Modified:
trunk/ChangeLog
trunk/glom/base_db.cc
trunk/glom/libglom/data_structure/field.cc
trunk/glom/libglom/data_structure/glomconversions.cc
trunk/glom/libglom/data_structure/glomconversions.h
Modified: trunk/glom/base_db.cc
==============================================================================
--- trunk/glom/base_db.cc (original)
+++ trunk/glom/base_db.cc Fri Dec 5 17:05:10 2008
@@ -1253,7 +1253,7 @@
{
const type_vecStrings vec_values = Utils::string_separate(row_data, ",", true /* ignore , inside quotes */);
if(true) //vec_values.size() == fields_count)
- {
+ {
//Do not allow any unescaped newlines in the row data.
//Note that this is checking for newlines ("\n"), not escaped newlines ("\\n").
Glib::ustring converted_row_data;
@@ -1277,10 +1277,10 @@
bool success;
const Gnome::Gda::Value value = vec_fields[i]->from_sql(vec_values[i], Field::SQL_FORMAT_POSTGRES, success);
- if(success)
+ if(success)
converted_row_data += vec_fields[i]->sql(value, connection_pool->get_sql_format());
- else
- converted_row_data += "''";
+ else
+ converted_row_data += "''";
}
actual_row_data = &converted_row_data;
@@ -1291,7 +1291,7 @@
if(query_execute(strQuery))
//std::cout << "debug: after query: " << strQuery << std::endl;
insert_succeeded = true;
- else
+ else
{
insert_succeeded = false;
break;
@@ -1988,12 +1988,12 @@
#ifdef GLIBMM_EXCEPTIONS_ENABLED
sharedptr<SharedConnection> sharedconnection = connect_to_server(0 /* parent window */);
#else
- std::auto_ptr<ExceptionConnection> error;
- sharedptr<SharedConnection> sharedconnection = connect_to_server(0 /* parent window */, error);
- // TODO: Rethrow?
+ std::auto_ptr<ExceptionConnection> error;
+ sharedptr<SharedConnection> sharedconnection = connect_to_server(0 /* parent window */, error);
+ // TODO: Rethrow?
#endif
- g_assert(sharedconnection);
+ g_assert(sharedconnection);
refCalcProgress.m_value = glom_evaluate_python_function_implementation(field->get_glom_type(), field->get_calculation(), field_values, get_document(), field_in_record.m_table_name, sharedconnection->get_gda_connection());
Modified: trunk/glom/libglom/data_structure/field.cc
==============================================================================
--- trunk/glom/libglom/data_structure/field.cc (original)
+++ trunk/glom/libglom/data_structure/field.cc Fri Dec 5 17:05:10 2008
@@ -291,6 +291,8 @@
result += '\'';
++ iter;
}
+ /* double quotes are not escaped, so don't unescape them. */
+#if 0
// Unescape "" to ".
else if(*iter == '\"')
{
@@ -299,6 +301,7 @@
result += '\"';
++ iter;
}
+#endif
// Escape sequence beginning with backslash.
else if(*iter == '\\')
{
@@ -425,15 +428,21 @@
const guchar* buffer = value.get_binary(buffer_length);
if(buffer && buffer_length > 0)
{
- //Get the escaped text that represents the binary data:
- const std::string escaped_binary_data = Conversions::get_escaped_binary_data((guint8*)buffer, buffer_length);
- //Now escape that text (to convert \ to \\, for instance):
- //The E prefix indicates ""escape" string constants, which are an extension to the SQL standard"
- //Otherwise, we get a warning when using large escaped strings:
if(format == SQL_FORMAT_POSTGRES)
- str = "E" + glom_escape_text(escaped_binary_data) /* has quotes */ + "::bytea";
+ {
+ //Get the escaped text that represents the binary data:
+ const std::string escaped_binary_data = Conversions::escape_binary_data_postgres((guint8*)buffer, buffer_length);
+ //Now escape that text (to convert \ to \\, for instance):
+ //The E prefix indicates ""escape" string constants, which are an extension to the SQL standard"
+ //Otherwise, we get a warning when using large escaped strings:
+ if(format == SQL_FORMAT_POSTGRES)
+ str = "E" + glom_escape_text(escaped_binary_data) /* has quotes */ + "::bytea";
+ }
else
- str = glom_escape_text(escaped_binary_data);
+ {
+ const std::string escaped_binary_data = Conversions::escape_binary_data_sqlite((guint8*)buffer, buffer_length);
+ str = "x'" + escaped_binary_data + "'";
+ }
}
}
else
@@ -502,27 +511,58 @@
// is expensive, and we only check for ASCII stuff anyway.
const std::string& raw = str.raw();
+ Glib::ustring unescaped;
switch(format)
{
case SQL_FORMAT_POSTGRES:
if(raw.length() >= 10 &&
raw.compare(0, 2, "E'") == 0 && raw.compare(raw.length() - 8, 8, "'::bytea") == 0)
{
- std::string unescaped = glom_unescape_text(raw.substr(1, raw.length() - 8));
- NumericFormat format_ignored; //Because we use ISO format.
- return Conversions::parse_value(m_glom_type, unescaped, format_ignored, success, true);
+ unescaped = glom_unescape_text(raw.substr(1, raw.length() - 8));
+ }
+ // The E can be omitted, and it is in some example files, such as
+ // example_smallbusiness.glom. We need to parse this to convert the
+ // data into sqlite format, when the small bussiness example is loaded
+ // into a sqlite database.
+ else if(raw.length() >= 9 &&
+ raw.compare(0, 1, "'") == 0 && raw.compare(raw.length() - 8, 8, "'::bytea") == 0)
+ {
+ unescaped = glom_unescape_text(raw.substr(0, raw.length() - 7));
}
- else
+
+ if(!unescaped.empty())
{
- success = false;
- return Gnome::Gda::Value();
+ gsize length;
+ guint8* binary_data = Conversions::unescape_binary_data_postgres(unescaped, length);
+ if(binary_data)
+ {
+ Gnome::Gda::Value value;
+ value.set(binary_data, length);
+ g_free(binary_data);
+ return value;
+ }
}
+
+ success = false;
+ return Gnome::Gda::Value();
case SQL_FORMAT_SQLITE:
+ if(raw.length() >= 3 &&
+ (raw.compare(0, 2, "x'") == 0 || raw.compare(0, 2, "X'")) &&
+ raw.compare(raw.length() - 1, 1, "'") == 0)
{
- std::string unescaped = glom_unescape_text(raw);
- NumericFormat format_ignored; //Because we use ISO format.
- return Conversions::parse_value(m_glom_type, unescaped, format_ignored, success, true);
+ gsize length;
+ guint8* binary_data = Conversions::unescape_binary_data_sqlite(raw.substr(2, raw.length()), length);
+ if(binary_data)
+ {
+ Gnome::Gda::Value value;
+ value.set(binary_data, length);
+ g_free(binary_data);
+ return value;
+ }
}
+
+ success = false;
+ return Gnome::Gda::Value();
default:
g_assert_not_reached();
break;
Modified: trunk/glom/libglom/data_structure/glomconversions.cc
==============================================================================
--- trunk/glom/libglom/data_structure/glomconversions.cc (original)
+++ trunk/glom/libglom/data_structure/glomconversions.cc Fri Dec 5 17:05:10 2008
@@ -35,6 +35,24 @@
#include <iomanip>
#include <string.h> // for strlen, memset, strcmp
+namespace
+{
+ char hextochar(guint8 hex)
+ {
+ if(hex < 10) return '0' + hex;
+ if(hex < 16) return 'a' - 10 + hex;
+ return '\0';
+ }
+
+ guint8 chartohex(char c)
+ {
+ if(c >= '0' && c <= '9') return c - '0';
+ if(c >= 'a' && c <= 'f') return c - 'a' + 10;
+ if(c >= 'A' && c <= 'F') return c - 'A' + 10;
+ return 0;
+ }
+}
+
namespace Glom
{
@@ -300,18 +318,39 @@
return "";
}
- if( (glom_type == Field::TYPE_DATE) && (value.get_value_type() == G_TYPE_DATE))
+ if(glom_type == Field::TYPE_DATE)
{
- Glib::Date gda_date = value.get_date();
- //Gnome::Gda::Date gda_date = value.get_date();
-
- //tm the_c_time = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
tm the_c_time;
memset(&the_c_time, 0, sizeof(the_c_time));
- the_c_time.tm_year = gda_date.get_year() - 1900; //C years start are the AD year - 1900. So, 01 is 1901.
- the_c_time.tm_mon = gda_date.get_month() - 1; //C months start at 0.
- the_c_time.tm_mday = gda_date.get_day(); //starts at 1
+ if(value.get_value_type() == G_TYPE_STRING)
+ {
+ // If a date is contained in a string type instead of a date type,
+ // which can happen if the database system does not support dates
+ // natively, then the string representation is always in ISO format.
+ bool success;
+ the_c_time = parse_date(value.get_string(), std::locale::classic(), success);
+ if(!success)
+ std::cerr << "Conversions::get_text_for_gda_value(): Failed to convert string-represented date value" << std::endl;
+ }
+ else if(value.get_value_type() == G_TYPE_DATE)
+ {
+ Glib::Date gda_date = value.get_date();
+ //Gnome::Gda::Date gda_date = value.get_date();
+
+ //tm the_c_time = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+
+ the_c_time.tm_year = gda_date.get_year() - 1900; //C years start are the AD year - 1900. So, 01 is 1901.
+ the_c_time.tm_mon = gda_date.get_month() - 1; //C months start at 0.
+ the_c_time.tm_mday = gda_date.get_day(); //starts at 1
+ }
+ else
+ {
+ std::cerr << "Conversions::get_text_for_gda_value(): glom field type is DATE but GdaValue type is: " << g_type_name(value.get_value_type()) << std::endl;
+
+ // Default
+ the_c_time.tm_mday = 1;
+ }
return format_date(the_c_time, locale, iso_format);
@@ -323,15 +362,32 @@
}
else if((glom_type == Field::TYPE_TIME) && (value.get_value_type() == GDA_TYPE_TIME))
{
- Gnome::Gda::Time gda_time = value.get_time();
-
- //tm the_c_time = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
tm the_c_time;
memset(&the_c_time, 0, sizeof(the_c_time));
+ if(value.get_value_type() == G_TYPE_STRING)
+ {
+ // If a time is contained in a string type instead of a gda time type,
+ // which can happen if the database system does not support times
+ // natively, then the string representation is always in ISO format.
+ bool success;
+ the_c_time = parse_time(value.get_string(), std::locale::classic(), success);
+ if(!success)
+ std::cerr << "Conversions::get_text_for_gda_value(): Failed to convert string-represented time value" << std::endl;
+ }
+ else if(value.get_value_type() == GDA_TYPE_TIME)
+ {
+ Gnome::Gda::Time gda_time = value.get_time();
+
+ //tm the_c_time = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
- the_c_time.tm_hour = gda_time.hour;
- the_c_time.tm_min = gda_time.minute;
- the_c_time.tm_sec = gda_time.second;
+ the_c_time.tm_hour = gda_time.hour;
+ the_c_time.tm_min = gda_time.minute;
+ the_c_time.tm_sec = gda_time.second;
+ }
+ else
+ {
+ std::cerr << "Conversions::get_text_for_gda_value(): glom field type is TIME but GdaValue type is: " << g_type_name(value.get_value_type()) << std::endl;
+ }
return format_time(the_c_time, locale, iso_format);
}
@@ -394,12 +450,13 @@
}
else if(glom_type == Field::TYPE_IMAGE)
{
- //Return the binary-as-escaped-text format, suitable for use in the document.
+ //Return the binary-as-escaped-text format, suitable for use in the document.
+ //TODO: Where do we need this? Do we need to have this in SQLite format sometimes?
std::string result;
long buffer_length;
const guchar* buffer = value.get_binary(buffer_length);
if(buffer && buffer_length > 0)
- result = Conversions::get_escaped_binary_data((guint8*)buffer, buffer_length);
+ result = Conversions::escape_binary_data_postgres((guint8*)buffer, buffer_length);
return result;
}
@@ -552,10 +609,11 @@
{
//We assume that the text is the same (escaped text) format that we use in the document when saving images:
//(The SQL format).
+ // TODO: For what do we need this? Does this have to be in SQLite format sometimes?
Gnome::Gda::Value result;
size_t buffer_binary_length = 0;
- guchar* buffer_binary = Glom_PQunescapeBytea((const guchar*)text.c_str() /* must be null-terminated */, &buffer_binary_length); //freed by us later.
+ guchar* buffer_binary = Conversions::unescape_binary_data_postgres(text, buffer_binary_length); //freed by us later.
if(buffer_binary)
{
result.set(buffer_binary, buffer_binary_length);
@@ -1043,7 +1101,7 @@
return tmpbuf;
}
-Glib::ustring Conversions::get_escaped_binary_data(guint8* buffer, size_t buffer_size)
+Glib::ustring Conversions::escape_binary_data_postgres(guint8* buffer, size_t buffer_size)
{
//g_warning("Conversions::get_escaped_binary_data: debug: buffer ");
//for(int i = 0; i < 10; ++i)
@@ -1085,6 +1143,44 @@
return result;
}
+Glib::ustring Conversions::escape_binary_data_sqlite(guint8* buffer, size_t buffer_size)
+{
+ // The sqlite format is two characters representing a byte in hexadecimal
+ // notation.
+ Glib::ustring result;
+ result.reserve(buffer_size*2);
+ for(unsigned int i = 0; i < buffer_size; ++ i)
+ {
+ result += hextochar((buffer[i] & 0xf0) >> 4);
+ result += hextochar((buffer[i] & 0x0f) );
+ }
+
+ return result;
+}
+
+guint8* Conversions::unescape_binary_data_postgres(const Glib::ustring& escaped_binary_data, size_t& length)
+{
+ return Glom_PQunescapeBytea((const guchar*)escaped_binary_data.c_str(), &length);
+}
+
+guint8* Conversions::unescape_binary_data_sqlite(const Glib::ustring& escaped_binary_data, size_t& length)
+{
+ g_assert(escaped_binary_data.bytes() % 2 == 0);
+
+ length = escaped_binary_data.bytes()/2;
+ const char* in_data = escaped_binary_data.c_str();
+ // Use malloc here, since unescape_binary_data_postgres also uses malloc
+ // in Glom_PQunescapeBytea and we want the API to stay consistent.
+ guint8* out_data = static_cast<guint8*>(malloc(length));
+ if(!out_data) { length = 0; return NULL; }
+
+ // The sqlite format is two characters representing a byte in hexadecimal
+ // notation.
+ for(unsigned int i = 0; i < length; ++i)
+ out_data[i] = chartohex(in_data[2*i] << 4) | chartohex(in_data[2*i+1]);
+ return out_data;
+}
+
Gnome::Gda::Value Conversions::convert_value(const Gnome::Gda::Value& value, Field::glom_field_type target_glom_type)
{
const GType gvalue_type = value.get_value_type();
Modified: trunk/glom/libglom/data_structure/glomconversions.h
==============================================================================
--- trunk/glom/libglom/data_structure/glomconversions.h (original)
+++ trunk/glom/libglom/data_structure/glomconversions.h Fri Dec 5 17:05:10 2008
@@ -81,7 +81,10 @@
Gnome::Gda::Value get_example_value(Field::glom_field_type field_type);
///Get a string representing binary data, for SQL
- Glib::ustring get_escaped_binary_data(guint8* buffer, size_t buffer_size);
+ Glib::ustring escape_binary_data_postgres(guint8* buffer, size_t buffer_size);
+ Glib::ustring escape_binary_data_sqlite(guint8* buffer, size_t buffer_size);
+ guint8* unescape_binary_data_postgres(const Glib::ustring& escaped_binary_data, size_t& length);
+ guint8* unescape_binary_data_sqlite(const Glib::ustring& escaped_binary_data, size_t& length);
Gnome::Gda::Value convert_value(const Gnome::Gda::Value& value, Field::glom_field_type target_glom_type);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]