[std.database]

Steve Teale steve.teale at britseyeview.com
Mon Oct 10 07:07:25 PDT 2011


Here's a sketch of an interface. This is based on my experiments with 
MySQL, and as such it is probably mid-level, and not a top level covers-
all interface.

Hopefully it will create a number of discussion points.

// Can interfaces include template functions???
interface SQLDBConnection
{
   @property Handle handle();
   Handle connect(string host, string user, string password,
                  string database = null);
   T getProperty(T)(string name);
   T getProperty(T)(int id);
   void setProperty(T)(T property, string name);
   void setProperty(T)(T property, int id);
   Handle disconnect();
}

// There should possibly be a connection pool as well, and that
// should handle the RAII aspects of connections. Handle is an
// alias to suit the database system.

interface Raw
{
   // Delete, insert, update, createXXX, and the like - no result set
   rowcount_t exec(string sql);
   // Select and such with result set - result set buffered to the
   // client to provide a Random Access Range of Rows
   rowcount_t execResultSet(string sql);
   // Select and such with result set - prepares for sequential
   // processing of an Input Range of Rows
   void execSequence(string sql);
  
    
   // Do the range defining methods need to be in the interface?
}

enum ParamDirection
{
	ParamIn,
   ParamOut,
   ParamInOut
}

interface Prepared
{
   void createParam(T)(ref T target, ParamDirection pd);
   void createInParams(T...)(ref T args)
   void createOutParams(T...)(ref T args)
   void createVariantParam(ref Variant v, ParamDirection pd);
   void createVariantParams(T...)(ref Variant[] va, T);

   // If D type arrays are the bound type, it's likely that some
   // updating of the bindings will be required when a new value
   // is set, since a.ptr and a.length may change. Otherwise
   // these operations are no-ops.
   void updateInputParam(T)(ref T target);
   void updateInParameters(T...)(ref T args);
   void updateInArray(Variant[]);
   void updateInStruct(S)(ref S s);

   // Create a set of in parameters from an array of Variants
   void setInArray(ref Variant[] va);
   // Create a set of out parameters from an array of Variants
   void setOutArray(ref Variant[] va);

   // Initialize an array of out Variants to types appropriate for a query
   void getTypesForArray(ref MyVariant[] va);

   // Create a set of input params from a struct
   void setInStruct(S)(ref S s) if (is(S== struct));
   // Create a set of out params from a struct
   void setOutStruct(S)(ref S s) if (is(S== struct));

   prepare(string sql);
   // Delete, update, createXXX, and the like - no result set
   // returns rows affected;
   rowcount_t exec();
   // Select and such with result set - result set buffered
   // to the client to
   // provide a Random Access Range of Rows
   rowcount_t execResultSet();
   // Select and such with result set - prepares for sequential
   // processing of an Input Range of Rows
   void execSequence();

   // A composite operation prepare, bind, and execute a statement
   // to get a single column value into a D variable.
   // execScalar(T)(ref T target);
   
   // Do the range defining methods need to be in the interface?
}

interface Row	// mmm bit close to Raw
{
   // Get the values from a fetched row into a D struct
   void rowToStruct(S)(ref S s) if (is(S == struct));
   // Get the values from a fetched row into an array of Variants
   void rowToStruct(ref Variant[] va);

   // Get a column value by index into a D variable from the current row
   T getValue(T)(out T target, int index, out bool isnull);
   // Get a column value by index into a D variable from the current row
   T getValue(T)(out T target, string colName, out bool isnull)

   string toString(uint index);
   string toString(string colName);
}

interface ResultSet
{
   // Get the entire result set into an array of structs/Variants
   S[] getAllRows(S)(ref S dummy) if (is(S == struct));
   Variant[] getAllRows();

   // This should be automated where possible
   void free();
}

I can currently do most of this for MySQL, and what I haven't done
is mostly rehashing of what I have.

As an example of how level 2 interfaces may differ from the top-level one
is that in my implementation, chunking is supported for transfer and 
disposal of large objects - either auto-chunking, or chunking via a 
delegate. That stuff is not shown here.

Steve



More information about the Digitalmars-d mailing list