static isc_result_t
mysql_get_resultset(const char *zone, const char *record,
		    const char *client, unsigned int query,
		    void *dbdata, MYSQL_RES **rs)
{
	isc_result_t result;
	dbinstance_t *dbi = NULL;
	char *querystring = NULL;
	unsigned int i = 0;
	unsigned int j = 0;
	int qres = 0;

	if (query != COUNTZONE)
		REQUIRE(*rs == NULL);
	else
		REQUIRE(rs == NULL);

	/* get db instance / connection */
	dbi =  (dbinstance_t *) dbdata;

	/* if DBI is null, can't do anything else */
	if (dbi == NULL) {
		result = ISC_R_FAILURE;
		goto cleanup;
	}

	/* what type of query are we going to run? */
	switch(query) {
	case ALLNODES:
		/*
		 * if the query was not passed in from the config file
		 * then we can't run it.  return not_implemented, so
		 * it's like the code for that operation was never
		 * built into the driver.... AHHH flexibility!!!
		 */
		if (dbi->allnodes_q == NULL) {
			result = ISC_R_NOTIMPLEMENTED;
			goto cleanup;
		}
		break;
	case ALLOWXFR:
		/* same as comments as ALLNODES */
		if (dbi->allowxfr_q == NULL) {
			result = ISC_R_NOTIMPLEMENTED;
			goto cleanup;
		}
		break;
	case AUTHORITY:
		/* same as comments as ALLNODES */
		if (dbi->authority_q == NULL) {
			result = ISC_R_NOTIMPLEMENTED;
			goto cleanup;
		}
		break;
	case FINDZONE:
		/* this is required.  It's the whole point of DLZ! */
		if (dbi->findzone_q == NULL) {
			isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
				      DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
				      "No query specified for findzone.  "
				      "Findzone requires a query");
			result = ISC_R_FAILURE;
			goto cleanup;
		}
		break;
	case COUNTZONE:
		/* same as comments as ALLNODES */
		if (dbi->countzone_q == NULL) {
			result = ISC_R_NOTIMPLEMENTED;
			goto cleanup;
		}
		break;
	case LOOKUP:
		/* this is required.  It's also a major point of DLZ! */
		if (dbi->lookup_q == NULL) {
			isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
				      DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
				      "No query specified for lookup.  "
				      "Lookup requires a query");
			result = ISC_R_FAILURE;
			goto cleanup;
		}
		break;
	default:
		/*
		 * this should never happen.  If it does, the code is
		 * screwed up!
		 */
		UNEXPECTED_ERROR(__FILE__, __LINE__,
				 "Incorrect query flag passed to "
				 "mysql_get_resultset");
		result = ISC_R_UNEXPECTED;
		goto cleanup;
	}


	/*
	 * was a zone string passed?  If so, make it safe for use in
	 * queries.
	 */
	if (zone != NULL) {
		dbi->zone = mysqldrv_escape_string((MYSQL *) dbi->dbconn,
						   zone);
		if (dbi->zone == NULL) {
			result = ISC_R_NOMEMORY;
			goto cleanup;
		}
	} else {	/* no string passed, set the string pointer to NULL */
		dbi->zone = NULL;
	}

	/*
	 * was a record string passed?  If so, make it safe for use in
	 * queries.
	 */
	if (record != NULL) {
		dbi->record = mysqldrv_escape_string((MYSQL *) dbi->dbconn,
						     record);
		if (dbi->record == NULL) {
			result = ISC_R_NOMEMORY;
			goto cleanup;
		}
	} else {	/* no string passed, set the string pointer to NULL */
		dbi->record = NULL;
	}

	/*
	 * was a client string passed?  If so, make it safe for use in
	 * queries.
	 */
	if (client != NULL) {
		dbi->client = mysqldrv_escape_string((MYSQL *) dbi->dbconn,
						     client);
		if (dbi->client == NULL) {
			result = ISC_R_NOMEMORY;
			goto cleanup;
		}
	} else {	/* no string passed, set the string pointer to NULL */
		dbi->client = NULL;
	}

	/*
	 * what type of query are we going to run?  this time we build
	 * the actual query to run.
	 */
	switch(query) {
	case ALLNODES:
		querystring = build_querystring(ns_g_mctx, dbi->allnodes_q);
		break;
	case ALLOWXFR:
		querystring = build_querystring(ns_g_mctx, dbi->allowxfr_q);
		break;
	case AUTHORITY:
		querystring = build_querystring(ns_g_mctx, dbi->authority_q);
		break;
	case FINDZONE:
		querystring = build_querystring(ns_g_mctx, dbi->findzone_q);
		break;
	case COUNTZONE:
		querystring = build_querystring(ns_g_mctx, dbi->countzone_q);
		break;
	case LOOKUP:
		querystring = build_querystring(ns_g_mctx, dbi->lookup_q);
		break;
	default:
		/*
		 * this should never happen.  If it does, the code is
		 * screwed up!
		 */
		UNEXPECTED_ERROR(__FILE__, __LINE__,
				 "Incorrect query flag passed to "
				 "mysql_get_resultset");
		result = ISC_R_UNEXPECTED;
		goto cleanup;
	}

	/* if the querystring is null, Bummer, outta RAM.  UPGRADE TIME!!!   */
	if (querystring == NULL) {
		result = ISC_R_NOMEMORY;
		goto cleanup;
	}

	/*
	 * output the full query string during debug so we can see
	 * what lame error the query has.
	 */
	isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
		      DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(1),
		      "\nQuery String: %s\n", querystring);

	/* attempt query up to 3 times. */
	for (i=0; i < 3; i++) {
		qres = mysql_query((MYSQL *) dbi->dbconn, querystring);
		if (qres == 0)
			break;
		for (j=0; mysql_ping((MYSQL *) dbi->dbconn) != 0 && j < 4; j++)
			;
	}

	if (qres == 0) {
		result = ISC_R_SUCCESS;
		if (query != COUNTZONE) {
			*rs = mysql_store_result((MYSQL *) dbi->dbconn);
			if (*rs == NULL)
				result = ISC_R_FAILURE;
		}
	} else {
		result = ISC_R_FAILURE;
	}


 cleanup:
	/* it's always good to cleanup after yourself */

	/* if we couldn't even get DBI, just return NULL */
	if (dbi == NULL)
		return ISC_R_FAILURE;

	/* free dbi->zone string */
	if (dbi->zone != NULL)
		isc_mem_free(ns_g_mctx, dbi->zone);

	/* free dbi->record string */
	if (dbi->record != NULL)
		isc_mem_free(ns_g_mctx, dbi->record);

	/* free dbi->client string */
	if (dbi->client != NULL)
		isc_mem_free(ns_g_mctx, dbi->client);

	/* release query string */
	if (querystring  != NULL)
		isc_mem_free(ns_g_mctx, querystring);

	/* return result */
	return result;
}
/*%
 * This function is the real core of the module.   Zone, record
 * and client strings are passed in (or NULL is passed if the
 * string is not available).  The type of query we want to run
 * is indicated by the query flag, and the dbdata object is passed
 * passed in to.  dbdata really holds a single database instance.
 * The function will construct and run the query, hopefully getting
 * a result set.
 */
