Exemple #1
0
SWITCH_DECLARE(switch_odbc_status_t) switch_odbc_handle_exec(switch_odbc_handle_t *handle, const char *sql, switch_odbc_statement_handle_t *rstmt,
															 char **err)
{
#ifdef SWITCH_HAVE_ODBC
	SQLHSTMT stmt = NULL;
	int result;
	char *err_str = NULL;

	if (!db_is_up(handle)) {
		goto error;
	}

	if (SQLAllocHandle(SQL_HANDLE_STMT, handle->con, &stmt) != SQL_SUCCESS) {
		goto error;
	}

	if (SQLPrepare(stmt, (unsigned char *) sql, SQL_NTS) != SQL_SUCCESS) {
		goto error;
	}

	result = SQLExecute(stmt);

	if (result != SQL_SUCCESS && result != SQL_SUCCESS_WITH_INFO && result != SQL_NO_DATA) {
		goto error;
	}

	if (rstmt) {
		*rstmt = stmt;
	} else {
		SQLFreeHandle(SQL_HANDLE_STMT, stmt);
	}

	return SWITCH_ODBC_SUCCESS;

  error:

	if (stmt) {
		err_str = switch_odbc_handle_get_error(handle, stmt);
	}

	if (err_str) {
		if (!switch_stristr("already exists", err_str) && !switch_stristr("duplicate key name", err_str)) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ERR: [%s]\n[%s]\n", sql, switch_str_nil(err_str));
		}
		if (err) {
			*err = err_str;
		} else {
			free(err_str);
		}
	}

	if (rstmt) {
		*rstmt = stmt;
	} else if (stmt) {
		SQLFreeHandle(SQL_HANDLE_STMT, stmt);
	}
#endif
	return SWITCH_ODBC_FAIL;
}
Exemple #2
0
SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_handle_exec_base(switch_pgsql_handle_t *handle, const char *sql, char **err)
{
#ifdef SWITCH_HAVE_PGSQL
	char *err_str = NULL;

	handle->affected_rows = 0;

	if (!db_is_up(handle)) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Database is not up!\n");
		goto error;
	}

	if (handle->auto_commit == SWITCH_FALSE && handle->in_txn == SWITCH_FALSE) {
		if (switch_pgsql_send_query(handle, "BEGIN") != SWITCH_PGSQL_SUCCESS) {
			switch_pgsql_finish_results(handle);
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error sending BEGIN!\n");
			goto error;
		}

		if (switch_pgsql_finish_results(handle) != SWITCH_PGSQL_SUCCESS) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error sending BEGIN!\n");
			goto error;
		}
		handle->in_txn = SWITCH_TRUE;
	}

	if (switch_pgsql_send_query(handle, sql) != SWITCH_PGSQL_SUCCESS) {
		switch_pgsql_finish_results(handle);
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error sending query!\n");
		goto error;
	}

	return SWITCH_PGSQL_SUCCESS;

  error:
	err_str = switch_pgsql_handle_get_error(handle);

	if (zstr(err_str)) {
		err_str = strdup((char *)"SQL ERROR!");
	}
	
	if (err_str) {
		if (!switch_stristr("already exists", err_str) && !switch_stristr("duplicate key name", err_str)) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ERR: [%s]\n[%s]\n", sql, switch_str_nil(err_str));
		}
		if (err) {
			*err = err_str;
		} else {
			free(err_str);
		}
	}
