Logo Search packages:      
Sourcecode: freetds version File versions

int tds_submit_prepare ( TDSSOCKET *  tds,
const char *  query,
const char *  id,
TDSDYNAMIC **  dyn_out 
)

tds_submit_prepare() creates a temporary stored procedure in the server. Currently works with TDS 5.0 and TDS7+

Parameters:
query language query with given placeholders (?)
id string to identify the dynamic query. Pass NULL for automatic generation.
dyn_out will receive allocated TDSDYNAMIC*. Any older allocated dynamic won't be freed, Can be NULL.
Returns:
TDS_FAIL or TDS_SUCCEED

Definition at line 197 of file query.c.

References tds_client_msg(), tds_count_placeholders(), tds_flush_packet(), tds_get_dynid(), tds_next_placeholders(), tds_put_string(), and tds_submit_prepare().

Referenced by tds_submit_prepare().

{
      int id_len, query_len;
      TDSDYNAMIC *dyn;

      if (!query)
            return TDS_FAIL;

      if (!IS_TDS50(tds) && !IS_TDS7_PLUS(tds)) {
            tdsdump_log(TDS_DBG_ERROR, "Dynamic placeholders only supported under TDS 5.0 and TDS 7.0+\n");
            return TDS_FAIL;
      }
      if (tds->state == TDS_PENDING) {
            tds_client_msg(tds->tds_ctx, tds, 20019, 7, 0, 1,
                         "Attempt to initiate a new SQL Server operation with results pending.");
            return TDS_FAIL;
      }
      tds_free_all_results(tds);

      /* allocate a structure for this thing */
      if (!id) {
      char *tmp_id = NULL;

            if (tds_get_dynid(tds, &tmp_id) == TDS_FAIL)
                  return TDS_FAIL;
            dyn = tds_alloc_dynamic(tds, tmp_id);
            TDS_ZERO_FREE(tmp_id);
            if (!dyn)
                  return TDS_FAIL;
      } else {
            dyn = tds_alloc_dynamic(tds, id);
      }
      if (!dyn)
            return TDS_FAIL;

      tds->cur_dyn = dyn;

      if (dyn_out)
            *dyn_out = dyn;

      tds->rows_affected = 0;
      tds->state = TDS_QUERYING;
      query_len = strlen(query);

      if (IS_TDS7_PLUS(tds)) {
      int len, i, n;
      const char *s, *e;

            tds->out_flag = 3;      /* RPC */
            /* procedure name */
            tds_put_smallint(tds, 10);
            tds_put_n(tds, "s\0p\0_\0p\0r\0e\0p\0a\0r\0e", 20);
            tds_put_smallint(tds, 0);

            /* return param handle (int) */
            tds_put_byte(tds, 0);
            tds_put_byte(tds, 1);   /* result */
            tds_put_byte(tds, SYBINTN);
            tds_put_byte(tds, 4);
            tds_put_byte(tds, 0);

            /* string with parameters types */
            tds_put_byte(tds, 0);
            tds_put_byte(tds, 0);
            tds_put_byte(tds, SYBNTEXT);  /* must be Ntype */
            if (IS_TDS80(tds))
                  tds_put_n(tds, tds->collation, 5);
            /* TODO build true param string from parameters */
            /* for now we use all "@PX varchar(80)," for parameters (same behavior of mssql2k) */
            n = tds_count_placeholders(query);
            len = n * 16 - 1;
            /* adjust for the length of X */
            for (i = 10; i <= n; i *= 10) {
                  len += n - i + 1;
            }
            tds_put_int(tds, len * 2);
            tds_put_int(tds, len * 2);
            for (i = 1; i <= n; ++i) {
      char buf[24];

                  sprintf(buf, "%s@P%d varchar(80)", (i == 1 ? "" : ","), i);
                  tds_put_string(tds, buf, -1);
            }

            /* string with sql statement */
            /* replace placeholders with dummy parametes */
            tds_put_byte(tds, 0);
            tds_put_byte(tds, 0);
            tds_put_byte(tds, SYBNTEXT);  /* must be Ntype */
            if (IS_TDS80(tds))
                  tds_put_n(tds, tds->collation, 5);
            len = (len + 1 - 14 * n) + query_len;
            tds_put_int(tds, len * 2);
            tds_put_int(tds, len * 2);
            s = query;
            /* TODO do a test with "...?" and "...?)" */
            for (i = 1;; ++i) {
      char buf[24];

                  e = tds_next_placeholders(s);
                  tds_put_string(tds, s, e ? e - s : strlen(s));
                  if (!e)
                        break;
                  sprintf(buf, "@P%d", i);
                  tds_put_string(tds, buf, -1);
                  s = e + 1;
            }

            /* 1 param ?? why ? flags ?? */
            tds_put_byte(tds, 0);
            tds_put_byte(tds, 0);
            tds_put_byte(tds, SYBINT4);
            tds_put_int(tds, 1);

            return tds_flush_packet(tds);
      }

      tds->out_flag = 0x0F;

      id_len = strlen(dyn->id);
      tds_put_byte(tds, TDS5_DYNAMIC_TOKEN);
      tds_put_smallint(tds, query_len + id_len * 2 + 21);
      tds_put_byte(tds, 0x01);
      tds_put_byte(tds, 0x00);
      tds_put_byte(tds, id_len);
      tds_put_n(tds, dyn->id, id_len);
      tds_put_smallint(tds, query_len + id_len + 16);
      tds_put_n(tds, "create proc ", 12);
      tds_put_n(tds, dyn->id, id_len);
      tds_put_n(tds, " as ", 4);
      tds_put_n(tds, query, query_len);

      return tds_flush_packet(tds);
}


Generated by  Doxygen 1.6.0   Back to index