static isc_result_t
mysql_get_resultset(const char *zone, const char *record,
		    const char *client, unsigned int query,
		    void *dbdata, MYSQL_RES **rs)
{
	isc_result_t result;
	dbinstance_t *dbi = NULL;
	mysql_instance_t *db = (mysql_instance_t *)dbdata;
	char *querystring = NULL;
	unsigned int i = 0;
	unsigned int j = 0;
	int qres = 0;

#if PTHREADS
	/* find an available DBI from the list */
	dbi = mysql_find_avail_conn(db);
#else /* PTHREADS */
	/*
	 * only 1 DBI - no need to lock instance lock either
	 * only 1 thread in the whole process, no possible contention.
	 */
	dbi = (dbinstance_t *)(db->db);
#endif /* PTHREADS */

	if (dbi == NULL) {
		result = ISC_R_FAILURE;
		goto cleanup;
	}

	/* what type of query are we going to run? */
	switch(query) {
	case ALLNODES:
		if (dbi->allnodes_q == NULL) {
			result = ISC_R_NOTIMPLEMENTED;
			goto cleanup;
		}
		break;
	case ALLOWXFR:
		if (dbi->allowxfr_q == NULL) {
			result = ISC_R_NOTIMPLEMENTED;
			goto cleanup;
		}
		break;
	case AUTHORITY:
		if (dbi->authority_q == NULL) {
			result = ISC_R_NOTIMPLEMENTED;
			goto cleanup;
		}
		break;
	case FINDZONE:
		if (dbi->findzone_q == NULL) {
			db->log(ISC_LOG_DEBUG(2),
				"No query specified for findzone.  "
				"Findzone requires a query");
			result = ISC_R_FAILURE;
			goto cleanup;
		}
		break;
	case COUNTZONE:
		if (dbi->countzone_q == NULL) {
			result = ISC_R_NOTIMPLEMENTED;
			goto cleanup;
		}
		break;
	case LOOKUP:
		if (dbi->lookup_q == NULL) {
			db->log(ISC_LOG_DEBUG(2),
				"No query specified for lookup.  "
				"Lookup requires a query");
			result = ISC_R_FAILURE;
			goto cleanup;
		}
		break;
	default:
		db->log(ISC_LOG_ERROR,
			"Incorrect query flag passed to "
			"mysql_get_resultset");
		result = ISC_R_UNEXPECTED;
		goto cleanup;
	}


	if (zone != NULL) {
		if (dbi->zone != NULL)
			free(dbi->zone);

		dbi->zone = mysqldrv_escape_string((MYSQL *) dbi->dbconn,
						   zone);
		if (dbi->zone == NULL) {
			result = ISC_R_NOMEMORY;
			goto cleanup;
		}
	} else
		dbi->zone = NULL;

	if (record != NULL) {
		if (dbi->record != NULL)
			free(dbi->record);

		dbi->record = mysqldrv_escape_string((MYSQL *) dbi->dbconn,
						     record);
		if (dbi->record == NULL) {
			result = ISC_R_NOMEMORY;
			goto cleanup;
		}
	} else
		dbi->record = NULL;

	if (client != NULL) {
		if (dbi->client != NULL)
			free(dbi->client);

		dbi->client = mysqldrv_escape_string((MYSQL *) dbi->dbconn,
						     client);
		if (dbi->client == NULL) {
			result = ISC_R_NOMEMORY;
			goto cleanup;
		}
	} else
		dbi->client = NULL;

	/*
	 * what type of query are we going to run?  this time we build
	 * the actual query to run.
	 */
	switch(query) {
	case ALLNODES:
		querystring = build_querystring(dbi->allnodes_q);
		break;
	case ALLOWXFR:
		querystring = build_querystring(dbi->allowxfr_q);
		break;
	case AUTHORITY:
		querystring = build_querystring(dbi->authority_q);
		break;
	case FINDZONE:
		querystring = build_querystring(dbi->findzone_q);
		break;
	case COUNTZONE:
		querystring = build_querystring(dbi->countzone_q);
		break;
	case LOOKUP:
		querystring = build_querystring(dbi->lookup_q);
		break;
	default:
		db->log(ISC_LOG_ERROR,
			"Incorrect query flag passed to "
			"mysql_get_resultset");
		result = ISC_R_UNEXPECTED; goto cleanup;
	}

	if (querystring == NULL) {
		result = ISC_R_NOMEMORY;
		goto cleanup;
	}

	/* output the full query string when debugging */
	db->log(ISC_LOG_DEBUG(1), "\nQuery String: %s\n", querystring);

	/* attempt query up to 3 times. */
	for (i = 0; i < 3; i++) {
		qres = mysql_query((MYSQL *) dbi->dbconn, querystring);
		if (qres == 0)
			break;
		for (j = 0; j < 4; j++)
		     if (mysql_ping((MYSQL *) dbi->dbconn) == 0)
			     break;
	}

	if (qres == 0) {
		result = ISC_R_SUCCESS;
		if (query != COUNTZONE) {
			*rs = mysql_store_result((MYSQL *) dbi->dbconn);
			if (*rs == NULL)
				result = ISC_R_FAILURE;
		}
	} else
		result = ISC_R_FAILURE;

 cleanup:
	if (dbi == NULL)
		return (ISC_R_FAILURE);

	if (dbi->zone != NULL) {
		free(dbi->zone);
		dbi->zone = NULL;
	}
	if (dbi->record != NULL) {
		free(dbi->record);
		dbi->record = NULL;
	}
	if (dbi->client != NULL) {
		free(dbi->client);
		dbi->client = NULL;
	}

	/* release the lock so another thread can use this dbi */
	(void) dlz_mutex_unlock(&dbi->lock);

	if (querystring != NULL)
		free(querystring);

	return (result);
}