#endif
	return SWITCH_PGSQL_FAIL;
}
Exemple #3
0
SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_next_result_timed(switch_pgsql_handle_t *handle, switch_pgsql_result_t **result_out, int msec)
{
#ifdef SWITCH_HAVE_PGSQL
    switch_pgsql_result_t *res;
    switch_time_t start;
    switch_time_t ctime;
    unsigned int usec = msec * 1000;
    char *err_str;
    struct pollfd fds[2] = { {0} };
    int poll_res = 0;

    if(!handle) {
        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "**BUG** Null handle passed to switch_pgsql_next_result.\n");
        return SWITCH_PGSQL_FAIL;
    }

    /* Try to consume input that might be waiting right away */
    if (PQconsumeInput(handle->con)) {
        /* And check to see if we have a full result ready for reading */
        if (PQisBusy(handle->con)) {

            /* Wait for a result to become available, up to msec milliseconds */
            start = switch_micro_time_now();
            while((ctime = switch_micro_time_now()) - start <= usec) {
                int wait_time = (usec - (ctime - start)) / 1000;
                fds[0].fd = handle->sock;
                fds[0].events |= POLLIN;
                fds[0].events |= POLLERR;
                fds[0].events |= POLLNVAL;
                fds[0].events |= POLLHUP;
                fds[0].events |= POLLPRI;
                fds[0].events |= POLLRDNORM;
                fds[0].events |= POLLRDBAND;

                /* Wait for the PostgreSQL socket to be ready for data reads. */
                if ((poll_res = poll(&fds[0], 1, wait_time)) > 0 ) {
                    if (fds[0].revents & POLLHUP || fds[0].revents & POLLNVAL) {
                        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "PGSQL socket closed or invalid while waiting for result for query (%s)\n", handle->sql);
                        goto error;
                    } else if (fds[0].revents & POLLERR) {
                        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Poll error trying to read PGSQL socket for query (%s)\n", handle->sql);
                        goto error;
                    } else if (fds[0].revents & POLLIN || fds[0].revents & POLLPRI || fds[0].revents & POLLRDNORM || fds[0].revents & POLLRDBAND) {
                        /* Then try to consume any input waiting. */
                        if (PQconsumeInput(handle->con)) {
                            if (PQstatus(handle->con) == CONNECTION_BAD) {
                                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Connection terminated while waiting for result.\n");
                                handle->state = SWITCH_PGSQL_STATE_ERROR;
                                goto error;
                            }

                            /* And check to see if we have a full result ready for reading */
                            if (!PQisBusy(handle->con)) {
                                /* If we can pull a full result without blocking, then break this loop */
                                break;
                            }
                        } else {
                            /* If we had an error trying to consume input, report it and cancel the query. */
                            err_str = switch_pgsql_handle_get_error(handle);
                            switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "An error occurred trying to consume input for query (%s): %s\n", handle->sql, err_str);
                            switch_safe_free(err_str);
                            switch_pgsql_cancel(handle);
                            goto error;
                        }
                    }
                } else if (poll_res == -1) {
                    switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Poll failed trying to read PGSQL socket for query (%s)\n", handle->sql);
                    goto error;
                }
            }

            /* If we broke the loop above because of a timeout, report that and cancel the query. */
            if (ctime - start > usec) {
                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Query (%s) took too long to complete or database not responding.\n", handle->sql);
                switch_pgsql_cancel(handle);
                goto error;
            }

        }
    } else {
        /* If we had an error trying to consume input, report it and cancel the query. */
        err_str = switch_pgsql_handle_get_error(handle);
        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "An error occurred trying to consume input for query (%s): %s\n", handle->sql, err_str);
        switch_safe_free(err_str);
        /* switch_pgsql_cancel(handle); */
        goto error;
    }


    /* At this point, we know we can read a full result without blocking. */
    if(!(res = malloc(sizeof(switch_pgsql_result_t)))) {
        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Malloc failed!\n");
        goto error;
    }
    memset(res, 0, sizeof(switch_pgsql_result_t));


    res->result = PQgetResult(handle->con);
    if (res->result) {
        *result_out = res;
        res->status = PQresultStatus(res->result);
        switch(res->status) {
#if POSTGRESQL_MAJOR_VERSION >= 9 && POSTGRESQL_MINOR_VERSION >= 2
        case PGRES_SINGLE_TUPLE:
            /* Added in PostgreSQL 9.2 */
#endif
        case PGRES_TUPLES_OK:
        {
            res->rows = PQntuples(res->result);
            handle->affected_rows = res->rows;
            res->cols = PQnfields(res->result);
        }
        break;
#if POSTGRESQL_MAJOR_VERSION >= 9 && POSTGRESQL_MINOR_VERSION >= 1
        case PGRES_COPY_BOTH:
            /* Added in PostgreSQL 9.1 */
#endif
        case PGRES_COPY_OUT:
        case PGRES_COPY_IN:
        case PGRES_COMMAND_OK:
            break;
        case PGRES_EMPTY_QUERY:
            switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Query (%s) returned PGRES_EMPTY_QUERY\n", handle->sql);
        case PGRES_BAD_RESPONSE:
            switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Query (%s) returned PGRES_BAD_RESPONSE\n", handle->sql);
        case PGRES_NONFATAL_ERROR:
            switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Query (%s) returned PGRES_NONFATAL_ERROR\n", handle->sql);
        case PGRES_FATAL_ERROR:
            switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Query (%s) returned PGRES_FATAL_ERROR\n", handle->sql);
            res->err = PQresultErrorMessage(res->result);
            goto error;
            break;
        }
    } else {
        free(res);
        res = NULL;
        *result_out = NULL;
    }

    return SWITCH_PGSQL_SUCCESS;
