With much help from KISTech, I have updated the
DBConn plugin to add a few more commands that I needed for my own projects. Changes included are:
Commands all start with
KKPODBC_ so they don't conflict with DBConn commands.
Multiple Instances! The first parameter of every function will be the instance number, from 0 to 2.
Added
KKPODBC_Init <Instance> to initialize an instance. Only call this once per instance.
Added
KKPODBC_ResetError(instance) to reset the error message to ""
Added
KKPODBC_GetColumns(instance) to return the number of columns from a SELECT statement
Added
KKPODBC_GetColumnName(instance,idx) to return the name of a column given the index
Modified the plugin so that it doesn't crash when failing to re-build the connection after it has been lost.
Full Command List:
KKPODBC_Init==(Instance) Initializes an ODBC connection
KKPODBC_Connect==(Instance, connection string)
KKPODBC_Error==(Instance) Returns a string
KKPODBC_ResetError==(Instance) Resets the error string
KKPODBC_Execute==(Instance, sql NON-SELECT statement) Returns an integer
KKPODBC_RunSQL==(Instance, sql SELECT statement) Returns an integer
KKPODBC_GetDataByColName==(Instance, row, column name) Returns a string
KKPODBC_GetDataByColNum==(Instance, row, column) Returns a string
KKPODBC_GetBool==(Instance, row, column) Returns a boolean
KKPODBC_GetByte==(Instance, row, column) Returns a byte value (0 to 255)
KKPODBC_GetWord==(Instance, row, column) Returns a word value (0 to 65535)
KKPODBC_GetDWord==(Instance, row, column) Returns a dword value (0 to +4,294,967,295)
KKPODBC_GetInt16==(Instance, row, column) Returns a small integer value (-32,768 to 32,767)
KKPODBC_GetInt32==(Instance, row, column) Returns an integer value (?2,147,483,648 to +2,147,483,647)
KKPODBC_GetInt64==(Instance, row, column) Returns a double integer value (?9,223,372,036,854,775,808 to +9,223,372,036,854,775,807)
KKPODBC_GetFloat==(Instance, row, column) Returns a float value
KKPODBC_GetDouble==(Instance, row, column) Returns a double float value
KKPODBC_GetString==(Instance, row, column) Returns a string value
KKPODBC_GetColumns==(Instance) Returns the number of columns from the last SELECT statement
KKPODBC_GetColumnName==(Instance, column) Returns the name of the specified column
With the new commands, you can create a SQL Browser of sorts. This crude snippet shows how. (Requires Matrix1)
` Initialize the connection
KKPODBC_Init 0
print "Connection Initialized"
wait key
` Connect to the server
c = KKPODBC_Connect(0,"DSN=triad.udd")
if c < 1
print "Connect failed:"
print KKPODBC_Error(0)
wait key
end
endif
print "Connection Created"
wait key
` Select Statement
numRows=KKPODBC_RunSQL(0,"SELECT * FROM AR_TAX_CODE")
if numRows = -1
print "SELECT failed:"
print KKPODBC_Error(0)
wait key
end
endif
numColumns=KKPODBC_GetColumns(0)
dim StringArray$(numRows-1,numColumns-1) : ` Holds the data from the query
dim BiggestString(numColumns-1) : ` Holds the largest length of the column
` Set the largest length to the header length
for c = 0 to numColumns-1
BiggestString(c) = fast len(KKPODBC_GetColumnName(0,c))+3
next c
` Grab the data, and increase the largest length if needed
for r = 0 to numRows-1
for c = 0 to numColumns-1
StringArray$(r,c) = KKPODBC_GetString(0,r,c)
if fast len(StringArray$(r,c))+3 > BiggestString(c) then BiggestString(c) = fast len(StringArray$(r,c))+3
next c
next r
` Create a new text file
open datafile to write 1, dir temp()+"\Temp.txt"
` Print the table column headers
h$ = ""
for c = 0 to numColumns-1
h$ = h$ + padright$(KKPODBC_GetColumnName(0,c)," ",BiggestString(c))
next c
write datafile string 1, h$
` Print the data
for r = 0 to numRows-1
h$ = ""
for c = 0 to numColumns-1
h$ = h$ + padright$(StringArray$(r,c)," ",BiggestString(c))
next c
write datafile string 1, h$
next r
close datafile 1
print
print " Done, Press any key to open results"
wait key
` Open the file
execute file dir temp()+"\Temp.txt","",""
nice wait 250
end
The source code for the plugin, in case anyone else wants to modify it:
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
namespace ClassLibrary1
{
using System;
using System.Data;
using System.Data.Odbc;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
public struct KKPConnection
{
public string DBConnError;
public OdbcConnection Conn;
public DataTable ResultSet;
}
public class Class1
{
private static uint g_uiReturnString;
private static string strFuncReturnValue;
// public static KKPConnection[] KKPConnections;
public static KKPConnection[] KKPConnections = new KKPConnection[3];
[DllImport("DBProCore.dll", EntryPoint="?CreateSingleString@@YAXPAKK@Z")]
private static extern void CreateSingleString2(ref uint pOldStr, uint dSize);
~Class1()
{
for (int con = 0; con < KKPConnections.Length; con++)
{
if (KKPConnections[con].Conn != null)
{
if (KKPConnections[con].Conn.State.ToString() == "Open")
{
KKPConnections[con].Conn.Close();
}
}
}
}
public static void KKPODBC_Init(int con)
{
KKPConnections[con].Conn = new OdbcConnection();
KKPConnections[con].ResultSet = new DataTable();
}
public static int KKPODBC_Connect(int con, string s)
{
KKPConnections[con].DBConnError = "";
if ((KKPConnections[con].Conn.ConnectionString != s) && (KKPConnections[con].Conn.State.ToString() == "Open"))
{
KKPConnections[con].Conn.Close();
}
KKPConnections[con].Conn.ConnectionString = s;
if (KKPConnections[con].Conn.State.ToString() != "Open")
{
try
{
KKPConnections[con].Conn.Open();
return 1;
}
catch (OdbcException exception)
{
KKPConnections[con].DBConnError = "ODBC Exception - " + exception.Message;
return -1;
}
catch (NullReferenceException exception2)
{
KKPConnections[con].DBConnError = "Null Reference Exception " + Convert.ToString(exception2);
return -1;
}
catch (Exception exception3)
{
KKPConnections[con].DBConnError = "System Exception " + exception3.Message;
return -1;
}
}
KKPConnections[con].DBConnError = "Criteria for openning a connection not met.";
return 0;
}
public static uint KKPODBC_Error(uint OldStr, int con)
{
return DBPStrings(OldStr, KKPConnections[con].DBConnError.ToString());
}
public static uint KKPODBC_ConnectionStatus(uint OldStr, int con)
{
return DBPStrings(OldStr, KKPConnections[con].Conn.State.ToString());
}
public static uint KKPODBC_CheckConnectionStatus(uint OldStr, int con, string sql)
{
if ((KKPConnections[con].Conn.State.ToString() != "Open") && (KKPConnections[con].Conn.ConnectionString != null))
{
try
{
KKPConnections[con].Conn.Open();
}
catch (OdbcException exception)
{
KKPConnections[con].DBConnError = "ODBC Exception - " + exception.Message;
}
catch (NullReferenceException exception2)
{
KKPConnections[con].DBConnError = "Null Reference Exception " + Convert.ToString(exception2);
}
catch (Exception exception3)
{
KKPConnections[con].DBConnError = "System Exception " + exception3.Message;
}
}
if ((KKPConnections[con].Conn.State.ToString() == "Open") && (KKPConnections[con].Conn.ConnectionString != null))
{
try
{
OdbcCommand selectCommand = new OdbcCommand(sql, KKPConnections[con].Conn);
}
catch
{
try
{
KKPConnections[con].Conn.Close();
KKPConnections[con].Conn.Open();
}
catch (OdbcException exception)
{
KKPConnections[con].DBConnError = "ODBC Exception - " + exception.Message;
}
catch (NullReferenceException exception2)
{
KKPConnections[con].DBConnError = "Null Reference Exception " + Convert.ToString(exception2);
}
catch (Exception exception3)
{
KKPConnections[con].DBConnError = "System Exception " + exception3.Message;
}
}
}
return DBPStrings(OldStr, KKPConnections[con].Conn.State.ToString());
}
public static void KKPODBC_ResetError(int con)
{
KKPConnections[con].DBConnError = "";
}
public static uint KKPODBC_GetColumns(int con)
{
return Convert.ToUInt32(KKPConnections[con].ResultSet.Columns.Count);
}
public static uint KKPODBC_GetColumnName(uint OldStr, int con, int col)
{
return DBPStrings(OldStr, KKPConnections[con].ResultSet.Columns[col].ColumnName);
}
// This command is used for SELECT statements, and returns the number of rows in the dataset
public static int KKPODBC_RunSQL(int con, string sql)
{
KKPConnections[con].ResultSet.Clear();
KKPConnections[con].ResultSet.Reset();
if (KKPConnections[con].Conn.State.ToString() == "Open")
{
try
{
OdbcCommand selectCommand = new OdbcCommand(sql, KKPConnections[con].Conn);
new OdbcDataAdapter(selectCommand).Fill(KKPConnections[con].ResultSet);
return KKPConnections[con].ResultSet.Rows.Count;
}
catch (OdbcException exception)
{
KKPConnections[con].DBConnError = Convert.ToString(exception);
return -1;
}
catch (NullReferenceException exception2)
{
KKPConnections[con].DBConnError = Convert.ToString(exception2);
return -1;
}
catch (Exception exception3)
{
KKPConnections[con].DBConnError = Convert.ToString(exception3);
return -1;
}
}
KKPConnections[con].DBConnError = "Could not establish database connection.";
return -1;
}
// This command is used for non-SELECT statements, and returns the number of rows affected by the command
public static int KKPODBC_Execute(int con, string sql)
{
if (KKPConnections[con].Conn.State.ToString() == "Open")
{
try
{
int num = new OdbcCommand(sql, KKPConnections[con].Conn).ExecuteNonQuery();
if (num > 0)
{
return num;
}
return 0;
}
catch (OdbcException exception)
{
KKPConnections[con].DBConnError = Convert.ToString(exception);
return -1;
}
catch (NullReferenceException exception2)
{
KKPConnections[con].DBConnError = Convert.ToString(exception2);
return -1;
}
catch (Exception exception3)
{
KKPConnections[con].DBConnError = Convert.ToString(exception3);
return -1;
}
}
KKPConnections[con].DBConnError = "Could not establish database connection.";
return -1;
}
public static uint KKPODBC_GetDataByColName(uint OldStr, int con, int r, string col)
{
if (KKPConnections[con].ResultSet.Columns.Contains(col))
{
DataRow row = KKPConnections[con].ResultSet.Rows[r];
return DBPStrings(OldStr, Convert.ToString(row[col]));
}
KKPConnections[con].DBConnError = "Column "+col+" does not exist";
return DBPStrings(OldStr, "ODBCERROR");
}
public static uint KKPODBC_GetDataByColNum(uint OldStr, int con, int r, int c)
{
DataRow row = KKPConnections[con].ResultSet.Rows[r];
return DBPStrings(OldStr, Convert.ToString(row[c]));
}
public static bool KKPODBC_GetBool(int con, int r, int c)
{
DataRow row = KKPConnections[con].ResultSet.Rows[r];
return Convert.ToBoolean(row[c]);
}
public static byte KKPODBC_GetByte(int con, int r, int c)
{
DataRow row = KKPConnections[con].ResultSet.Rows[r];
return Convert.ToByte(row[c]);
}
public static double KKPODBC_GetDouble(int con, int r, int c)
{
DataRow row = KKPConnections[con].ResultSet.Rows[r];
return Convert.ToDouble(row[c]);
}
public static uint KKPODBC_GetDWord(int con, int r, int c)
{
DataRow row = KKPConnections[con].ResultSet.Rows[r];
return Convert.ToUInt32(row[c]);
}
public static float KKPODBC_GetFloat(int con, int r, int c)
{
DataRow row = KKPConnections[con].ResultSet.Rows[r];
return Convert.ToSingle(row[c]);
}
public static short KKPODBC_GetInt16(int con, int r, int c)
{
DataRow row = KKPConnections[con].ResultSet.Rows[r];
return Convert.ToInt16(row[c]);
}
public static int KKPODBC_GetInt32(int con, int r, int c)
{
DataRow row = KKPConnections[con].ResultSet.Rows[r];
return Convert.ToInt32(row[c]);
}
public static long KKPODBC_GetInt64(int con, int r, int c)
{
DataRow row = KKPConnections[con].ResultSet.Rows[r];
return Convert.ToInt64(row[c]);
}
public static uint KKPODBC_GetString(uint OldStr, int con, int r, int c)
{
DataRow row = KKPConnections[con].ResultSet.Rows[r];
return DBPStrings(OldStr, Convert.ToString(row[c]));
}
public static ushort KKPODBC_GetWord(int con, int r, int c)
{
DataRow row = KKPConnections[con].ResultSet.Rows[r];
return Convert.ToUInt16(row[c]);
}
private static uint DBPStrings(uint OldStr, string strArg)
{
strFuncReturnValue = strArg + '\0';
CreateSingleString2(ref OldStr, Convert.ToUInt32(0));
CreateSingleString2(ref g_uiReturnString, Convert.ToUInt32(strFuncReturnValue.Length));
MoveMemory(g_uiReturnString, strFuncReturnValue, Convert.ToUInt32(strFuncReturnValue.Length));
return g_uiReturnString;
}
[DllImport("kernel32", EntryPoint="RtlMoveMemory")]
private static extern void MoveMemory(uint pDst, string pSrc, uint ByteLen);
}
}
Attached is the plugin, keywords file, and help files, most just slightly altered versions of KISTechs. Also attached is an example project that connects to a database, runs a select statement, and opens the results in Microsoft Excel.