Re: a better libtds

Brian Bruns <[email protected]>
Newsgroups gmane.comp.db.tds.freetds
Message-ID <CAAATWxm1Pb7A5C_oDZ=5qUZNA34PHkYTpvS_HZ=H+dRjooB=DA@mail.gmail.com>
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 <[email protected]> wrote:
> On Thu, 18 Aug 2011 20:39:31 -0400
> Brian Bruns <[email protected]> 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
> [email protected]
> http://lists.ibiblio.org/mailman/listinfo/freetds
>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.