error:

    /* Make sure the failed connection does not have any transactions marked as in progress */
    switch_pgsql_flush(handle);

    /* Try to reconnect to the DB if we were dropped */
    db_is_up(handle);

#endif
    return SWITCH_PGSQL_FAIL;
}
Exemple #4
0
SWITCH_DECLARE(switch_odbc_status_t) switch_odbc_handle_callback_exec_detailed(const char *file, const char *func, int line,
																			   switch_odbc_handle_t *handle,
																			   const char *sql, switch_core_db_callback_func_t callback, void *pdata,
																			   char **err)
{
#ifdef SWITCH_HAVE_ODBC
	SQLHSTMT stmt = NULL;
	SQLSMALLINT c = 0, x = 0;
	SQLLEN m = 0;
	char *x_err = NULL, *err_str = NULL;
	int result;
	int err_cnt = 0;
	int done = 0;

	handle->affected_rows = 0;

	switch_assert(callback != NULL);

	if (!db_is_up(handle)) {
		x_err = "DB is not up!";
		goto error;
	}

	if (SQLAllocHandle(SQL_HANDLE_STMT, handle->con, &stmt) != SQL_SUCCESS) {
		x_err = "Unable to SQL allocate handle!";
		goto error;
	}

	if (SQLPrepare(stmt, (unsigned char *) sql, SQL_NTS) != SQL_SUCCESS) {
		x_err = "Unable to prepare SQL statement!";
		goto error;
	}

	result = SQLExecute(stmt);

	if (result != SQL_SUCCESS && result != SQL_SUCCESS_WITH_INFO && result != SQL_NO_DATA) {
		x_err = "execute error!";
		goto error;
	}

	SQLNumResultCols(stmt, &c);
	SQLRowCount(stmt, &m);
	handle->affected_rows = (int) m;


	while (!done) {
		int name_len = 256;
		char **names;
		char **vals;
		int y = 0;

		result = SQLFetch(stmt);

		if (result != SQL_SUCCESS) {
			if (result != SQL_NO_DATA) {
				err_cnt++;
			}
			break;
		}

		names = calloc(c, sizeof(*names));
		vals = calloc(c, sizeof(*vals));

		switch_assert(names && vals);

		for (x = 1; x <= c; x++) {
			SQLSMALLINT NameLength = 0, DataType = 0, DecimalDigits = 0, Nullable = 0;
			SQLULEN ColumnSize = 0;
			names[y] = malloc(name_len);
			memset(names[y], 0, name_len);

			SQLDescribeCol(stmt, x, (SQLCHAR *) names[y], (SQLSMALLINT) name_len, &NameLength, &DataType, &ColumnSize, &DecimalDigits, &Nullable);

			if (!ColumnSize) {
				ColumnSize = 255;
			}
			ColumnSize++;

			vals[y] = malloc(ColumnSize);
			memset(vals[y], 0, ColumnSize);
			SQLGetData(stmt, x, SQL_C_CHAR, (SQLCHAR *) vals[y], ColumnSize, NULL);
			y++;
		}

		if (callback(pdata, y, vals, names)) {
			done = 1;
		}

		for (x = 0; x < y; x++) {
			free(names[x]);
			free(vals[x]);
		}
		free(names);
		free(vals);
	}

	SQLFreeHandle(SQL_HANDLE_STMT, stmt);
	stmt = NULL; /* Make sure we don't try to free this handle again */
	
	if (!err_cnt) {
		return SWITCH_ODBC_SUCCESS;
	}

  error:

	if (stmt) {
		err_str = switch_odbc_handle_get_error(handle, stmt);
	}

	if (zstr(err_str) && !zstr(x_err)) {
		err_str = strdup(x_err);
	}

	if (err_str) {
		switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, NULL, SWITCH_LOG_ERROR, "ERR: [%s]\n[%s]\n", sql, switch_str_nil(err_str));
		if (err) {
			*err = err_str;
		} else {
			free(err_str);
		}
	}

	if (stmt) {
		SQLFreeHandle(SQL_HANDLE_STMT, stmt);
	}


