本記事では CData サポート担当からこんなことを聞かれたらどこを確認すべきか?という観点で、よく頂くお問合せ内容をご紹介します。
記事はこちら →CData ODBC Driver for AAS は、ODBC スタンダードを使用してAzure Analysis Services にアクセスすることを可能にします。また、CData ODBC Driver for AAS を使用して、Azure Analysis Services をFoxPro プロジェクトに統合することも可能です。以下のステップは、含まれているコードサンプルのウォークスルーを提供します。このコードでは、Azure Analysis Services データをFoxPro データベースのテーブルに保存します。
未指定の場合は、初めにODBC DSN(data source name)で接続プロパティを指定します。ドライバーのインストールの最後にアドミニストレーターが開きます。Microsoft ODBC Data Source Administrator を使用して、ODBC DSN を作成および構成できます。
NOTE:[Map To WVarchar]接続プロパティをFALSE に設定します。(FoxPro はODBC W API を使用し、値タイプのWCHAR を返します。)
To connect to Azure Analysis Services, set the Url property to a valid server, for instance, asazure://southcentralus.asazure.windows.net/server, in addition to authenticating. Optionally, set Database to distinguish which Azure database on the server to connect to.
Azure Analysis Services uses the OAuth authentication standard. OAuth requires the authenticating user to interact with Azure Analysis Services using the browser. You can connect without setting any connection properties for your user credentials. See the Help documentation for more information.
開始するには、コードサンプルを新しいプロジェクトに追加します。以下のコマンドを実行することで、テーブルをすべて表示することなく保存できます。
DO C:\Temp\sqldump.prg WITH "CData AAS Source", "TESTDB", .f.
以下は、プログラムが従うプロセスです。
以下の行でAzure Analysis Services への接続を開きます。
m.hSQLconnection = SQLCONNECT(m.cODBCDSN)
接続が成功したら、SQLTABLES 関数を使用してテーブルのリストを取得できるようになります。以下のコードは、テーブルのリストを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
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
以下は、FoxPro 9 構文の完全なコードです。
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