[vlc-devel] [PATCH] Prepared statements for SQL
Laurent Aimar
fenrir at via.ecp.fr
Tue Nov 3 20:02:39 CET 2009
Hi,
On Tue, Oct 27, 2009, Srikanth Raju wrote:
> > +#define VLC_SQL_ROW 1
> > +#define VLC_SQL_DONE 2
> What are they used for? A doxy comment would be usefull.
> They're used as return values for sql_Run(). Documented.
> > What are they used for? A doxy comment would be usefull.
>
> > +struct sql_value_t
> > +{
> > + int length;
> > + union
> > + {
> > + int i;
> > + double dbl;
> > + char* psz;
> > + void* ptr;
> > + } value;
> > +};
> You could merge it with:
> > +typedef struct sql_value_t sql_value_t;
>
> I didn't because the other typedefs arent.
The others cannot be easily merged while this one can.
> > +struct sql_stmt_t
> > +{
> > + sql_t* p_sql;
> > + sql_stmt_sys_t *p_sys;
> > +};
> I don't think that explicitly declaring sql_stmt_t is needed.
> It seems that is only needed by the plugin implementation.
>
> Needed only by the plugin implementation meaning? It's required by users
> of
> the sql module.
A user will already have the p_sql pointer somewhere, so it leaves only
sql_stmt_sys_t and so making sql_stmt_t opaque will replace it and is simpler.
> > +/**
> > + * @brief Bind arguments to a sql_stmt_t object
> > + * @param p_sql The SQL object
> > + * @param p_stmt Statement Object
> > + * @param type Data type of the value
> > + * @param p_value Value to be bound
> > + * @param i_length For values which require a length
> > + * @param i_pos Position at which the parameter should be bound
> > + * @return VLC_SUCCESS or VLC_EGENERIC
> > + */
> > +static inline int sql_BindGeneric( sql_t* p_sql, sql_stmt_t* p_stmt,
> > + sql_type_e type, sql_value_t* p_value, int i_pos )
> I think using int instead of sql_type_e is better for binary
> compatibility.
>
> Type safety?
The problem with sql_type_e is that the size of the storage of an enum is
compiler dependant and so the ABI would easily be broken.
Now, I don't feel strongly about it, anyone cares to comment ?
> > +#define sql_GetIntegerColumn( A, B, C, D ) sql_GetColumn( A, B, C,
> SQL_INT, D )
> > +#define sql_GetDoubleColumn( A, B, C, D ) sql_GetColumn( A, B, C,
> SQL_DOUBLE, D )
> > +#define sql_GetTextColumn( A, B, C, D ) sql_GetColumn( A, B, C,
> SQL_TEXT, D )
> > +#define sql_GetBlobColumn( A, B, C, D ) sql_GetColumn( A, B, C,
> SQL_BLOB, D )
> I think more advanced wrapper would be helpful, they could completly
> hide sql_value_t.
>
>
> I'm not sure why one would want to hide the type of the value, because
> that was one of the reasons the prepared statement interface is being
> included. So that there may be stronger type checking.
That's why better wrappers will help.
Something like that for example:
static inline int sql_GetColumnInteger( sql_t* p_sql, sql_stmt_t* p_stmt, int i_col, int *pi_res)
{
sql_value_t v;
if(sql_GetColumn(..., &v))
return VLC_EGENERIC;
*pi_res = v.i_int;
return VLC_SUCCESS;
}
It will make sure that you don't do a sql_GetColumnInteger(&v) and then uses
v.dbl for example.
> + /** Create a statement object */
> + sql_stmt_t* (*pf_prepare) ( sql_t* p_sql, const char* psz_fmt,
> + int i_length );
Please, change the psz_ prefix into p_ to avoid confusion as it is not always
a 0 terminated string.
> + /** Bind parameters to a statement */
> + int (*pf_bind) ( sql_t* p_sql, sql_stmt_t* p_stmt, sql_type_e type,
> + sql_value_t* p_value, int i_pos );
How is p_value used ? As an input or as a pointer where the output value
will be stored ? (If as an input, a const is probably needed).
> +
> + /** Get the datatype for a specified column */
> + int (*pf_gettype) ( sql_t* p_sql, sql_stmt_t* p_stmt, int i_col,
> + sql_type_e* type );
> +
> + /** Get the data from a specified column */
> + int (*pf_getcolumn) ( sql_t* p_sql, sql_stmt_t* p_stmt, int i_col,
> + sql_type_e type, sql_value_t *p_res );
> };
As a general remark, I don't think the order of the arguments of
pf_bind/pf_gettype/pf_getcolumn are consistant (or I missed the logic).
Regards,
--
fenrir
More information about the vlc-devel
mailing list