Logo Search packages:      
Sourcecode: dballe version File versions

dba_err dba_db_cursor_query ( dba_db_cursor  cur,
dba_record  query,
unsigned int  wanted,
unsigned int  modifiers 
)

Create and execute a database query.

The results are retrieved by iterating the cursor.

Parameters:
cur The dballe cursor to use for the query
query The record with the query data (see technical specifications, par. 1.6.4 "parameter output/input"
wanted The values wanted in output
modifiers Optional modifiers to ask for special query behaviours
Returns:
The error indicator for the function (
See also:
dba_err)

Definition at line 700 of file cursor.c.

References DBA_DB_MODIFIER_BEST, and DBA_RUN_OR_RETURN.

{
      const char* val;

      /* Reset the cursor to start a new query */
      dba_querybuf_reset(cur->query);
      dba_querybuf_reset(cur->where);
      cur->wanted = wanted;
      cur->from_wanted = 0;
      cur->input_seq = 1;
      cur->output_seq = 1;
      cur->accept_from_ana_context = 0;

      /* Scan query modifiers */
      cur->modifiers = modifiers;
      DBA_RUN_OR_RETURN(init_modifiers(cur, query));

      DBA_RUN_OR_RETURN(dba_querybuf_append(cur->query, "SELECT "));
      if (cur->modifiers & DBA_DB_MODIFIER_DISTINCT)
            DBA_RUN_OR_RETURN(dba_querybuf_append(cur->query, "DISTINCT "));
      if (cur->modifiers & DBA_DB_MODIFIER_BIGANA)
            DBA_RUN_OR_RETURN(dba_querybuf_append(cur->query, "straight_join "));

      /* Prepare WHERE part and see what needs to be available in the FROM part */
      DBA_RUN_OR_RETURN(make_where(cur, query));

      /* Prepare SELECT Part and see what needs to be available in the FROM part.
       * We do this after creating the WHERE part, so that we can add
       * more opportunistic extra values (see the end of make_select) */
      DBA_RUN_OR_RETURN(make_select(cur));

      /* Enforce join dependencies */
      if (cur->from_wanted & (DBA_DB_FROM_DBLO | DBA_DB_FROM_DSTA | DBA_DB_FROM_DANA))
            cur->from_wanted |= DBA_DB_FROM_CBS;
      if (cur->from_wanted & (DBA_DB_FROM_DDF))
            cur->from_wanted |= DBA_DB_FROM_C;
      if (cur->from_wanted & (DBA_DB_FROM_ADF))
            cur->from_wanted |= (DBA_DB_FROM_C | DBA_DB_FROM_D);
      if (cur->from_wanted & DBA_DB_FROM_PA && cur->from_wanted & DBA_DB_FROM_D)
            cur->from_wanted |= DBA_DB_FROM_C;

      /* Always join with context if we need to weed out the extra ana data */
      if (cur->modifiers & DBA_DB_MODIFIER_NOANAEXTRA)
            cur->from_wanted |= DBA_DB_FROM_C;

      /* Ignore anagraphical context unless explicitly requested */
      if (cur->from_wanted & DBA_DB_FROM_C && !cur->accept_from_ana_context)
      {
            DBA_RUN_OR_RETURN(dba_querybuf_append_list(cur->where, "c.datetime>='1001-01-01 00:00:00'"));
            TRACE("ignoring anagraphical context as it has not been explicitly requested: adding AND c.datetime >= '1002-01-01 00:00:00'\n");
      }

      /* Create the FROM part with everything that is needed */
      if (cur->from_wanted & DBA_DB_FROM_C)
      {
            DBA_RUN_OR_RETURN(dba_querybuf_append(cur->query, " FROM context AS c "));
            add_other_froms(cur, DBA_DB_FROM_C);
      } else if (cur->from_wanted & DBA_DB_FROM_PA) {
            DBA_RUN_OR_RETURN(dba_querybuf_append(cur->query, " FROM pseudoana AS pa "));
            add_other_froms(cur, DBA_DB_FROM_PA);
      } else if (cur->from_wanted & DBA_DB_FROM_D) {
            DBA_RUN_OR_RETURN(dba_querybuf_append(cur->query, " FROM data AS d "));
            add_other_froms(cur, DBA_DB_FROM_D);
      } else if (cur->from_wanted & DBA_DB_FROM_RI) {
            DBA_RUN_OR_RETURN(dba_querybuf_append(cur->query, " FROM repinfo AS ri "));
            add_other_froms(cur, DBA_DB_FROM_RI);
      }

      /* Append the WHERE part that we prepared previously */
      if (dba_querybuf_size(cur->where) > 0)
      {
            DBA_RUN_OR_RETURN(dba_querybuf_append(cur->query, "WHERE "));
            DBA_RUN_OR_RETURN(dba_querybuf_append(cur->query, dba_querybuf_get(cur->where)));
      }

      /* Append GROUP BY and ORDER BY as needed */
      if (cur->modifiers & DBA_DB_MODIFIER_UNSORTED)
      {
            if (cur->modifiers & DBA_DB_MODIFIER_BEST)
                  DBA_RUN_OR_RETURN(dba_querybuf_append(cur->query,
                        " GROUP BY d.id_var, c.id_ana, c.ltype, c.l1, c.l2, c.ptype, c.p1, c.p2, c.datetime "
                        "HAVING ri.prio=MAX(ri.prio)"));
      } else {
            if (cur->modifiers & DBA_DB_MODIFIER_BEST)
                  DBA_RUN_OR_RETURN(dba_querybuf_append(cur->query,
                        " GROUP BY d.id_var, c.id_ana, c.ltype, c.l1, c.l2, c.ptype, c.p1, c.p2, c.datetime "
                        "HAVING ri.prio=MAX(ri.prio) "
                        "ORDER BY c.id_ana, c.datetime, c.ltype, c.l1, c.l2, c.ptype, c.p1, c.p2"));
#define WANTS(mask) ((cur->from_wanted & (mask)) == (mask))
            else if (WANTS(DBA_DB_FROM_C | DBA_DB_FROM_RI))
                  DBA_RUN_OR_RETURN(dba_querybuf_append(cur->query,
                        " ORDER BY c.id_ana, c.datetime, c.ltype, c.l1, c.l2, c.ptype, c.p1, c.p2, ri.prio"));
#undef WANTS
            else if (cur->from_wanted & DBA_DB_FROM_C)
                  DBA_RUN_OR_RETURN(dba_querybuf_append(cur->query,
                        " ORDER BY c.id_ana, c.datetime, c.ltype, c.l1, c.l2, c.ptype, c.p1, c.p2"));
            else if (cur->from_wanted & DBA_DB_FROM_PA)
                  DBA_RUN_OR_RETURN(dba_querybuf_append(cur->query, " ORDER BY pa.id"));
      }

      /* Append LIMIT if requested */
      if ((val = dba_record_key_peek_value(query, DBA_KEY_LIMIT)) != NULL)
            DBA_RUN_OR_RETURN(dba_querybuf_appendf(cur->query, " LIMIT %s", val));

      TRACE("Performing query: %s\n", dba_querybuf_get(cur->query));

      if (cur->modifiers & DBA_DB_MODIFIER_STREAM)
      {
            int res = SQLSetStmtAttr(cur->stm, SQL_ATTR_CURSOR_TYPE, 
                        (SQLPOINTER)SQL_CURSOR_FORWARD_ONLY, SQL_IS_INTEGER);
            if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO))
                  return dba_db_error_odbc(SQL_HANDLE_STMT, cur->stm, "setting SQL_CURSOR_FORWARD_ONLY on DBALLE query");
      }

      /* Perform the query */
      {
            int res = SQLExecDirect(cur->stm, (unsigned char*)dba_querybuf_get(cur->query), dba_querybuf_size(cur->query));
            if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO))
                  return dba_db_error_odbc(SQL_HANDLE_STMT, cur->stm, "performing DBALLE query \"%s\"", dba_querybuf_get(cur->query));
      }

      /* Get the number of affected rows */
      {
            SQLINTEGER rowcount;
            int res = SQLRowCount(cur->stm, &rowcount);
            if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO))
                  return dba_db_error_odbc(SQL_HANDLE_STMT, cur->stm, "getting row count");
            cur->count = rowcount;
      }

      /* Retrieve results will happen in dba_db_cursor_next() */

      /* Done.  No need to deallocate the statement, it will be done by
       * dba_db_cursor_delete */
      return dba_error_ok();
}


Generated by  Doxygen 1.6.0   Back to index