Win32-SqlServer

 view release on metacpan or  search on metacpan

tableparam.cpp  view on Meta::CPAN

   // Check that table parameter are supported at all.
   if (mydata->provider < provider_sqlncli10 ||
       mydata->majorsqlversion < 10) {
       olledb_message(olle_ptr, -1, 1, 16,
           L"To use table parameters, you need SQL 2008 and SQL Server Native Client 10 or later.");
       return FALSE;
   }

   // Check that maxlen is legal.
   if (no_of_cols < 1 || no_of_cols > 1024) {
      olle_croak(olle_ptr, "Illegal number of columns (%d) specified for table-valued parameter",
              no_of_cols);
   }

   // Check that we have name for the type.
   if (! my_sv_is_defined(tabletypename)) {
      olle_croak(olle_ptr, "Name of type missing for table-valued parameter");
   }

   // Allocate the table parameter itself and initiate the area.
   New(902, tabledef, 1, tableparam);
   memset(tabledef, 0, sizeof(tableparam));

   tabledef->tabletypename = SV_to_BSTR(tabletypename);
   tabledef->no_of_cols = tabledef->cols_undefined = no_of_cols;
   tabledef->no_of_usedefault = 0;
   tabledef->colnamemap = newHV();
   New(902, tabledef->columns, no_of_cols, DBCOLUMNDESC);
   memset(tabledef->columns, 0, no_of_cols * sizeof(DBCOLUMNDESC));
   New(902, tabledef->colbindings, no_of_cols, DBBINDING);
   memset(tabledef->colbindings, 0, no_of_cols * sizeof(DBBINDING));
   New(902, tabledef->colbindstatus, no_of_cols, DBBINDSTATUS);
   memset(tabledef->colbindstatus, 0, no_of_cols * sizeof(DBBINDSTATUS));
   New(902, tabledef->usedefault, no_of_cols, BOOL);
   memset(tabledef->usedefault, FALSE, no_of_cols * sizeof(BOOL));
   New(902, tabledef->bindix, no_of_cols, UINT);
   memset(tabledef->bindix, ~0, no_of_cols * sizeof(UINT));

   // Set the table definition as the value for the current parameter.
   this_param->value.table = tabledef;

   // If the table parameter has a name, save it into a hash so that the
   // caller can refer to the parameter by name later.
   if (this_param->param_info.pwszName != NULL) {
      if (mydata->tableparams == NULL) {
         mydata->tableparams = newHV();
      }
      SV * sv_tabledef = newSViv((IV) tabledef);
      hv_store_ent(mydata->tableparams, paramname, sv_tabledef, 0);
   }

   return TRUE;
}

