Skip to Content.
Sympa Menu

freetds - Re: [freetds] a better libtds

freetds AT lists.ibiblio.org

Subject: FreeTDS Development Group

List archive

Chronological Thread  
  • From: Brian Bruns <brian AT bruns.com>
  • To: FreeTDS Development Group <freetds AT lists.ibiblio.org>
  • Subject: Re: [freetds] a better libtds
  • Date: Mon, 22 Aug 2011 10:53:02 -0400

If I'm understanding you correctly, you want a structure with an enum
and essentially an array of void * to all the elements and then to use
it you need to cast the void * back depending on the value of the
attached datatype? I'm a little dubious to this making the code more
approachable for newcomers.

Another popular approach is to use an offset into the destination
structure and a function reference to the reader (either a canned ones
or custom). So, in libtds we get something like (glossing over the
flags bit values, should use bit fields)

struct {
uint16 flags;
uint16 unknown;
uint32 rowcount;
} tds_done_inproc;

tds_member_t done_in_proc_reader[] = {
{
offsetof(tds_done_inproc, flags),
tds_read_uint16
},
{
offsetof(tds_done_inproc, unknown),
tds_read_uint16
},
{
offsetof(tds_done_inproc, rowcount),
tds_read_uint32
},
};

where tds_read_uint16 and tds_read_uint32 are functions. So we can
have a library of the basic functions for various data (ints of
different sizes, strings, bit flags, whatever) and specialized
functions for things like TDS_ROW that has complicated parsing.

The nice part is this is easily generated from a table of grammars,
and you get a nice usable structure on the other end (as opposed to a
nameless array of elements if I'm understanding you correctly), no
casting from void * necessary. Do the same in reverse for
writing..things like XOR key password could be a function and you just
pass the plain text and the function pointer handles the ugly bits.

Brian

On Mon, Aug 22, 2011 at 9:52 AM, James K. Lowden <jklowden AT freetds.org> wrote:
> On Thu, 18 Aug 2011 20:39:31 -0400
> Brian Bruns <brian AT bruns.com> wrote:
>
>> MARSy type stuff would be easier (can have a separate state machine
>> for TDS+MARS), SSL/TDS isn't such a kludge, and deferred/asynchronous
>> I/O gets a whole lot easier.  This also makes something like TDS over
>> RPC or named pipes much more approachable.
>>
>> I think everyone agrees the byte-by-byte read from the wire idiom that
>> libtds is written in is a disaster.
>>
>> Is this along the lines of what you were thinking Jim?
>
> Yes, indeed, Brian, it is.
>
> The byte-by-byte write idiom isn't much better (although it doesn't
> occur as much, mostly in login, bcp, and parameterized queries).  It's
> hard to avoid because a C struct doesn't contain enough run-time
> information to drive a generalized packet-writer, what the Java folks
> call "reflection". That is, there's no way at run-time to enumerate a
> struct's elements, let alone their types.  If, however, C structs
> were generated from a table describing the packet, the generator could
> include an array of types and addresses, viz:
>
>        struct tds_member_t {
>                TDS_TYPE type;
>                void *   addr;
>        };
>
>        struct tds_XXX_packet {
>                enum {tds_XXX_packet_nelem = NN};
>                struct tds_member_t elem[NN];
>                ...
>        };
>
> Now we need only one packet writer.  Each elem is only an alias to a
> struct member.  The packet-writer iterates over elem, and writes it to
> the wire according to the rules of TDS.  When populating the struct,
> the member can be more conveniently referenced by name.
>
> It might prove convenient to use a similar structure for TDS_ROW; it
> could unify the structure of regular and compute rows.
>
> --jkl
> _______________________________________________
> FreeTDS mailing list
> FreeTDS AT lists.ibiblio.org
> http://lists.ibiblio.org/mailman/listinfo/freetds
>




Archive powered by MHonArc 2.6.24.

Top of Page