Hi Vivien,

here it is a possible patch. I added only the function
gda_holder_take_static_value (), in this way it's possible to use both
strings or G_TYPE_* values.
Putting all the values static in my test program I could gain an average
performance of 20ms quicker than the normal method for 100 queries.
User should then care to free the const GValue* passed to the holder and
he must also be sure to let the holder has a valid GValue at query time.

Please review it and tell me what you think,

thanks and regards,
Massimo



Massimo Cora' wrote:
> 
> Vivien Malerba wrote:
>> 2008/8/25 Massimo Cora' <[EMAIL PROTECTED]>:
>>> Hi Vivien,
>>>
>>>
>>> while trying to optimize the speed of some queries I came on
>>> g_value_set_static_string (), which is good and faster than its brother
>>> g_value_set_str ().
>>> I was wondering if it was possibile to add a
>>> gda_holder_set_value_static_str ()?
>> This can be done, even if it would be usefull only for GdaHolder with
>> a G_TYPE_STRING value.
>>
>>> Another question, always in that fashion:
>>> gda_holder_take_value () takes as input a *value that is freed when the
>>> holder is re-set. That method returns TRUE if value has been set.
>>> I was thinking about this speed improvement:
>>> create a gda_holder_take_value_do_not_free () [well, the name is
>>> unlucky...] that when is re-set will return the stored value instead of
>>> freeing it. In this manner it's possible to reuse that GValue without a
>>> g_free () and g_value_new_*().
>> Could you provide a patch for this?
> 
> sure I'll try to come out with a patch ASAP.
> 
> regards,
> Massimo
> 
> 
> _______________________________________________
> gnome-db-list mailing list
> [email protected]
> http://mail.gnome.org/mailman/listinfo/gnome-db-list
> 
Index: libgda/gda-holder.c
===================================================================
--- libgda/gda-holder.c (revision 3210)
+++ libgda/gda-holder.c (working copy)
@@ -93,6 +93,7 @@
        
        gboolean         invalid_forced;
        gboolean         valid;
+       gboolean         is_freeable;
 
        GValue           *value;
        GValue          *default_value; /* CAN be either NULL or of any type */
@@ -267,6 +268,7 @@
        holder->priv->invalid_forced = FALSE;
        holder->priv->valid = TRUE;
        holder->priv->default_forced = FALSE;
+       holder->priv->is_freeable = TRUE;
        holder->priv->value = NULL;
        holder->priv->default_value = NULL;
 
@@ -339,6 +341,7 @@
                /* direct settings */
                holder->priv->invalid_forced = orig->priv->invalid_forced;
                holder->priv->valid = orig->priv->valid;
+               holder->priv->is_freeable = orig->priv->is_freeable;
                holder->priv->default_forced = orig->priv->default_forced;      
                if (orig->priv->value)
                        holder->priv->value = gda_value_copy 
(orig->priv->value);
@@ -466,8 +469,9 @@
 
                holder->priv->g_type = G_TYPE_INVALID;
 
