Exemple #1
0
static int o_read_database_query (o_database_t *db, /* {{{ */
    udb_query_t *q, udb_query_preparation_area_t *prep_area)
{
  char **column_names;
  char **column_values;
  size_t column_num;

  OCIStmt *oci_statement;

  /* List of `OCIDefine' pointers. These defines map columns to the buffer
   * space declared above. */
  OCIDefine **oci_defines;

  int status;
  size_t i;

  oci_statement = udb_query_get_user_data (q);

  /* Prepare the statement */
  if (oci_statement == NULL) /* {{{ */
  {
    const char *statement;

    statement = udb_query_get_statement (q);
    assert (statement != NULL);

    status = OCIHandleAlloc (oci_env, (void *) &oci_statement,
        OCI_HTYPE_STMT, /* user_data_size = */ 0, /* user_data = */ NULL);
    if (status != OCI_SUCCESS)
    {
      o_report_error ("o_read_database_query", db->name,
          udb_query_get_name (q), "OCIHandleAlloc", oci_error);
      oci_statement = NULL;
      return (-1);
    }

    status = OCIStmtPrepare (oci_statement, oci_error,
        (text *) statement, (ub4) strlen (statement),
        /* language = */ OCI_NTV_SYNTAX,
        /* mode     = */ OCI_DEFAULT);
    if (status != OCI_SUCCESS)
    {
      o_report_error ("o_read_database_query", db->name,
          udb_query_get_name (q), "OCIStmtPrepare", oci_error);
      OCIHandleFree (oci_statement, OCI_HTYPE_STMT);
      oci_statement = NULL;
      return (-1);
    }
    udb_query_set_user_data (q, oci_statement);

    DEBUG ("oracle plugin: o_read_database_query (%s, %s): "
        "Successfully allocated statement handle.",
        db->name, udb_query_get_name (q));
  } /* }}} */

  assert (oci_statement != NULL);

  /* Execute the statement */
  status = OCIStmtExecute (db->oci_service_context, /* {{{ */
      oci_statement,
      oci_error,
      /* iters = */ 0,
      /* rowoff = */ 0,
      /* snap_in = */ NULL, /* snap_out = */ NULL,
      /* mode = */ OCI_DEFAULT);
  if (status != OCI_SUCCESS)
  {
    o_report_error ("o_read_database_query", db->name, udb_query_get_name (q),
        "OCIStmtExecute", oci_error);
    return (-1);
  } /* }}} */

  /* Acquire the number of columns returned. */
  do /* {{{ */
  {
    ub4 param_counter = 0;
    status = OCIAttrGet (oci_statement, OCI_HTYPE_STMT, /* {{{ */
        &param_counter, /* size pointer = */ NULL,
        OCI_ATTR_PARAM_COUNT, oci_error);
    if (status != OCI_SUCCESS)
    {
      o_report_error ("o_read_database_query", db->name,
          udb_query_get_name (q), "OCIAttrGet", oci_error);
      return (-1);
    } /* }}} */

    column_num = (size_t) param_counter;
  } while (0); /* }}} */

  /* Allocate the following buffers:
   *
   *  +---------------+-----------------------------------+
   *  ! Name          ! Size                              !
   *  +---------------+-----------------------------------+
   *  ! column_names  ! column_num x DATA_MAX_NAME_LEN    !
   *  ! column_values ! column_num x DATA_MAX_NAME_LEN    !
   *  ! oci_defines   ! column_num x sizeof (OCIDefine *) !
   *  +---------------+-----------------------------------+
   *
   * {{{ */
#define NUMBER_BUFFER_SIZE 64

#define FREE_ALL \
  if (column_names != NULL) { \
    sfree (column_names[0]); \
    sfree (column_names); \
  } \
  if (column_values != NULL) { \
    sfree (column_values[0]); \
    sfree (column_values); \
  } \
  sfree (oci_defines)

#define ALLOC_OR_FAIL(ptr, ptr_size) \
  do { \
    size_t alloc_size = (size_t) ((ptr_size)); \
    (ptr) = calloc (1, alloc_size); \
    if ((ptr) == NULL) { \
      FREE_ALL; \
      ERROR ("oracle plugin: o_read_database_query: calloc failed."); \
      return (-1); \
    } \
  } while (0)

  /* Initialize everything to NULL so the above works. */
  column_names  = NULL;
  column_values = NULL;
  oci_defines   = NULL;

  ALLOC_OR_FAIL (column_names, column_num * sizeof (char *));
  ALLOC_OR_FAIL (column_names[0], column_num * DATA_MAX_NAME_LEN
      * sizeof (char));
  for (i = 1; i < column_num; i++)
    column_names[i] = column_names[i - 1] + DATA_MAX_NAME_LEN;

  ALLOC_OR_FAIL (column_values, column_num * sizeof (char *));
  ALLOC_OR_FAIL (column_values[0], column_num * DATA_MAX_NAME_LEN
      * sizeof (char));
  for (i = 1; i < column_num; i++)
    column_values[i] = column_values[i - 1] + DATA_MAX_NAME_LEN;

  ALLOC_OR_FAIL (oci_defines, column_num * sizeof (OCIDefine *));
  /* }}} End of buffer allocations. */

  /* ``Define'' the returned data, i. e. bind the columns to the buffers
   * allocated above. */
  for (i = 0; i < column_num; i++) /* {{{ */
  {
    char *column_name;
    ub4 column_name_length;
    OCIParam *oci_param;

    oci_param = NULL;

    status = OCIParamGet (oci_statement, OCI_HTYPE_STMT, oci_error,
        (void *) &oci_param, (ub4) (i + 1));
    if (status != OCI_SUCCESS)
    {
      /* This is probably alright */
      DEBUG ("oracle plugin: o_read_database_query: status = %#x (= %i);",
          status, status);
      o_report_error ("o_read_database_query", db->name,
          udb_query_get_name (q), "OCIParamGet", oci_error);
      status = OCI_SUCCESS;
      break;
    }

    column_name = NULL;
    column_name_length = 0;
    status = OCIAttrGet (oci_param, OCI_DTYPE_PARAM,
        &column_name, &column_name_length, OCI_ATTR_NAME, oci_error);
    if (status != OCI_SUCCESS)
    {
      OCIDescriptorFree (oci_param, OCI_DTYPE_PARAM);
      o_report_error ("o_read_database_query", db->name,
          udb_query_get_name (q), "OCIAttrGet (OCI_ATTR_NAME)", oci_error);
      continue;
    }

    OCIDescriptorFree (oci_param, OCI_DTYPE_PARAM);
    oci_param = NULL;

    /* Copy the name to column_names. Warning: The ``string'' returned by OCI
     * may not be null terminated! */
    memset (column_names[i], 0, DATA_MAX_NAME_LEN);
    if (column_name_length >= DATA_MAX_NAME_LEN)
      column_name_length = DATA_MAX_NAME_LEN - 1;
    memcpy (column_names[i], column_name, column_name_length);
    column_names[i][column_name_length] = 0;

    DEBUG ("oracle plugin: o_read_database_query: column_names[%zu] = %s; "
        "column_name_length = %"PRIu32";",
        i, column_names[i], (uint32_t) column_name_length);

    status = OCIDefineByPos (oci_statement,
        &oci_defines[i], oci_error, (ub4) (i + 1),
        column_values[i], DATA_MAX_NAME_LEN, SQLT_STR,
        NULL, NULL, NULL, OCI_DEFAULT);
    if (status != OCI_SUCCESS)
    {
      o_report_error ("o_read_database_query", db->name,
          udb_query_get_name (q), "OCIDefineByPos", oci_error);
      continue;
    }
  } /* for (j = 1; j <= param_counter; j++) */
  /* }}} End of the ``define'' stuff. */

  status = udb_query_prepare_result (q, prep_area,
      (db->host != NULL) ? db->host : hostname_g,
      /* plugin = */ "oracle", db->name, column_names, column_num,
      /* interval = */ 0);
  if (status != 0)
  {
    ERROR ("oracle plugin: o_read_database_query (%s, %s): "
        "udb_query_prepare_result failed.",
        db->name, udb_query_get_name (q));
    FREE_ALL;
    return (-1);
  }

  /* Fetch and handle all the rows that matched the query. */
  while (42) /* {{{ */
  {
    status = OCIStmtFetch2 (oci_statement, oci_error,
        /* nrows = */ 1, /* orientation = */ OCI_FETCH_NEXT,
        /* fetch offset = */ 0, /* mode = */ OCI_DEFAULT);
    if (status == OCI_NO_DATA)
    {
      status = OCI_SUCCESS;
      break;
    }
    else if ((status != OCI_SUCCESS) && (status != OCI_SUCCESS_WITH_INFO))
    {
      o_report_error ("o_read_database_query", db->name,
          udb_query_get_name (q), "OCIStmtFetch2", oci_error);
      break;
    }

    status = udb_query_handle_result (q, prep_area, column_values);
    if (status != 0)
    {
      WARNING ("oracle plugin: o_read_database_query (%s, %s): "
          "udb_query_handle_result failed.",
          db->name, udb_query_get_name (q));
    }
  } /* }}} while (42) */

  /* DEBUG ("oracle plugin: o_read_database_query: This statement succeeded: %s", q->statement); */
  FREE_ALL;

  return (0);
#undef FREE_ALL
#undef ALLOC_OR_FAIL
} /* }}} int o_read_database_query */
Exemple #2
0
static int c_psql_exec_query (c_psql_database_t *db, udb_query_t *q,
		udb_query_preparation_area_t *prep_area)
{
	PGresult *res;

	c_psql_user_data_t *data;

	const char *host;

	char **column_names;
	char **column_values;
	int    column_num;

	int rows_num;
	int status;
	int row, col;

	/* The user data may hold parameter information, but may be NULL. */
	data = udb_query_get_user_data (q);

	/* Versions up to `3' don't know how to handle parameters. */
	if (3 <= db->proto_version)
		res = c_psql_exec_query_params (db, q, data);
	else if ((NULL == data) || (0 == data->params_num))
		res = c_psql_exec_query_noparams (db, q);
	else {
		log_err ("Connection to database \"%s\" (%s) does not support "
				"parameters (protocol version %d) - "
				"cannot execute query \"%s\".",
				db->database, db->instance, db->proto_version,
				udb_query_get_name (q));
		return -1;
	}

	column_names = NULL;
	column_values = NULL;

#define BAIL_OUT(status) \
	sfree (column_names); \
	sfree (column_values); \
	PQclear (res); \
	return status

	if (PGRES_TUPLES_OK != PQresultStatus (res)) {
		log_err ("Failed to execute SQL query: %s",
				PQerrorMessage (db->conn));
		log_info ("SQL query was: %s",
				udb_query_get_statement (q));
		BAIL_OUT (-1);
	}

	rows_num = PQntuples (res);
	if (1 > rows_num) {
		BAIL_OUT (0);
	}

	column_num = PQnfields (res);
	column_names = (char **) calloc (column_num, sizeof (char *));
	if (NULL == column_names) {
		log_err ("calloc failed.");
		BAIL_OUT (-1);
	}

	column_values = (char **) calloc (column_num, sizeof (char *));
	if (NULL == column_values) {
		log_err ("calloc failed.");
		BAIL_OUT (-1);
	}
	
	for (col = 0; col < column_num; ++col) {
		/* Pointers returned by `PQfname' are freed by `PQclear' via
		 * `BAIL_OUT'. */
		column_names[col] = PQfname (res, col);
		if (NULL == column_names[col]) {
			log_err ("Failed to resolve name of column %i.", col);
			BAIL_OUT (-1);
		}
	}

	if (C_PSQL_IS_UNIX_DOMAIN_SOCKET (db->host)
			|| (0 == strcmp (db->host, "localhost")))
		host = hostname_g;
	else
		host = db->host;

	status = udb_query_prepare_result (q, prep_area, host, "postgresql",
			db->instance, column_names, (size_t) column_num, db->interval);
	if (0 != status) {
		log_err ("udb_query_prepare_result failed with status %i.",
				status);
		BAIL_OUT (-1);
	}

	for (row = 0; row < rows_num; ++row) {
		for (col = 0; col < column_num; ++col) {
			/* Pointers returned by `PQgetvalue' are freed by `PQclear' via
			 * `BAIL_OUT'. */
			column_values[col] = PQgetvalue (res, row, col);
			if (NULL == column_values[col]) {
				log_err ("Failed to get value at (row = %i, col = %i).",
						row, col);
				break;
			}
		}

		/* check for an error */
		if (col < column_num)
			continue;

		status = udb_query_handle_result (q, prep_area, column_values);
		if (status != 0) {
			log_err ("udb_query_handle_result failed with status %i.",
					status);
		}
	} /* for (row = 0; row < rows_num; ++row) */

	udb_query_finish_result (q, prep_area);

	BAIL_OUT (0);
#undef BAIL_OUT
} /* c_psql_exec_query */
Exemple #3
0
static int cdbi_read_database_query (cdbi_database_t *db, /* {{{ */
    udb_query_t *q, udb_query_preparation_area_t *prep_area)
{
  const char *statement;
  dbi_result res;
  size_t column_num;
  char **column_names;
  char **column_values;
  int status;
  size_t i;

  /* Macro that cleans up dynamically allocated memory and returns the
   * specified status. */
#define BAIL_OUT(status) \
  if (column_names != NULL) { sfree (column_names[0]); sfree (column_names); } \
  if (column_values != NULL) { sfree (column_values[0]); sfree (column_values); } \
  if (res != NULL) { dbi_result_free (res); res = NULL; } \
  return (status)

  column_names = NULL;
  column_values = NULL;

  statement = udb_query_get_statement (q);
  assert (statement != NULL);

  res = dbi_conn_query (db->connection, statement);
  if (res == NULL)
  {
    char errbuf[1024];
    ERROR ("dbi plugin: cdbi_read_database_query (%s, %s): "
        "dbi_conn_query failed: %s",
        db->name, udb_query_get_name (q),
        cdbi_strerror (db->connection, errbuf, sizeof (errbuf)));
    BAIL_OUT (-1);
  }
  else /* Get the number of columns */
  {
    unsigned int db_status;

    db_status = dbi_result_get_numfields (res);
    if (db_status == DBI_FIELD_ERROR)
    {
      char errbuf[1024];
      ERROR ("dbi plugin: cdbi_read_database_query (%s, %s): "
          "dbi_result_get_numfields failed: %s",
          db->name, udb_query_get_name (q),
          cdbi_strerror (db->connection, errbuf, sizeof (errbuf)));
      BAIL_OUT (-1);
    }

    column_num = (size_t) db_status;
    DEBUG ("cdbi_read_database_query (%s, %s): There are %zu columns.",
        db->name, udb_query_get_name (q), column_num);
  }

  /* Allocate `column_names' and `column_values'. {{{ */
  column_names = calloc (column_num, sizeof (*column_names));
  if (column_names == NULL)
  {
    ERROR ("dbi plugin: calloc failed.");
    BAIL_OUT (-1);
  }

  column_names[0] = calloc (column_num, DATA_MAX_NAME_LEN);
  if (column_names[0] == NULL)
  {
    ERROR ("dbi plugin: calloc failed.");
    BAIL_OUT (-1);
  }
  for (i = 1; i < column_num; i++)
    column_names[i] = column_names[i - 1] + DATA_MAX_NAME_LEN;

  column_values = calloc (column_num, sizeof (*column_values));
  if (column_values == NULL)
  {
    ERROR ("dbi plugin: calloc failed.");
    BAIL_OUT (-1);
  }

  column_values[0] = calloc (column_num, DATA_MAX_NAME_LEN);
  if (column_values[0] == NULL)
  {
    ERROR ("dbi plugin: calloc failed.");
    BAIL_OUT (-1);
  }
  for (i = 1; i < column_num; i++)
    column_values[i] = column_values[i - 1] + DATA_MAX_NAME_LEN;
  /* }}} */

  /* Copy the field names to `column_names' */
  for (i = 0; i < column_num; i++) /* {{{ */
  {
    const char *column_name;

    column_name = dbi_result_get_field_name (res, (unsigned int) (i + 1));
    if (column_name == NULL)
    {
      ERROR ("dbi plugin: cdbi_read_database_query (%s, %s): "
          "Cannot retrieve name of field %zu.",
          db->name, udb_query_get_name (q), i + 1);
      BAIL_OUT (-1);
    }

    sstrncpy (column_names[i], column_name, DATA_MAX_NAME_LEN);
  } /* }}} for (i = 0; i < column_num; i++) */

  udb_query_prepare_result (q, prep_area, (db->host ? db->host : hostname_g),
      /* plugin = */ "dbi", db->name,
      column_names, column_num, /* interval = */ (db->interval > 0) ? db->interval : 0);

  /* 0 = error; 1 = success; */
  status = dbi_result_first_row (res); /* {{{ */
  if (status != 1)
  {
    char errbuf[1024];
    ERROR ("dbi plugin: cdbi_read_database_query (%s, %s): "
        "dbi_result_first_row failed: %s. Maybe the statement didn't "
        "return any rows?",
        db->name, udb_query_get_name (q),
        cdbi_strerror (db->connection, errbuf, sizeof (errbuf)));
    udb_query_finish_result (q, prep_area);
    BAIL_OUT (-1);
  } /* }}} */

  /* Iterate over all rows and call `udb_query_handle_result' with each list of
   * values. */
  while (42) /* {{{ */
  {
    status = 0;
    /* Copy the value of the columns to `column_values' */
    for (i = 0; i < column_num; i++) /* {{{ */
    {
      status = cdbi_result_get_field (res, (unsigned int) (i + 1),
          column_values[i], DATA_MAX_NAME_LEN);

      if (status != 0)
      {
        ERROR ("dbi plugin: cdbi_read_database_query (%s, %s): "
            "cdbi_result_get_field (%zu) failed.",
            db->name, udb_query_get_name (q), i + 1);
        status = -1;
        break;
      }
    } /* }}} for (i = 0; i < column_num; i++) */

    /* If all values were copied successfully, call `udb_query_handle_result'
     * to dispatch the row to the daemon. */
    if (status == 0) /* {{{ */
    {
      status = udb_query_handle_result (q, prep_area, column_values);
      if (status != 0)
      {
        ERROR ("dbi plugin: cdbi_read_database_query (%s, %s): "
            "udb_query_handle_result failed.",
            db->name, udb_query_get_name (q));
      }
    } /* }}} */

    /* Get the next row from the database. */
    status = dbi_result_next_row (res); /* {{{ */
    if (status != 1)
    {
      if (dbi_conn_error (db->connection, NULL) != 0)
      {
        char errbuf[1024];
        WARNING ("dbi plugin: cdbi_read_database_query (%s, %s): "
            "dbi_result_next_row failed: %s.",
            db->name, udb_query_get_name (q),
            cdbi_strerror (db->connection, errbuf, sizeof (errbuf)));
      }
      break;
    } /* }}} */
  } /* }}} while (42) */

  /* Tell the db query interface that we're done with this query. */
  udb_query_finish_result (q, prep_area);

  /* Clean up and return `status = 0' (success) */
  BAIL_OUT (0);
#undef BAIL_OUT
} /* }}} int cdbi_read_database_query */