Work with RabbitMQ Data in FoxPro
The CData ODBC driver for RabbitMQ enables you to access RabbitMQ data using the ODBC standard. You can use the CData ODBC Driver for RabbitMQ to integrate RabbitMQ data into your FoxPro project. The procedure below provides a walk-through of the included code sample, which saves RabbitMQ data into tables in a FoxPro database.
Connect to RabbitMQ as an ODBC Data Source
If you have not already, first specify connection properties in an ODBC DSN (data source name). This is the last step of the driver installation. You can use the Microsoft ODBC Data Source Administrator to create and configure ODBC DSNs.
NOTE: Set the 'Map To WVarchar' connection property to FALSE (FoxPro uses the ODBC W API and returns the WCHAR for the value type).
About RabbitMQ Management HTTP API
RabbitMQ is an open-source message broker that supports multiple messaging protocols. The RabbitMQ Management HTTP API provides HTTP-based access to management and monitoring data for a RabbitMQ server. The API exposes information about virtual hosts, exchanges, queues, bindings, connections, channels, consumers, users, permissions, policies, and cluster-wide statistics.
The Management plugin must be enabled on the RabbitMQ server for the HTTP API to be available. By default, the management interface listens on port 15672.
Using Basic Authentication
RabbitMQ Management HTTP API uses HTTP Basic authentication. You must supply the username and password of a RabbitMQ management user.
To enable access to the management API:
- Ensure the RabbitMQ Management plugin is enabled on your server (rabbitmq-plugins enable rabbitmq_management).
- Use an existing management user or create one with the appropriate management tag (management, policymaker, monitoring, or administrator).
- Note the full base URL of your RabbitMQ Management HTTP API (e.g., http://localhost:15672).
After configuring your RabbitMQ server, set the following connection properties to connect:
- AuthScheme: Set this to Basic.
- URL: Set this to the base URL of your RabbitMQ Management HTTP API (e.g., http://localhost:15672).
- User: Set this to your RabbitMQ management username (e.g., guest).
- Password: Set this to your RabbitMQ management password.
Example connection string:
Profile=C:\profiles\RabbitMQ.apip;AuthScheme=Basic;URL=http://localhost:15672;User=guest;Password=guest;
Available Tables
The RabbitMQ profile provides access to the following tables:
- Overview - Cluster-wide statistics and information about the RabbitMQ node
- Nodes - Information about individual nodes in the RabbitMQ cluster
- NodeMemory - Detailed memory usage breakdown for a specific cluster node
- Connections - List of all open AMQP connections to the broker
- Channels - List of all open AMQP channels across all connections
- Consumers - List of all consumers registered across all queues
- Exchanges - List of exchanges declared across all virtual hosts
- Queues - List of queues declared across all virtual hosts
- Bindings - List of all bindings between exchanges and queues
- VirtualHosts - List of virtual hosts configured on the broker
- VhostPermissions - User permissions within a specific virtual host
- Users - List of all RabbitMQ users
- Permissions - Permission records for all users across all virtual hosts
- TopicPermissions - Topic-level permission records for all users
- Policies - List of policies applied to queues and exchanges in virtual hosts
- OperatorPolicies - List of operator policies applied to queues in virtual hosts
- Parameters - List of component parameters (e.g., federation, shovel) per virtual host
- GlobalParameters - List of global parameters that apply across all virtual hosts
- VhostLimits - Resource limits configured for specific virtual hosts
- UserLimits - Resource limits configured for specific users
- FeatureFlags - List of feature flags and their enabled/disabled state on the node
- DeprecatedFeatures - List of deprecated features and their usage state
- AuthAttempts - Authentication attempt statistics for the node
- ClusterName - The name of the RabbitMQ cluster
- WhoAmI - Information about the currently authenticated management user
- ExchangeBindingsSource - Bindings for which a specific exchange is the source
- ExchangeBindingsDestination - Bindings for which a specific exchange is the destination
- QueueBindings - Bindings for a specific queue within a virtual host
Connect and Transfer
To get started, add the code sample to a new project. You can execute the following command to save all tables without displaying them:
DO C:\Temp\sqldump.prg WITH "CData API Source", "TESTDB", .f.
Below is the process that the program follows:
- Create a new FoxPro database.
Open a connection to RabbitMQ data with the line below:
m.hSQLconnection = SQLCONNECT(m.cODBCDSN)
If the connection was successful, you can now retrieve the list of tables using the SQLTABLES function. The code below saves the list of tables in sys_tables.dbf:
WAIT WINDOW "Fetching tables for data source '" + m.cODBCDSN + "'..." NOWAIT NOCLEAR m.nSQLTABLES = SQLTABLES(m.hSQLconnection) IF lUseDistinctConnections WAIT WINDOW "Closing ODBC Connection for data source '" + m.cODBCDSN + "'..." NOWAIT NOCLEAR SQLDISCONNECT(m.hSQLconnection) m.hSQLconnection = 0 * SQLCONNECT needs to be called again ENDIF IF m.nSQLTABLES > 0 * create local table containing list of tables in db COPY TO (m.cImportData + "sys_tables") USE * convert each table to DBF USE (m.cImportData + "sys_tables") ALTER TABLE DBF("sys_tables") ; ADD COLUMN records i ; ADD COLUMN dbfname m-
Scan over each table, saving it to a DBF file. The function ODBCtoDBF stores the table in a DBF file and then opens a grid if the lBrowse parameter is set to true:
FUNCTION ODBCtoDBF (cTableName as String, cTableType as String, lBrowse as Logical, lhSQLConnection as Integer) WAIT WINDOW ; "Converting " + m.cTableType + ' "' + m.cTableName + '" to DBF...' ; NOWAIT NOCLEAR ACTIVATE SCREEN * strip characters incompatible with FoxPro out of the name of the DBF file m.cTableAlias = "" m.nTableNameLen = LEN(m.cTableName) m.nTableNameStart = 1 FOR m.nTableNameStart = 1 TO m.nTableNameLen m.cCharacter = SUBSTR(m.cTableName, m.nTableNameStart, 1) IF !ISALPHA(m.cCharacter) .and. (m.nTableNameStart = 1 .or. !ISDIGIT(m.cCharacter)) m.cTableAlias = m.cTableAlias + "_" ELSE m.cTableAlias = m.cTableAlias + m.cCharacter ENDIF ENDFOR m.cFromTable = m.cTableName m.cTempViewAlias = m.cTableType + "_" + m.cTableAlias LOCAL loException as Exception LOCAL lnResultSets TRY * run query m.lnResultSets = SQLEXEC(m.lhSQLConnection, ; "SELECT * FROM " + m.cFromTable, ; m.cTempViewAlias, ; aSQLResult) IF m.lnResultSets#1 SET STEP ON ENDIF ACTIVATE SCREEN CATCH TO m.loException ACTIVATE SCREEN ? "Error opening " + m.cTempViewAlias + ":" ? m.loException.Message ? m.loException.Details ENDTRY IF !USED(m.cTempViewAlias) RETURN ENDIF * copy records from view cursor to disk SELECT * FROM (m.cTempViewAlias) ; INTO TABLE (m.cImportData + m.cTableAlias) IF USED(m.cTableAlias) ACTIVATE SCREEN FLUSH && flush the buffer to write the data to disk IF m.lBrowse * pop the table up on screen SELECT (m.cTableAlias) BROWSE NORMAL NOMODIFY NOWAIT ACTIVATE SCREEN ELSE * close on-disk table for now USE IN (m.cTableAlias) ACTIVATE SCREEN ENDIF ENDIF IF USED(m.cTempViewAlias) USE IN &cTempViewAlias && close SQL view ACTIVATE SCREEN ENDIF WAIT CLEAR ENDFUNC - You can now save tables of RabbitMQ data as DBF files.
Below is the full code, in FoxPro 9 syntax:
PARAMETERS cODBCDSN, cDatabaseName, lBrowseAfterConvert
* cODBCDSN The ODBC data source name, used for the name of the folder where the DBF tables are stored.
* cDatabaseName The name of the FoxPro database to use. This database is created if it does not exist. The default is DATABASE_NAME.
*
* lBrowseAfterConvert If ".t." display each table with the BROWSE command after importing it. If ".f." close each table before moving on to the next one.
#define ODBC_DATASOURCE "DataSourceName"
#define DATABASE_NAME "odbcdata"
m.m_tpath = ".\" && root directory for data
ON ERROR
SET SAFETY OFF
IF VARTYPE(m.cODBCDSN)#"C" .or. EMPTY(m.cODBCDSN)
m.cODBCDSN = ODBC_DATASOURCE
ENDIF
IF VARTYPE(m.cDatabaseName)#"C" .or. EMPTY(m.cDatabaseName)
m.cDatabaseName = DATABASE_NAME
ENDIF
m.cImportData = m.cODBCDSN + "\"
CLOSE TABLES ALL
CLOSE DATABASES ALL
IF !DIRECTORY(m.cImportData)
MKDIR (m.cImportData)
ENDIF
CREATE DATABASE (m.cDatabaseName)
CREATE CONNECTION (m.cDatabaseName) DATASOURCE (m.cODBCDSN) DATABASE (m.cDatabaseName)
WAIT WINDOW "Opening ODBC Connection for data source '" + m.cODBCDSN + "'..." NOWAIT NOCLEAR
m.hSQLconnection = SQLCONNECT(m.cODBCDSN)
IF m.hSQLconnection > 0
* Connection successful; get list of tables
WAIT WINDOW "Fetching tables for data source '" + m.cODBCDSN + "'..." NOWAIT NOCLEAR
m.nSQLTABLES = SQLTABLES(m.hSQLconnection)
IF m.nSQLTABLES > 0
* Create local table containing list of tables in db
COPY TO (m.cImportData + "sys_tables")
USE
* Convert each table to DBF
USE (m.cImportData + "sys_tables")
ALTER TABLE DBF("sys_tables") ;
ADD COLUMN records i ;
ADD COLUMN dbfname m
SCAN
m.cCurrentTable = TRIM(sys_tables.table_name)
m.cCurrentTableType = TRIM(sys_tables.table_type) && Valid values are "SYSTEMTABLE", "TABLE", and "VIEW".
IF m.cCurrentTableType = "TABLE" or m.cCurrentTableType = "VIEW"
ODBCtoDBF(m.cCurrentTable, m.cCurrentTableType, m.lBrowseAfterConvert, m.hSQLConnection)
ELSE
ACTIVATE SCREEN
? "ERROR:", m.cCurrentTable, "Couldn't open ODBC connection."
=MESSAGEBOX("couldn't open data source " + m.cODBCDSN + " for table " + m.cCurrentTable + ".")
ENDIF
ENDSCAN
BROWSE NORMAL NOWAIT
ELSE
=MESSAGEBOX("No tables found in data source " + m.cODBCDSN + ".")
SET STEP ON
ENDIF
SQLDISCONNECT(m.hSQLconnection)
ELSE
=MESSAGEBOX("Could not open data source " + m.cODBCDSN + ".")
SET STEP ON
ENDIF
FUNCTION ODBCtoDBF (cTableName as String, cTableType as String, lBrowse as Logical, lhSQLConnection as Integer)
WAIT WINDOW ;
"Converting " + m.cTableType + ' "' + m.cTableName + '" to DBF...' ;
NOWAIT NOCLEAR
ACTIVATE SCREEN
* Strip characters incompatible with FoxPro out of the name of the DBF file
m.cTableAlias = ""
m.nTableNameLen = LEN(m.cTableName)
m.nTableNameStart = 1
FOR m.nTableNameStart = 1 TO m.nTableNameLen
m.cCharacter = SUBSTR(m.cTableName, m.nTableNameStart, 1)
IF !ISALPHA(m.cCharacter) .and. (m.nTableNameStart = 1 .or. !ISDIGIT(m.cCharacter))
m.cTableAlias = m.cTableAlias + "_"
ELSE
m.cTableAlias = m.cTableAlias + m.cCharacter
ENDIF
ENDFOR
m.cFromTable = m.cTableName
m.cTempViewAlias = m.cTableType + "_" + m.cTableAlias
LOCAL loException as Exception
LOCAL lnResultSets
TRY
* Run query
m.lnResultSets = SQLEXEC(m.lhSQLConnection, ;
"SELECT * FROM " + m.cFromTable, ;
m.cTempViewAlias, ;
aSQLResult)
IF m.lnResultSets#1
SET STEP ON
ENDIF
ACTIVATE SCREEN
CATCH TO m.loException
ACTIVATE SCREEN
? "Error opening " + m.cTempViewAlias + ":"
? m.loException.Message
? m.loException.Details
ENDTRY
IF !USED(m.cTempViewAlias)
RETURN
ENDIF
* Copy records from view cursor to disk
SELECT * FROM (m.cTempViewAlias) ;
INTO TABLE (m.cImportData + m.cTableAlias)
IF USED(m.cTableAlias)
ACTIVATE SCREEN
FLUSH && Flush the buffer to write the data to disk
IF m.lBrowse
* Display the table on screen
SELECT (m.cTableAlias)
BROWSE NORMAL NOMODIFY NOWAIT
ACTIVATE SCREEN
ELSE
* Close on-disk table
USE IN (m.cTableAlias)
ACTIVATE SCREEN
ENDIF
ENDIF
IF USED(m.cTempViewAlias)
USE IN &cTempViewAlias && Close SQL view
ACTIVATE SCREEN
ENDIF
WAIT CLEAR
ENDFUNC