-               if (holder->priv->value) {
-                       gda_value_free (holder->priv->value);
+               if (holder->priv->value) {                      
+                       if (holder->priv->is_freeable)
+                               gda_value_free (holder->priv->value);
                        holder->priv->value = NULL;
                }
 
@@ -792,23 +796,23 @@
 
        if (!value || !g_ascii_strcasecmp (value, "NULL")) 
                 return gda_holder_set_value (holder, NULL, error);
-        else {
-                GValue *gdaval = NULL;
+    else {
+               GValue *gdaval = NULL;
 
                if (!dh)
                        dh = gda_get_default_handler (holder->priv->g_type);
-                if (dh)
-                        gdaval = gda_data_handler_get_value_from_str (dh, 
value, holder->priv->g_type);
+               if (dh)
+               gdaval = gda_data_handler_get_value_from_str (dh, value, 
holder->priv->g_type);
 
-                if (gdaval)
+               if (gdaval)
                        return real_gda_holder_set_value (holder, gdaval, 
FALSE, error);
-                else {
+        else {
                        g_set_error (error, GDA_HOLDER_ERROR, 
GDA_HOLDER_STRING_CONVERSION_ERROR,
                                     _("Unable to convert string to '%s' 
type"), 
                                     gda_g_type_to_string 
(holder->priv->g_type));
-                        return FALSE;
+               return FALSE;
                }
-        }
+       }
 }
 
 /**
@@ -858,6 +862,12 @@
        gboolean was_valid = gda_holder_is_valid (holder);
 #endif
 
+       /* if the value has been set with gda_holder_take_static_value () 
you'll be able
+        * to change the value only with another call to 
real_gda_holder_set_value 
+        */
+       if (!holder->priv->is_freeable)
+               return FALSE;           
+               
        /* holder will be changed? */
        newnull = !value || gda_value_is_null (value);
        current_val = gda_holder_get_value (holder);
@@ -960,7 +970,149 @@
        return newvalid;
 }
 
+static GValue *
+real_gda_holder_set_const_value (GdaHolder *holder, const GValue *value, 
GError **error)
+{
+       gboolean changed = TRUE;
+       gboolean newvalid;
+       const GValue *current_val;
+       GValue *value_to_return = NULL;
+       gboolean newnull;
+#define DEBUG_HOLDER
+#undef DEBUG_HOLDER
+
+#ifdef DEBUG_HOLDER
+       gboolean was_valid = gda_holder_is_valid (holder);
+#endif
+
+       /* holder will be changed? */
+       newnull = !value || gda_value_is_null (value);
+       current_val = gda_holder_get_value (holder);
+       if (current_val == value)
+               changed = FALSE;
+       else if ((!current_val || gda_value_is_null ((GValue *)current_val)) && 
newnull)
+               changed = FALSE;
+       else if (value && current_val &&
+                (G_VALUE_TYPE (value) == G_VALUE_TYPE ((GValue *)current_val)))
+               changed = gda_value_differ (value, (GValue *)current_val);
+               
+       /* holder's validity */
+       newvalid = TRUE;
+       if (newnull && holder->priv->not_null) {
+               g_set_error (error, GDA_HOLDER_ERROR, 
GDA_HOLDER_VALUE_NULL_ERROR,
+                            _("Holder does not allow NULL values"));
+               newvalid = FALSE;
+               changed = TRUE;
+       }
+       else if (!newnull && (G_VALUE_TYPE (value) != holder->priv->g_type)) {
+               g_set_error (error, GDA_HOLDER_ERROR, 
GDA_HOLDER_VALUE_TYPE_ERROR,
+                            _("Wrong value type: expected type '%s' when 
value's type is '%s'"),
+                            gda_g_type_to_string (holder->priv->g_type),
+                            gda_g_type_to_string (G_VALUE_TYPE (value)));
+               newvalid = FALSE;
+               changed = TRUE;
+       }
+
+#ifdef DEBUG_HOLDER
+       g_print ("Changed holder %p (%s): value %s --> %s \t(type %d -> %d) 
VALID: %d->%d CHANGED: %d\n", 
+                holder, holder->priv->id,
+                current_val ? gda_value_stringify ((GValue *)current_val) : 
"_NULL_",
+                value ? gda_value_stringify ((value)) : "_NULL_",
+                current_val ? G_VALUE_TYPE ((GValue *)current_val) : 0,
+                value ? G_VALUE_TYPE (value) : 0, 
+                was_valid, newvalid, changed);
+#endif
+
+       /* end of procedure if the value has not been changed, after 
calculating the holder's validity */
+       if (!changed) {
+               holder->priv->invalid_forced = FALSE;
+               return NULL;
+       }
+
+       /* check if we are allowed to change value */
+       GError *lerror = NULL;
+       g_signal_emit (holder, gda_holder_signals[VALIDATE_CHANGE], 0, value, 
&lerror);
+       if (lerror) {
+               /* change refused by signal callback */
+               g_propagate_error (error, lerror);
+               return NULL;
+       }
+
+       /* new valid status */
+       holder->priv->invalid_forced = FALSE;
+       holder->priv->valid = newvalid;
+       holder->priv->is_freeable = FALSE;
+
+       /* check is the new value is the default one */
+       holder->priv->default_forced = FALSE;
+       if (holder->priv->default_value) {
+               if ((G_VALUE_TYPE (holder->priv->default_value) == 
GDA_TYPE_NULL) && newnull)
+                       holder->priv->default_forced = TRUE;
+               else if ((G_VALUE_TYPE (holder->priv->default_value) == 
holder->priv->g_type) &&
+                        value && (G_VALUE_TYPE (value) == 
holder->priv->g_type))
+                       holder->priv->default_forced = !gda_value_compare 
(holder->priv->default_value, value);
+       }
+
+       /* real setting of the value */
+       if (holder->priv->full_bind) {
+#ifdef DEBUG_HOLDER
+               g_print ("Holder %p is alias of holder %p => propagating 
changes to holder %p\n",
+                        holder, holder->priv->full_bind, 
holder->priv->full_bind);
+#endif
+               return real_gda_holder_set_const_value 
(holder->priv->full_bind, value, error);
+       }
+       else {
+               if (holder->priv->value) {
+                       value_to_return = holder->priv->value;
+                       holder->priv->value = NULL;
+               }
+
+               if (value) {
+                       if (newvalid) {
+                               holder->priv->value = value;
+                       }
+               }
+
+               g_signal_emit (holder, gda_holder_signals[CHANGED], 0);
+       }
+
+       return value_to_return;
+}
+
 /**
+ * gda_holder_take_static_value
+ * @holder: a #GdaHolder object
+ * @value: a const value to set the holder to
+ * @error: a place to store errors, or %NULL
+ *
+ * Sets the const value within the holder. If @holder is an alias for another
+ * holder, then the value is also set for that other holder.
+ *
+ * The value will not be freed, and user should take care of it, either for its
+ * freeing or for its correct value at the moment of query.
+ * 
+ * If the value is not different from the one already contained within @holder,
+ * then @holder is not chaged and no signal is emitted.
+ *
+ * Note1: if @holder can't accept the @value value, then this method returns 
NULL, and @holder will be left
+ * in an invalid state.
+ *
+ * Note2: before the change is accepted by @holder, the "validate-change" 
signal will be emitted (the value
+ * of which can prevent the change from happening) which can be connected to 
to have a greater control
+ * of which values @holder can have, or implement some business rules.
+ *
+ * Returns: TRUE if value has been set
+ */
+GValue *
+gda_holder_take_static_value (GdaHolder *holder, const GValue *value, GError 
**error)
+{
+       g_return_val_if_fail (GDA_IS_HOLDER (holder), FALSE);
+       g_return_val_if_fail (holder->priv, FALSE);
+
+       return real_gda_holder_set_const_value (holder, (GValue*) value, error);
+}
+
+/**
  * gda_holder_force_invalid
  * @holder: a #GdaHolder object
  *
@@ -986,7 +1138,8 @@
        holder->priv->valid = FALSE;
        
        if (holder->priv->value) {
-               gda_value_free (holder->priv->value);
+               if (holder->priv->is_freeable)
+                       gda_value_free (holder->priv->value);
                holder->priv->value = NULL;
        }
 
@@ -1048,7 +1201,8 @@
                holder->priv->default_forced = TRUE;
                holder->priv->invalid_forced = FALSE;
                if (holder->priv->value) {
-                       gda_value_free (holder->priv->value);
+                       if (holder->priv->is_freeable)
+                               gda_value_free (holder->priv->value);
                        holder->priv->value = NULL;
                }
        }
@@ -1361,7 +1515,8 @@
 
                /* get rid of the internal holder's value */
                if (holder->priv->value) {
-                       gda_value_free (holder->priv->value);
+                       if (holder->priv->is_freeable)
+                               gda_value_free (holder->priv->value);
                        holder->priv->value = NULL;
                }
 
Index: libgda/gda-holder.h
===================================================================
--- libgda/gda-holder.h (revision 3210)
+++ libgda/gda-holder.h (working copy)
@@ -75,6 +75,7 @@
 gchar              *gda_holder_get_value_str           (GdaHolder *holder, 
GdaDataHandler *dh);
 gboolean            gda_holder_set_value               (GdaHolder *holder, 
const GValue *value, GError **error);
 gboolean            gda_holder_take_value              (GdaHolder *holder, 
GValue *value, GError **error);
+GValue             *gda_holder_take_static_value       (GdaHolder *holder, 
const GValue *value, GError **error);
 gboolean            gda_holder_set_value_str           (GdaHolder *holder, 
GdaDataHandler *dh, const gchar *value, GError **error);
 
 const GValue       *gda_holder_get_default_value       (GdaHolder *holder);
Index: ChangeLog
===================================================================
--- ChangeLog   (revision 3211)
+++ ChangeLog   (working copy)
@@ -1,3 +1,14 @@
+2008-09-18  Massimo Cora'  <[EMAIL PROTECTED]>
+
+       * libgda/gda-holder.c (gda_holder_init), (gda_holder_copy),
+       (gda_holder_dispose), (real_gda_holder_set_value),
+       (real_gda_holder_set_const_value), (gda_holder_take_static_value),
+       (gda_holder_force_invalid), (gda_holder_set_value_to_default),
+       (gda_holder_set_full_bind):
+       * libgda/gda-holder.h:
+       added function gda_holder_take_static_value () to permit a quicker use 
of GValues
+       without allocation/deallocation. On my tests I can gain 20ms on 100 
queries.
+
 2008-09-18  Vivien Malerba <[EMAIL PROTECTED]>
 
        * libgda/gda-data-model.c: make gda_data_model_dump() work whith data 
models which

_______________________________________________
gnome-db-list mailing list
[email protected]
http://mail.gnome.org/mailman/listinfo/gnome-db-list

Reply via email to