// add_column_props is called to handle XML and UDT columns to define
// the type name or schema collection.
static void add_column_props (SV           * olle_ptr,
                              DBCOLUMNDESC * coldesc,
                              SV           * typeinfo)
{
    DBPROPSET * propset;
    int         propscnt = 0;

    // Drop out if there is no typeinfo.
    if (! my_sv_is_defined(typeinfo)) {
       return;
    }

    SV * server   = newSV(sv_len(typeinfo));
    SV * database = newSV(sv_len(typeinfo));
    SV * schema   = newSV(sv_len(typeinfo));
    SV * object   = newSV(sv_len(typeinfo));
    int  ix = 0;
    DBPROPID  dbpropid;
    DBPROPID  schemapropid;
    DBPROPID  objectpropid;

    // First extract components from typeinfo.
    if (! parsename(olle_ptr, typeinfo, 0, server, database, schema, object)) {
       return;
    }

    // If there was a server, cry foul.
    if (sv_len(server) > 0) {
       BSTR typeinfo_str = SV_to_BSTR(typeinfo);
       olledb_message(olle_ptr, -1, -1, 16,
                      L"Type name/XML schema '%s' includes a server compenent.\n",
                      typeinfo_str);
       SysFreeString(typeinfo_str);
       SvREFCNT_dec(server);
       SvREFCNT_dec(database);
       SvREFCNT_dec(schema);
       SvREFCNT_dec(object);
       return;
    }

    // Find out how many components we have.
    if (sv_len(database) > 0) propscnt++;
    if (sv_len(schema) > 0) propscnt++;
    if (sv_len(object) > 0) propscnt++;

    // If there was nothing, just drop out.
    if (propscnt == 0)
        return;

    // Set up property ids
    switch (coldesc->wType) {
        case DBTYPE_UDT :
             dbpropid     = SSPROP_COL_UDT_CATALOGNAME;
             schemapropid = SSPROP_COL_UDT_SCHEMANAME;
             objectpropid = SSPROP_COL_UDT_NAME;
             break;

        case DBTYPE_XML :
             dbpropid     = SSPROP_COL_XML_SCHEMACOLLECTION_CATALOGNAME;
             schemapropid = SSPROP_COL_XML_SCHEMACOLLECTION_SCHEMANAME;
             objectpropid = SSPROP_COL_XML_SCHEMACOLLECTIONNAME;
             break;

         default :
             olle_croak(olle_ptr,
                        "Internal error: Unexpected value %d for data type in add_column_props",
                        coldesc->wType);
    }

    // Set up the property set.
    New(902, propset, 1, DBPROPSET);
    propset->guidPropertySet = DBPROPSET_SQLSERVERCOLUMN;
    propset->cProperties = propscnt;
    New(902, propset->rgProperties, propscnt, DBPROP);

    // Store database if any.
    if (sv_len(database) > 0) {
       propset->rgProperties[ix].dwPropertyID = dbpropid;
       propset->rgProperties[ix].colid = DB_NULLID;
       propset->rgProperties[ix].dwOptions = DBPROPOPTIONS_REQUIRED;
       VariantInit(&(propset->rgProperties[ix].vValue));
       propset->rgProperties[ix].vValue.vt = VT_BSTR;
       propset->rgProperties[ix].vValue.bstrVal = SV_to_BSTR(database);
       ix++;
    }

    // And schema if any.
    if (sv_len(schema) > 0) {
       propset->rgProperties[ix].dwPropertyID = schemapropid;
       propset->rgProperties[ix].colid = DB_NULLID;
       propset->rgProperties[ix].dwOptions = DBPROPOPTIONS_REQUIRED;
       VariantInit(&(propset->rgProperties[ix].vValue));
       propset->rgProperties[ix].vValue.vt = VT_BSTR;
       propset->rgProperties[ix].vValue.bstrVal = SV_to_BSTR(schema);
       ix++;
    }

    // And the type name.
    if (sv_len(object) > 0) {
       propset->rgProperties[ix].dwPropertyID = objectpropid;
       propset->rgProperties[ix].colid = DB_NULLID;
       propset->rgProperties[ix].dwOptions = DBPROPOPTIONS_REQUIRED;
       VariantInit(&(propset->rgProperties[ix].vValue));
       propset->rgProperties[ix].vValue.vt = VT_BSTR;
       propset->rgProperties[ix].vValue.bstrVal = SV_to_BSTR(object);
    }

    // And save the property set.
    coldesc->rgPropertySets = propset;
    coldesc->cPropertySets = 1;

    // We must clean up our SVs to not leak memory.
    SvREFCNT_dec(server);
    SvREFCNT_dec(database);
    SvREFCNT_dec(schema);
    SvREFCNT_dec(object);
}


//------------------------------------------------------------------------
// definetablecolumn, exposed in the mid-level interface.
int definetablecolumn(SV * olle_ptr,
                      SV * tblname,
                      SV * colname,
                      SV * sv_nameoftype,
                      SV * sv_maxlen,
                      SV * sv_precision,
                      SV * sv_scale,
                      SV * usedefault,
                      SV * typeinfo)
{
   internaldata    * mydata = get_internaldata(olle_ptr);
   tableparam      * tbldef;
   char            * nameoftype;
   DBLENGTH          maxlen;
   int               colno;
   int               colix;
   int               bindix;
   DBTYPE            typeind;
   DBCOLUMNDESC    * coldesc;
   DBPARAMBINDINFO   param_info;
   DBBINDING       * binding;

   // Check that we're in the state where we're accepting parameters at all.
   if (mydata->pending_cmd == NULL) {
      olle_croak(olle_ptr, "Cannot call definetablecolumn now. There is no pending command. Call initbatch first");
   }

   if (mydata->cmdtext_ptr != NULL) {
      olle_croak(olle_ptr, "Cannot call definetablecolumn now. There are unprocessed result sets. Call cancelbatch first");
   }

   // See if we have a table parameter to work with. The caller can specify
   // a name, or undef to work the the most recently added parameter.
   if (my_sv_is_defined(tblname)) {
      HE * he = hv_fetch_ent(mydata->tableparams, tblname, 0, 0);
      if (he == NULL) {
         olle_croak(olle_ptr, "Attempt to define column for parameter %s, but this is not a table-valued parameter",
                    SvPV_nolen(tblname));
      }
      tbldef = (tableparam *) SvIV(HeVAL(he));
   }
   else if (mydata->paramlast && mydata->paramlast->value.table != NULL) {
      tbldef = mydata->paramlast->value.table;
   }
   else {
      olle_croak(olle_ptr, "Cannot define table column without a parameter name now. Most recently entered parameter is not a table");
   }



( run in 0.511 second using v1.01-cache-2.11-cpan-71847e10f99 )