#endif
	return SWITCH_ODBC_FAIL;
}
Exemple #5
0
SWITCH_DECLARE(switch_odbc_status_t) switch_odbc_handle_exec(switch_odbc_handle_t *handle, const char *sql, switch_odbc_statement_handle_t *rstmt,
															 char **err)
{
#ifdef SWITCH_HAVE_ODBC
	SQLHSTMT stmt = NULL;
	int result;
	char *err_str = NULL, *err2 = NULL;
	SQLLEN m = 0;

	handle->affected_rows = 0;

	if (!db_is_up(handle)) {
		goto error;
	}

	if (SQLAllocHandle(SQL_HANDLE_STMT, handle->con, &stmt) != SQL_SUCCESS) {
		err2 = "SQLAllocHandle failed.";
		goto error;
	}

	if (SQLPrepare(stmt, (unsigned char *) sql, SQL_NTS) != SQL_SUCCESS) {
		err2 = "SQLPrepare failed.";
		goto error;
	}

	result = SQLExecute(stmt);

	switch (result) {
	case SQL_SUCCESS:
	case SQL_SUCCESS_WITH_INFO:
	case SQL_NO_DATA:
		break;
	case SQL_ERROR:
		err2 = "SQLExecute returned SQL_ERROR.";
		goto error;
		break;
	case SQL_NEED_DATA:
		err2 = "SQLExecute returned SQL_NEED_DATA.";
		goto error;
		break;
	default:
		err2 = "SQLExecute returned unknown result code.";
		goto error;
	}

	SQLRowCount(stmt, &m);
	handle->affected_rows = (int) m;

	if (rstmt) {
		*rstmt = stmt;
	} else {
		SQLFreeHandle(SQL_HANDLE_STMT, stmt);
	}

	return SWITCH_ODBC_SUCCESS;

  error:


	if (stmt) {
		err_str = switch_odbc_handle_get_error(handle, stmt);
	}

	if (zstr(err_str)) {
		if (err2) {
			err_str = strdup(err2);
		} else {
			err_str = strdup((char *)"SQL ERROR!");
		}
	}
	
	if (err_str) {
		if (!switch_stristr("already exists", err_str) && !switch_stristr("duplicate key name", err_str)) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ERR: [%s]\n[%s]\n", sql, switch_str_nil(err_str));
		}
		if (err) {
			*err = err_str;
		} else {
			free(err_str);
		}
	}

	if (rstmt) {
		*rstmt = stmt;
	} else if (stmt) {
		SQLFreeHandle(SQL_HANDLE_STMT, stmt);
	}
#endif
	return SWITCH_ODBC_FAIL;
}