text: /*-------------------------------------------------------------------------
   *
   * cdb_table.c
   *
   * Structures and functions to read cdb tables using libpq.
   *
   * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
   * Portions Copyright (c) 1994, Regents of the University of California
   *
   *-------------------------------------------------------------------------
   */
  
  #include "postgres_fe.h"
  #include "pqexpbuffer.h"
  #include "libpq-fe.h"
  #include "cdb_dump_util.h"
  #include "cdb_table.h"
  
  /*-------------------------------------------------------------------------
   *
   * FreeCDBAssignmentArray( CDBAssignmentArray* pAssignmentAr ) returns void
   *
   * This frees the pointers allocated in each of the CDBAssignment structs
   * that are part of the pAssignmentAr->pData array, and then frees the pData
   * pointer itself.	It does NOT free the pAssignmentAr.
   *-------------------------------------------------------------------------
   */
  /*
  void FreeCDBAssignmentArray( CDBAssignmentArray* pAssignmentAr )
  {
  	if ( pAssignmentAr == NULL )
  		return;
  
  	int i;
  	for ( i=0; i<pAssignmentAr->count; i++ )
  	{
  		CDBAssignment* pAssignment = &pAssignmentAr->pData[i];
  
  		if ( pAssignment->pszTableName != NULL )
  			free( pAssignment->pszTableName );
  		if ( pAssignment->pszNspName != NULL )
  			free( pAssignment->pszNspName );
  	}
  
  	if ( pAssignmentAr->pData != NULL )
  	{
  		free( pAssignmentAr->pData );
  		pAssignmentAr->pData = NULL;
  	}
  
  	pAssignmentAr->count = 0;
  }
  */
  
  /*-------------------------------------------------------------------------
   *
   * FreeCDBBaseTableArray( CDBBaseTableArray* pTableAr ) returns void
   *
   * This frees the pointers allocated in each of the CBBBaseTable structs
   * that are part of the pTableAr->pData array, and then frees the pData
   * pointer itself.	It does NOT free the pTableAr.
   *-------------------------------------------------------------------------
   */
  
  void
  FreeCDBBaseTableArray(CDBBaseTableArray *pTableAr)
  {
  	int			i;
  
  	if (pTableAr == NULL)
  		return;
  
  	for (i = 0; i < pTableAr->count; i++)
  	{
  		CDBBaseTable *pBaseTable = &pTableAr->pData[i];
  
  		if (pBaseTable->pszTableName != NULL)
  			free(pBaseTable->pszTableName);
  		if (pBaseTable->pszNspName != NULL)
  			free(pBaseTable->pszNspName);
  	}
  
  	if (pTableAr->pData != NULL)
  		free(pTableAr->pData);
  
  	pTableAr->count = 0;
  	pTableAr->pData = NULL;
  }
  
  /*-------------------------------------------------------------------------
   *
   * FreeCDBInstanceArray( CDBInstanceArray* pInstanceAr ) returns void
   *
   * This frees the pointers allocated in each of the CBBInstance structs
   * that are part of the pInstanceAr->pData array, and then frees the pData
   * pointer itself.	It does NOT free the pInstanceAr.
   *-------------------------------------------------------------------------
   */
  /*
  void FreeCDBInstanceArray( CDBInstanceArray* pInstanceAr )
  {
  	if ( pInstanceAr == NULL )
  		return;
  
  	int i;
  	for ( i=0; i<pInstanceAr->count; i++ )
  	{
  		CDBInstance* pInstance = &pInstanceAr->pData[i];
  
  		if ( pInstance->pszHost != NULL )
  			free( pInstance->pszHost );
  		if ( pInstance->pszDataDir != NULL )
  			free( pInstance->pszDataDir );
  	}
  
  	if ( pInstanceAr->pData != NULL )
  	{
  		free( pInstanceAr->pData );
  		pInstanceAr->pData = NULL;
  	}
  
  	pInstanceAr->count = 0;
  }
  */
  
  /*-------------------------------------------------------------------------
   *
   * FreeCDBPolicyArray( CDBPolicyArray* pPolicyAr ) returns void
   *
   * This frees the pointers allocated in each of the CDBPolicy structs
   * that are part of the pPolicyAr->pData array, and then frees the pData
   * pointer itself.	It does NOT free the pPolicyAr.
   *-------------------------------------------------------------------------
   */
  /*
  void FreeCDBPolicyArray( CDBPolicyArray* pPolicyAr )
  {
  	if ( pPolicyAr == NULL )
  		return;
  
  	int i;
  	for ( i=0; i<pPolicyAr->count; i++ )
  	{
  		CDBPolicy* pPolicy = &pPolicyAr->pData[i];
  
  		if ( pPolicy->pszTableName != NULL )
  			free( pPolicy->pszTableName );
  		if ( pPolicy->pszNspName != NULL )
  			free( pPolicy->pszNspName );
  		if ( pPolicy->pszParameters != NULL )
  			free( pPolicy->pszParameters );
  	}
  
  	if ( pPolicyAr->pData != NULL )
  	{
  		free( pPolicyAr->pData );
  		pPolicyAr->pData = NULL;
  	}
  
  	pPolicyAr->count = 0;
  }
  */
  
  /*-------------------------------------------------------------------------
   *
   * FreeCDBSegArray( CDBSegArray* pSegAr ) returns void
   *
   * This frees the pointers allocated in each of the CDVSeg structs
   * that are part of the pSegAr->pData array, and then frees the pData
   * pointer itself.	It does NOT free the pSegAr.
   *-------------------------------------------------------------------------
   */
  /*
  void FreeCDBSegArray( CDBSegArray* pSegAr )
  {
  	if ( pSegAr == NULL )
  		return;
  
  	int i;
  	for ( i=0; i<pSegAr->count; i++ )
  	{
  		CDBSeg* pSeg = &pSegAr->pData[i];
  
  		if ( pSeg->pszDBName != NULL )
  			free( pSeg->pszDBName );
  		if ( pSeg->pszDBUser != NULL )
  			free( pSeg->pszDBUser );
  		if ( pSeg->pszDBPswd != NULL )
  			free( pSeg->pszDBPswd );
  	}
  
  	if ( pSegAr->pData != NULL )
  	{
  		free( pSegAr->pData );
  		pSegAr->pData = NULL;
  	}
  
  	pSegAr->count = 0;
  }
  */
  
  /*-------------------------------------------------------------------------
   *
   * FreeCDBSegmentInstanceArray( CDBSegmentInstanceArray* pSegmentInstanceAr ) returns void
   *
   * This frees the pointers allocated in each of the CDBSegmentInstance structs
   * that are part of the pSegmentInstanceAr->pData array, and then frees the pData
   * pointer itself.	It does NOT free the pSegmentInstanceAr.
   *-------------------------------------------------------------------------
   */
  void
  FreeCDBSegmentInstanceArray(CDBSegmentInstanceArray *pSegmentInstanceAr)
  {
  	if (pSegmentInstanceAr == NULL)
  		return;
  
  	if (pSegmentInstanceAr->pData != NULL)
  	{
  		free(pSegmentInstanceAr->pData);
  		pSegmentInstanceAr->pData = NULL;
  	}
  
  	pSegmentInstanceAr->count = 0;
  }
  
  /*-------------------------------------------------------------------------
   *
   * GetCDBAssignmentArray(PGconn* pConn, const char* pszDBName, CDBAssignmentArray* pAssignmentAr )
   * returns bool
   *
   * This reads all rows from cdb_assignment,
   * joining with pg_class and pg_namespace to get the table and schema names.
   *
   * After using it, call FreeCDBAssignmentArray.
   *-------------------------------------------------------------------------
   */
  /*
  bool GetCDBAssignmentArray(PGconn* pConn, const char* pszDBName, CDBAssignmentArray* pAssignmentAr )
  {
  	bool		bRtn = false;
  	PQExpBuffer pQry = NULL;
  	PGresult*	pRes = NULL;
  
  	pAssignmentAr->count = 0;
  	pAssignmentAr->pData = NULL;
  
  	pQry = createPQExpBuffer();
  	appendPQExpBuffer(pQry,		" SELECT"
  							"	a.tbloid,"
  							"	c.relname,"
  							"	n.nspname,"
  							"	a.partno,"
  							"	a.segid"
  							"	FROM"
  							"	cdb_assignment a,"
  							"	pg_class c,"
  							"	pg_namespace n"
  							"	WHERE"
  							"	a.tbloid = c.oid"
  							" 	AND c.relnamespace = n.oid"
  							"	ORDER BY"
  							"	2" );
  
  	pRes = PQexec(pConn, pQry->data);
  	if ( pRes == NULL || PQresultStatus(pRes) != PGRES_TUPLES_OK )
  	{
  		write_err_msg("query to obtain list of cdb assignments failed : %s",
  				  PQerrorMessage(pConn));
  		goto cleanup;
  	}
  
  	int ntups = PQntuples(pRes);
  	if (ntups <= 0)
  	{
  		write_err_msg("no CDB assignments for database \"%s\"\n", pszDBName);
  		goto cleanup;
  	}
  
  	pAssignmentAr->count = ntups;
  	pAssignmentAr->pData = (CDBAssignment *)calloc( ntups, sizeof(CDBAssignment) );
  	if ( pAssignmentAr->pData == NULL )
  	{
  		write_err_msg("cannot allocate memory for query results in GetCDBAssignmentArray\n");
  		goto cleanup;
  	}
  
  	int i_tbloid	= PQfnumber(pRes, "tbloid");
  	int i_relname	= PQfnumber(pRes, "relname");
  	int i_nspname	= PQfnumber(pRes, "nspname");
  	int i_partno	= PQfnumber(pRes, "partno");
  	int i_dbid		= PQfnumber(pRes, "segid");
  
  	int i;
  	for ( i=0; i<ntups; i++ )
  	{
  		CDBAssignment* pAssignment = &pAssignmentAr->pData[i];
  		pAssignment->tbloid			= atoi(PQgetvalue(pRes, i, i_tbloid));
  		pAssignment->pszTableName	= strdup(PQgetvalue(pRes, i, i_relname));
  		pAssignment->pszNspName		= strdup(PQgetvalue(pRes, i, i_nspname));
  		pAssignment->partno			= atoi(PQgetvalue(pRes, i, i_partno));
  		pAssignment->segid			= atoi(PQgetvalue(pRes, i, i_dbid));
  	}
  
  	bRtn = true;
  
  cleanup:
  	if ( pRes != NULL )
  		PQclear(pRes);
  	if ( pQry != NULL )
  		destroyPQExpBuffer(pQry);
  
  	return bRtn;
  }
  */
  
  /*-------------------------------------------------------------------------
   *
   * GetCDBBaseTableArray(PGconn* pConn, const char* pszDBName, CDBBaseTableArray* pTableAr )
   * returns bool
   *
   * This reads all rows from cdb_basetable, with an optional filter on partitioned.
   *
   * After using it, call FreeCDBBaseTableArray.
   *-------------------------------------------------------------------------
   */
  
  bool
  GetCDBBaseTableArray(PGconn *pConn, CDBBaseTableArray *pTableAr)
  {
  	bool		bRtn = false;
  	PQExpBuffer pQry = NULL;
  	PGresult   *pRes = NULL;
  	int			ntups;
  	int			i_tbloid;
  	int			i_relname;
  	int			i_nspname;
  	int			i;
  
  	pTableAr->count = 0;
  	pTableAr->pData = NULL;
  
  	pQry = createPQExpBuffer();
  	appendPQExpBuffer(pQry, " SELECT"
  					  "	p.localoid,"
  					  "	c.relname,"
  					  "	n.nspname"
  					  "	FROM"
  					  "	gp_distribution_policy p,"
  					  "	pg_class c,"
  					  "	pg_namespace n"
  					  "	WHERE"
  					  "	p.localoid = c.oid"
  					  " 	AND c.relnamespace = n.oid"
  					  "	AND NOT c.relkind = 'x'"
  					  "	ORDER BY"
  					  "	2");
  
  	pRes = PQexec(pConn, pQry->data);
  
  	if (pRes == NULL || PQresultStatus(pRes) != PGRES_TUPLES_OK)
  	{
  		mpp_err_msg("ERROR", "mpp_table", "query to obtain list of Greenplum managed tables failed : %s",
  					PQerrorMessage(pConn));
  		goto cleanup;
  	}
  
  	ntups = PQntuples(pRes);
  
  	/*
  	if (ntups <= 0)
  	{
  		write_err_msg("no Greenplum managed tables for database \"%s\"\n", pszDBName);
  		goto cleanup;
  	}
  	 */
  
  	pTableAr->count = ntups;
  	pTableAr->pData = (CDBBaseTable *) calloc(ntups, sizeof(CDBBaseTable));
  	if (pTableAr->pData == NULL)
  	{
  		mpp_err_msg("ERROR", "mpp_table", "cannot allocate memory for query results in GetCDBBaseTableArray\n");
  		goto cleanup;
  	}
  
  	/* get column numbers */
  	i_tbloid = PQfnumber(pRes, "localoid");
  	i_relname = PQfnumber(pRes, "relname");
  	i_nspname = PQfnumber(pRes, "nspname");
  
  	for (i = 0; i < ntups; i++)
  	{
  		CDBBaseTable *pBaseTable = &pTableAr->pData[i];
  
  		pBaseTable->tbloid = atoi(PQgetvalue(pRes, i, i_tbloid));
  		pBaseTable->pszTableName = strdup(PQgetvalue(pRes, i, i_relname));
  		pBaseTable->pszNspName = strdup(PQgetvalue(pRes, i, i_nspname));
  	}
  
  	bRtn = true;
  
  cleanup:
  	if (pRes != NULL)
  		PQclear(pRes);
  	if (pQry != NULL)
  		destroyPQExpBuffer(pQry);
  
  	return bRtn;
  }
  
  /*-------------------------------------------------------------------------
   *
   * GetCDBSegmentInstanceArray(PGconn* pConn, const char* pszDBName, CDBSegmentInstanceArray* pSegmentInstanceAr )
   * returns bool
   *
   * This reads all rows from gp_segment_instance.
   *
   * After using it, call FreeCDBSegmentInstanceArray.
   *-------------------------------------------------------------------------
   */
  bool
  GetCDBSegmentInstanceArray(PGconn *pConn, const char *pszDBName, CDBSegmentInstanceArray *pSegmentInstanceAr)
  {
  	int			ntups;
  	int			i_dbid;
  	int			i_isValid;
  	int			i_hostname;
  	int			i_port;
  	int			i_datadir;
  	int			i;
  
  	bool		bRtn = false;
  	PQExpBuffer pQry = NULL;
  	PGresult   *pRes = NULL;
  
  	pSegmentInstanceAr->count = 0;
  	pSegmentInstanceAr->pData = NULL;
  
  	pQry = createPQExpBuffer();
  	appendPQExpBuffer(pQry, " SELECT"
  					  "	d.dbid,"
  					  "   d.valid,"
  					  "   h.hostname,"
  					  "   l.port,"
  					  "   l.datadir"
  					  "	FROM"
  					  " mpp.pgdatabase d,"
  					  "   mpp.listener l,"
  					  "   mpp.host h"
  					  "   where d.listenerid = l.listenerid"
  					  "   and l.hostId = h.hostid");
  
  	pRes = PQexec(pConn, pQry->data);
  	if (pRes == NULL || PQresultStatus(pRes) != PGRES_TUPLES_OK)
  	{
  		mpp_err_msg("ERROR", "mpp_table" "query to obtain list of Greenplum segment databases failed : %s",
  					PQerrorMessage(pConn));
  		goto cleanup;
  	}
  
  	ntups = PQntuples(pRes);
  	if (ntups <= 0)
  	{
  		mpp_err_msg("ERROR", "mpp_table" "no Greenplum segment databases for database \"%s\"\n", pszDBName);
  		goto cleanup;
  	}
  
  	pSegmentInstanceAr->count = ntups;
  	pSegmentInstanceAr->pData = (CDBSegmentInstance *) malloc(ntups * sizeof(CDBSegmentInstance));
  	if (pSegmentInstanceAr->pData == NULL)
  	{
  		mpp_err_msg("ERROR", "mpp_table", "cannot allocate memory for query results in GetCDBSegmentInstanceArray\n");
  		goto cleanup;
  	}
  
  	i_dbid = PQfnumber(pRes, "dbid");
  	i_isValid = PQfnumber(pRes, "valid");
  	i_hostname = PQfnumber(pRes, "hostname");
  	i_port = PQfnumber(pRes, "port");
  	i_datadir = PQfnumber(pRes, "datadir");
  
  	for (i = 0; i < ntups; i++)
  	{
  		CDBSegmentInstance *pSegmentInstance = &pSegmentInstanceAr->pData[i];
  
  		pSegmentInstance->segid = atoi(PQgetvalue(pRes, i, i_dbid));
  		pSegmentInstance->isValid = (strcmp(PQgetvalue(pRes, i, i_isValid), "t") == 0);
  		pSegmentInstance->dbname = strdup(pszDBName);
  		pSegmentInstance->dbhostname = PQgetvalue(pRes, i, i_hostname);
  		pSegmentInstance->dbport = atoi(PQgetvalue(pRes, i, i_port));
  		pSegmentInstance->dbdatadir = PQgetvalue(pRes, i, i_datadir);
  	}
  
  	bRtn = true;
  
  cleanup:
  	if (pRes != NULL)
  		PQclear(pRes);
  	if (pQry != NULL)
  		destroyPQExpBuffer(pQry);
  
  	return bRtn;
  }
  