Showing posts with label firebird. Show all posts
Showing posts with label firebird. Show all posts

2014/01/10

Bitnami의 WAMP를 이용하여 PHP와 Firebird 연동하기

간단한 PHP 테스트를 위해 환경을 구축하는데 Firebird 연동에서 고생을 좀 했다.

별도의 구성이 필요 없고 PHP 와 Firebird와의 연동 테스트로 Bitnami 의 WAMP 패키지를 이용하였다.

아주 오랫만에 해보는 거이고 Firebird에 대한 정보가 많지 않아 고생한 것 같다.


PHP에서는 Firebird와 연동하는 방법으로 두 가지를 지원한다.

하나는 오래전 방법으로 php_interbase.dll 이고 다른 하나는 PHP 5 부터인가 지원하는 PDO(PHP Data Objects)를 이용하는 방법이 있다.


이 두가지 방법 모두 활성화 해 보았다.


우선 Bitnami 가 설치된 경로에서 php폴더에 php.ini내용 중에서 주석으로 처리되어 있는 아래 두 줄의 주석을 해제한다.

extension=php_interbase.dll

extension=php_pdo_firebird.dll


그리고 Firebird 32비트 버전에 포함되어 있는 fbclient.dll 파일을 Bitnami 에 포함되어있는 Apache 폴더의 bin 디렉토리에 복사를 하고 Apache 서버를 재 시작한 후 phpinfo(); 함수를 이용하여 확인 한다. 

phpinfo() 함수의 결과중에서 PDO 등록된 드라이버 목록에 Firebird가 보여지고 PDO_Firebird가 enable 된다. <

Original Post : http://neodreamer-dev.tistory.com/723

2011/10/13

Firebird 2.5.1 Release

Firebird 데이터베이스의 새 버전이 공개 되었다. 이번 버전은 2.5 버전의 마이너 업그레이드 버전으로 버그픽스와 성능 개선이 이루어 졌다고 한다.



Firebird 2.5.1 버전의 개선 사항


  • The SQLSTATE code has been made available as a PSQL context variable, for use in WHEN .. exception blocks, in the same manner as GDSCODE and SQLCODE

  • Now it is possible to write to global temporary tables in a read-only database

  • Diagnostics for internal trace errors were improved

  • The fbtracemgr utility will now do a periodic flush to output

  • Performance of gbak restore at the data insertion stages has improved

  • Conversions between BLOBs and other data types can now be effected in the API functions

  • The Services API now supports the “metadata-only” restore

  • A “silent install” switch has been implemented for make install on POSIX

  • The unused bytes of VARCHAR values in the message buffer are now set to zero

  • The actual record compression ratio is now estimated in the optimizer

  • The MON$STATEMENT_ID value now stays constant among monitoring snapshots

  • The SO_KEEPALIVE option on the client TCP socket will now be set, as a measure to guard against aggressive timing out of sockets by newer Windows systems

  • Lock Manager can now cancel waits that become interminable

  • A platform port of v.2.5.1 for HPPA has been done for both Linux and Alpha




Firebird websit

Original Post :
http://neodreamer-dev.tistory.com/594

2011/09/25

[C#] Firebird Embedded로 사용하기

C#에서 Firebird를 사용해 보았는데 Embedded 도 사용이 가능한지 테스트 해 보았다.


Embedded 사용도 크게 차이가 없었다.


연결문자열의 ServerType을 1로(FbConnectionStringBuilder를 사용할 경우 csb.ServerType = FbServerType.Embedded;) 설정 하고 Firebird Embedded 패키지의 아래 파일들을 실행파일과 함께 두면 된다.

fbembed.dll

firebird.conf

firebird.msg

ib_util.dll

icudt30.dll

icuin30.dll

icuuc30.dll<

Original Post : http://neodreamer-dev.tistory.com/581

2011/09/22

[C#] Firebird 연결문자열을 FbConnectionStringBuilder를 이용하여 만들기

Connection Strings을 아래와 같이 문자열로 작업하는 것이 아니라 FbConnectionStringBuilder 객체를 이용하면 좀 더 쉽고 직관적으로 만들 수 있다.

string connectionString =
"User=SYSDBA;" +
"Password=masterkey;" +
"Database=F:\FirebirdDB\ estdb.fdb;" +
"DataSource=localhost;" +
"Charset=UTF8;" +
"ServerType=0"; // Type: 0 - Server, 1 - Embedded



FbConnectionStringBuilder csb = new FbConnectionStringBuilder();
csb.UserID = "SYSDBA";
csb.Password = "masterkey";
csb.Database = "F:\FirebirdDB\ estdb.fdb";
csb.DataSource = "localhost";
csb.Charset = "UTF8";
csb.ServerType = FbServerType.Default;

// Create Database
FbConnection.CreateDatabase(csb.ToString());

// Create Connection object
FbConnection conFirebird = new FbConnection(csb.ToString());

:

// Drop Database
FbConnection.DropDatabase(csb.ToString());



FbConnectionStringBuilder Properties (출처: Firebird .Net Provider SDK 1.7 문서)





















































































































NameTypeDescription
CharsetstringGets or sets the connection character set.
ClientLibrarystring

ConnectionLifeTimeintGets or sets the lifetime of a connection in the pool.
ConnectionTimeoutintGets the time to wait while trying to establish a connection before terminating
the attempt and generating an error.
ContextConnectionbool

DatabasestringGets the name of the actual database or the database to be used when a
connection is open.
DataSourcestringGets the name of the Firebird Server to which to connect.
DbCachePagesint

DialectintGets or sets the database dialect.
Enlistbool

FetchSizeintIndicates the number of rows that will be fetched at the same time on Read calls into the internal row buffer.
IsolationLevelIsolationLevel Gets or sets the default Isolation Leve for implicit transactions.
MaxPoolSizeintGets or sets the maximun pool size.
MinPoolSizeintGets or sets the minumun pool size.
PacketSizeintGets or sets the size (in bytes) of network packets used to communicate with an
instance of Firebird Server.
PasswordstringGets ort sets the password for the Firebird user account.
PoolingboolGets or sets the status of the connection pooling.
PortintGets or sets the port number in the server for establish the connection.
ReturnRecordsAffected bool

RolestringGets or sets the suer role name.
ServerTypeFbServerType Gets or sets the server type to wich we want to connect.
UserIDstringGets or sets the firebird User account for login.



<

Original Post : http://neodreamer-dev.tistory.com/580

[C#] Firebird 사용하기

C#을 공부하고 있는데 Firebird를 사용해보고 싶어 Firebird .Net Provider 사용에 대한 테스트를 해 보았다.

C#은 참 사용하기 쉽게 만든 언어 같다. Firebird를 C++에서 사용하기 위해 IBPP 나 Firebird C API를 사용해서 Firebird를 이용할 때에는 무척이나 복잡했었다.

Firebird C++ Wrapper도 .Net Provider 처럼 사용하기 어렵지 않은 라이브러리가 있었으면 좋겠다.


C#에서의 테스트는 데이버베이스를 생성하고 테이블을 만들어 Insert, Update 등의 테스트를 하고 테이블과 데이터베이스를 삭제하여 보았다.


아래 코드는 테스트에 사용된 코드이다.

txtResult.Clear();
txtResult.AppendText("Begin Testing...\n");

string connectionString =
"User=SYSDBA;" +
"Password=masterkey;" +
"Database=F:\FirebirdDB\ estdb.fdb;" +
"DataSource=localhost;" +
"Charset=UTF8;" +
"ServerType=0"; // Type: 0 - Server, 1 - Embedded

try
{
// Create Database
FbConnection.CreateDatabase(connectionString);
txtResult.AppendText("Create Database...OK\n");

// Create Connection object
FbConnection conFirebird = new FbConnection(connectionString);
txtResult.AppendText("Create Connection Object...OK["
+ conFirebird.State.ToString() + " : "
+ FbConnection.ConnectionPoolsCount.ToString()
+ "]\n");

// Connect
conFirebird.Open();
txtResult.AppendText("Open Connection...OK["
+ conFirebird.State.ToString() + " : "
+ FbConnection.ConnectionPoolsCount.ToString()
+ "]\n");

FbCommand cmdSQL = new FbCommand();
cmdSQL.Connection = conFirebird;

// Create Table
string strQuery = "CREATE TABLE Member"
+ "("
+ " ID VARCHAR(20) NOT NULL,"
+ " NAME VARCHAR(20) NOT NULL,"
+ " ALIAS VARCHAR(20),"
+ " AGE INTEGER"
+ ")";

cmdSQL.CommandText = strQuery;
cmdSQL.ExecuteNonQuery();
txtResult.AppendText("Create test Table...OK\n");

// Insert Data
FbTransaction transInsert = conFirebird.BeginTransaction();
cmdSQL.Transaction = transInsert;
for (int i = 0; i < 5; i++)
{
cmdSQL.CommandText = "INSERT INTO Member(ID, NAME, ALIAS, AGE) "
+ "VALUES ("
+ " 'Man" + i.ToString() + "' "
+ " ,'Name" + i.ToString() + "' "
+ " ,'Alias" + i.ToString() + "' "
+ " ," + (i + 10).ToString()
+ ");";
int nRow = cmdSQL.ExecuteNonQuery();
txtResult.AppendText(" Insert " + nRow.ToString() + "row(s)...OK\n");
}
transInsert.Commit();
transInsert.Dispose();
cmdSQL.Transaction = null;
txtResult.AppendText(" Insertion committed...OK\n");
txtResult.AppendText("Insert data...OK\n");

// Select Data
FbDataAdapter da = new FbDataAdapter("SELECT * FROM Member", conFirebird);
DataTable dt = new DataTable();
da.Fill(dt);
ArrayList lstColumn = new ArrayList();
foreach (DataColumn col in dt.Columns)
{
txtResult.AppendText(col.ColumnName + " ");
lstColumn.Add(col.ColumnName);
}
txtResult.AppendText("\n");
foreach (DataRow row in dt.Rows)
{
txtResult.AppendText(row[lstColumn[0] as string] + " "
+ row[lstColumn[1] as string] + " "
+ row[lstColumn[2] as string] + " "
+ row[lstColumn[3] as string] + " "
+ "\n"
);
}
dt.Clear();

// Update some data
FbTransaction transUpdate = conFirebird.BeginTransaction();
txtResult.AppendText("UPDATE Member SET Age = Age + 20 WHERE Age > 11;\n");
cmdSQL.CommandText = "UPDATE Member SET Age = Age + 20 WHERE Age > 11;";
cmdSQL.Transaction = transUpdate;
int nUpdate = cmdSQL.ExecuteNonQuery();
transUpdate.Commit();
transUpdate.Dispose();
cmdSQL.Transaction = null;
txtResult.AppendText(" " + nUpdate.ToString() + "row(s) updated!\n");
txtResult.AppendText("Update data...OK\n");

// Select Data
da.SelectCommand.CommandText = "SELECT * FROM Member";
da.Fill(dt);
foreach (DataColumn col in dt.Columns)
{
txtResult.AppendText(col.ColumnName + " ");
}
txtResult.AppendText("\n");
foreach (DataRow row in dt.Rows)
{
txtResult.AppendText(row["ID"] + " "
+ row["NAME"] + " "
+ row["ALIAS"] + " "
+ row["AGE"] + " "
+ "\n"
);
}
dt.Clear();
da.Dispose();

// Delete data
cmdSQL.CommandText = "DELETE FROM Member;";
cmdSQL.ExecuteNonQuery();
txtResult.AppendText("Delete data...OK\n");

// Drop Table
cmdSQL.CommandText = "DROP TABLE Member;";
cmdSQL.ExecuteNonQuery();
txtResult.AppendText("Drop test Table...OK\n");

// Close
conFirebird.Close();
txtResult.AppendText("Close Connection...OK["
+ conFirebird.State.ToString() + " : "
+ FbConnection.ConnectionPoolsCount.ToString()
+ "]\n");

// Clear Pool
FbConnection.ClearPool(conFirebird);
txtResult.AppendText("Clear Connection pool...OK["
+ conFirebird.State.ToString() + " : "
+ FbConnection.ConnectionPoolsCount.ToString()
+ "]\n");

// Drop Database
FbConnection.DropDatabase(connectionString);
txtResult.AppendText("Drop Database...OK\n");
}
catch (FbException ex)
{
//MessageBox.Show("Occured FbException \n" + ex.ToString());
txtResult.AppendText("Occured FbException => Error code : "
+ ex.ErrorCode.ToString() + "\n");
txtResult.AppendText("-------------------------------------------------\n");
txtResult.AppendText(ex.ToString() + "\n");
txtResult.AppendText("-------------------------------------------------\n");
}
catch (Exception ex)
{
//MessageBox.Show("Occured Exception \n" + ex.ToString());
txtResult.AppendText("Occured Exception \n");
txtResult.AppendText("-------------------------------------------------\n");
txtResult.AppendText(ex.ToString() + "\n");
txtResult.AppendText("-------------------------------------------------\n");
}

txtResult.AppendText("End Testing.\n");


실행 결과:


Begin Testing...
Create Database...OK
Create Connection Object...OK[Closed : 0]
Open Connection...OK[Open : 1]
Create test Table...OK
Insert 1row(s)...OK
Insert 1row(s)...OK
Insert 1row(s)...OK
Insert 1row(s)...OK
Insert 1row(s)...OK
Insertion committed...OK
Insert data...OK
ID NAME ALIAS AGE
Man0 Name0 Alias0 10
Man1 Name1 Alias1 11
Man2 Name2 Alias2 12
Man3 Name3 Alias3 13
Man4 Name4 Alias4 14
UPDATE Member SET Age = Age + 20 WHERE Age > 11;
3row(s) updated!
Update data...OK
ID NAME ALIAS AGE
Man0 Name0 Alias0 10
Man1 Name1 Alias1 11
Man2 Name2 Alias2 32
Man3 Name3 Alias3 33
Man4 Name4 Alias4 34
Delete data...OK
Drop test Table...OK
Close Connection...OK[Closed : 1]
Clear Connection pool...OK[Closed : 0]
Drop Database...OK
End Testing.
<

Original Post : http://neodreamer-dev.tistory.com/579

2011/01/28

Firebird는 Transaction 처리가 기본!!

요즘 Firebird 를 공부하고 있다. 조금은 당황스러운 경험을 하였다.



Firebird 설치시 포함되어 있는 Interactive SQL(isql.exe) 을 이용하여 몇가지 테스트를 하였다. 두 개의 isql 인스턴스를 실행하고 하나의 데이터베이스 연결을 하였다.




A isql 인스턴스(이하 A) 에서 테이블을 하나 생성 하였다. 그리고 B isql 인스턴스(이하 B)에서 데이블이 존재하는지 SHOW TABLE 명령을 확인해 보니 존재 하는 것으로 보였다. 이 것이 DDL은 자동으로 commit 이 되어 그러는 것으로 알았다. 나중에 알게되었지만 DDL 이라도 isql 환경 설정에서 AutoDDL 을 off 로 두면 자동으로 commit 이 수행되지 않는다.




B 에서 방금 생성한 member 테이블에 데이터가 있는지 확인(SELECT * FROM member;)하여 보았다. 데이터가 없음을 확인하고 A 에서 member 테이블에 데이터를 Insert 하고 B 에서 확인을 하였다. B 에서는 아무런 데이터가 확인 되지 않았다. 당연한 결과로 A 에서 작업을 한 후 commit 을 하지 않았기 때문에 B 에서 확인할 수 없었다. A 에서 commit 을 한 후 B 에서 확인을 해 보아도 보이지 않았다. 이상한 일이였다. B 에서 commit 명령을 내리고서야 A 에서 작업한 내용을 확인할 수 있었다.




이 상황이 잘 이해가 되지 않았다. A 에서 작업(Transaction)이 commit 이 되면 B 에서 당연히 확인이 되어야 하는 것으로 생각을 하였다. 이 상황이 잘 못 된 것인줄 알고 MySQL 의 InnoDB 를 이용하여 Transaction 테스트를 해 보았지만 MySQL 는 나의 예상대로 동작을 하였다.




답을 찾아 헤메던 중 외국의 firebird community 에서 도움을 얻어 이유를 알았다. 예전에 오라클을 공부할 때 들었던 관계형 데이터베이스의 ACID 특성에 대해서 다시 듣게 되었다.

B 에서 A 의 작업이 확인되지 않은 이유는 B 에서 데이터를 확인하기 위해 DML(select)을 수행하면서 B 에서 transaction 이 시작 되었고 transaction 이 시작되면서 ACID 의 Isolation 특성으로 데이터베이스는 transaction 이 시작할때의 상태를 독립적으로 유지하게 되어서 B 의 transaction 이 commit 된 후에 A 에서 가한 데이터베이스의 변경된 사항을 확인할 수 있었던 것이였다. mysql 에서도 이러한 관점에서 다시 테스트를 해 보니 동일한 결과를 얻을 수 있었다.




일반적인 GUI 프로그램을 사용하게 되면 Transaction 관리를 하기 때문에 개별적인 작업에 대한 적용이 이루어지는 것이다.




Firebird 란 놈을 좀 더 공부해 보아야겠다. Open Source 정책으로 운영되고 사용자 층이 두텁지 않아서 자료가 많이 부족해서 공부하기가 어렵다.<

Original Post : http://neodreamer-dev.tistory.com/495

2011/01/24

Firebird Table Schema 확인하기

SQL> SHOW TABLE member2;
NAME VARCHAR(20) Nullable
AGE INTEGER Nullable
SQL>
<

Original Post : http://neodreamer-dev.tistory.com/493

Firebird 2.5 기본 데이터베이스 경로 설정하기

긴 경로명을 표시하지 않고 기본 설정으로 하는 방법을 찾아 보았다. alias 를 사용하는 것이 아니라 firebird.conf 에 DatabaseAccess 를 설정하는 방법이다.



firebird 설치 경로의 firebird.conf 파일을 열어보면 DatabaseAccess 항목이 있는데 이 항목에 원하는 경로를 설정해 놓으면 데이터베이스 접속시 전체 경로를 입력하지 않고 접속할 수 있다.




DatabaseAccess = Restrict E:\firebirdx64\db




위 처럼 설정을 하고 데이터베이스를 재시작 하면 isql 에서 경로 없이 데이터베이스를 새성하면 지정한 위치에 데이터베이스가 생성이 된다.




SQL>CREATE DATABASE "test.fdb";




위와 같이 입력을 하면 "E:\firebirdx64\db" 위치에 test.fdb 가 생성이 된다.




원격에서 이 데이터베이스를 접속할 때에서 전체 경로설정 없이 아래와 같이 입력을 하면 test.fdb 에 접속할 수 있다.




SQL>CONNECT "IPAddress:test.fdb";




이 방법은 해당 경로에 대한 작업에만 유효하며 하위 폴더에 대한 접근은 이 방법으로 할 수가 없었다.<

Original Post : http://neodreamer-dev.tistory.com/492

2011/01/23

Firebird Datetime 필드 값 가져오기

Firebird 를 공부하면서 공부해야 할 게 많은 것 같다. Firebird 는 무료이면서 강력한 기능을 지원하고는 있지만 API를 활용하는 면 에서는 자료가 많지 않아 기술을 습득히가기 너무 힘든 것 같다. 여러가지중 오늘은 날짜형 데이터를 접근하는 것을 해 보았고 기록을 남긴다.



아래 코드는 날짜 필드(Timestamp) 에서 데이터를 가져와서 C 의 날짜형으로 변환하는 코드이다.




ISC_TIMESTAMP tmEnter;
short outFlag_00;

pOutSqlDA->sqlvar[ 0 ].sqldata = (ISC_SCHAR*)&tmEnter;
pOutSqlDA->sqlvar[ 0 ].sqltype = SQL_TIMESTAMP + 1;
pOutSqlDA->sqlvar[ 0 ].sqllen = sizeof(tmEnter);
pOutSqlDA->sqlvar[ 0 ].sqlind = &outFlag_00;

fetch_stat = isc_dsql_fetch( status, &stmt, 1, pOutSqlDA )

tm tmPC;
isc_decode_timestamp( &tmEnter, &tmPC );
<

Original Post : http://neodreamer-dev.tistory.com/491

2011/01/17

2010/12/30

Firebird C API - 질의문 수행 후 반영된 레코드 수 구하는 함수

struct AFFECTED_ROW
{
int Insert;
int Select;
int Update;
int Delete;

AFFECTED_ROW()
{
Init();
}

void Init()
{
Insert = 0;
Select = 0;
Update = 0;
Delete = 0;
}
};


void CTestEFBDlg::GetAffectedRow( isc_stmt_handle stmt, AFFECTED_ROW& affected )
{
static char const info_count[] = { isc_info_sql_records };
char result[64] = { 0, };
int ret = 0;

ISC_STATUS_ARRAY status;
ISC_LONG sqlcode;

affected.Init();

isc_dsql_sql_info( status, &stmt, sizeof(info_count), info_count, sizeof(result), result );

if ( status[ 0 ] == 1 && status[ 1 ] > 0 )
{
// Error occurred
sqlcode = isc_sqlcode( status );

char szMsg[512];
isc_sql_interprete( (short)sqlcode, szMsg, 512 );

CString strMsg;
strMsg.Format( _T("Fail to isc_dsql_sql_info : %d - %s"), sqlcode, CString( szMsg ) );
AppendResult( strMsg );
}
else
{
char* pCur = result;
int length;
if ( *pCur == isc_info_sql_records )
{
pCur++;
length = isc_vax_integer(pCur, 2);
pCur += 2;

while(*pCur != 1)
{
switch(*pCur)
{
case isc_info_req_select_count:
pCur++;
length = isc_vax_integer(pCur, 2);
pCur += 2;
affected.Select = isc_vax_integer(pCur, length);
pCur += length;
break;
case isc_info_req_insert_count:
pCur++;
length = isc_vax_integer(pCur, 2);
pCur += 2;
affected.Insert = isc_vax_integer(pCur, length);
pCur += length;
break;
case isc_info_req_update_count:
pCur++;
length = isc_vax_integer(pCur, 2);
pCur += 2;
affected.Update = isc_vax_integer(pCur, length);
pCur += length;
break;
case isc_info_req_delete_count:
pCur++;
length = isc_vax_integer(pCur, 2);
pCur += 2;
affected.Delete = isc_vax_integer(pCur, length);
pCur += length;
break;
default:
pCur++;
break;
}
}
}
}
}


GetAffectedRow( stmt, affected );

CString strMsg;
strMsg.Format( _T("%d Row(s) Updated"), affected.Update );
AfxMessageBox( strMsg );
<

Original Post : http://neodreamer-dev.tistory.com/481

2010/12/26

Firebird C API 질의문 수행 후 반영된 레코드 수 구하기

아래 코드는 isc_dsql_sql_info() 함수를 이용하여 질의문를 후행 한 후 반영된 레코드 수를 가져오는 코드 이다.

int del_count = 0, ins_count = 0, upd_count = 0, sel_count = 0;
static char const info_count[] = { isc_info_sql_records };
char result[64];
int ret = 0;

isc_dsql_sql_info( status, &stmt, sizeof(info_count), info_count, sizeof(result), result );

if ( status[ 0 ] == 1 && status[ 1 ] > 0 )
{
// Error occurred
sqlcode = isc_sqlcode( status );

char szMsg[512];
isc_sql_interprete( (short)sqlcode, szMsg, 512 );

CString strMsg;
strMsg.Format( _T("Fail to isc_dsql_sql_info : %d - %s"), sqlcode, CString( szMsg ) );
AfxMessageBox( strMsg );
}
else
{
char* pCur = result;
int length;
if ( *pCur == isc_info_sql_records )
{
pCur++;
length = isc_vax_integer(pCur, 2);
pCur += 2;

while(*pCur != 1)
{
switch(*pCur)
{
case isc_info_req_select_count:
pCur++;
length = isc_vax_integer(pCur, 2);
pCur += 2;
sel_count = isc_vax_integer(pCur, length);
pCur += length;
break;

case isc_info_req_insert_count:
pCur++;
length = isc_vax_integer(pCur, 2);
pCur += 2;
ins_count = isc_vax_integer(pCur, length);
pCur += length;
break;

case isc_info_req_update_count:
pCur++;
length = isc_vax_integer(pCur, 2);
pCur += 2;
upd_count = isc_vax_integer(pCur, length);
pCur += length;
break;

case isc_info_req_delete_count:
pCur++;
length = isc_vax_integer(pCur, 2);
pCur += 2;
del_count = isc_vax_integer(pCur, length);
pCur += length;
break;

default:
pCur++;
break;
}
}

CString strMsg;
strMsg.Format( _T("%d Row(s) Updated"), upd_count );
AfxMessageBox( strMsg );
}
}






isc_info_sql_records 파라메터를 이용하여 isc_dsql_sql_info() 함수를 수행 한 후의 Request Buffer 내용


Result buffer for DELETE statement contains:
23, 29,0, (isc_info_sql_records, length=29)
15, 4,0, 0,0,0,0, (isc_info_req_update_count, 0 rows updated)
16, 4,0, 4,0,0,0, (isc_info_req_delete_count, 4 rows deleted)
13, 4,0, 4,0,0,0, (isc_info_req_select_count, 4 rows selected)
14, 4,0, 0,0,0,0, (isc_info_req_insert_count)
1, (isc_info_end)

Result buffer for UPDATE statement contains:
23, 29,0,
15, 4,0, 4,0,0,0,
16, 4,0, 0,0,0,0,
13, 4,0, 4,0,0,0,
14, 4,0, 0,0,0,0,
1,

Result buffer for INSERT statement contains:
23, 29,0,
15, 4,0, 0,0,0,0,
16, 4,0, 0,0,0,0,
13, 4,0, 0,0,0,0,
14, 4,0, 1,0,0,0,
1,







isc_dsql_sql_info() 함수에 isc_info_sql_records 파라메터를 이용하여 데이터베이스에서 반영 된 레코드 수를 가져올 수 있는데 반영된 수가 누적되고 있다. 이에 대한 내용은 좀 더 분석을 해 보아야겠다. Firebird C API 의 경우 관련 자료가 많지 않아서 분석이 쉽지가 않다.





자료 출처


Firebird C API 간단 사용기

C API를 이용한 Firebird embedded 를 간단하게 사용하는 예이다. 질의문의 결과난 파라메터를 이용한 방법은 XSQLDA(eXtended SQL Descriptor Area)를 이해한 후에 정리를 해야 할 것 같다.





ClearResult();
AppendResult( _T("Try to attach database!!") );
isc_db_handle db = 0L; /* database handle */
isc_tr_handle trans = NULL; /* transaction handle */
isc_stmt_handle stmt = NULL; /* statement handle */

char szDBName[ MAX_PATH ] = "E:\TEST.FDB";
ISC_STATUS_ARRAY status;
ISC_LONG sqlcode;

// Database Parameter Block (DPB) 준비
std::string strDPB;

strDPB.append( 1, isc_dpb_version1 ); // DPB 버전
strDPB.append( 1, isc_dpb_user_name ); // User Account
strDPB.append( 1, (char)strlen("sysdba") );
strDPB.append( "sysdba" );
strDPB.append( 1, isc_dpb_password ); // Password
strDPB.append( 1, (char)strlen("masterkey") );
strDPB.append( "masterkey" );

// Database connect
if ( isc_attach_database( status, 0, szDBName, &db, (short)strDPB.length(), strDPB.c_str() ) )
{
AppendResult( _T("Fail to attach database!!") );

return;
}

// Start Transaction
isc_start_transaction( status, &trans, 1, &db, 0, NULL );

// Execute query
char szQuery[1024];

// Create Table
sprintf_s( szQuery, 1024,
"CREATE TABLE employee ("
" name VARCHAR(20) "
", birth INTEGER"
", enter TIMESTAMP"
")");

isc_dsql_execute_immediate( status, &db, &trans, strlen(szQuery), szQuery, 1, NULL );
isc_commit_transaction( status, &trans );

if ( status[0] == 1 && status[ 1 ] > 0 )
{
// Error occurred
sqlcode = isc_sqlcode( status );

char szMsg[512];
isc_sql_interprete( (short)sqlcode, szMsg, 512 );

CString strMsg;
strMsg.Format( _T("Fail to Create Table : %d - %s"), sqlcode, CString( szMsg ) );
AppendResult( strMsg );
}
else
{
AppendResult( _T("Table Creaded.") );
}

// Insert Data
isc_start_transaction( status, &trans, 1, &db, 0, NULL );
AppendResult( _T("Insertion!!") );
for ( int i = 0; i < 5; ++i )
{
sprintf_s( szQuery, 1024,
"INSERT INTO employee ( name, birth, enter ) VALUES ( 'name%d', %d, CURRENT_TIMESTAMP )"
, i, 20 + i
);

isc_dsql_execute_immediate( status, &db, &trans, strlen(szQuery), szQuery, 1, NULL );

if ( status[0] == 1 && status[ 1 ] > 0 )
{
// Error occurred
sqlcode = isc_sqlcode( status );

char szMsg[512];
isc_sql_interprete( (short)sqlcode, szMsg, 512 );

CString strMsg;
strMsg.Format( _T("Fail to Insert : %d - %s"), sqlcode, CString( szMsg ) );
AppendResult( strMsg );
}
else
{
AppendResult( _T("1 Row Inserted.") );
}
}

// Update Data
// Statement allocation
isc_dsql_allocate_statement( status, &db, &stmt );

AppendResult( _T("Update!!") );
sprintf_s( szQuery, 1024, "UPDATE employee SET birth = birth + 2 WHERE birth > 22");

isc_dsql_prepare( status, &trans, &stmt, 0, szQuery, 0, NULL );

isc_dsql_execute( status, &trans, &stmt, 0, NULL );
isc_commit_transaction( status, &trans );

if ( status[ 0 ] == 1 && status[ 1 ] > 0 )
{
// Error occurred
sqlcode = isc_sqlcode( status );

char szMsg[512];
isc_sql_interprete( (short)sqlcode, szMsg, 512 );

CString strMsg;
strMsg.Format( _T("Fail to Update : %d - %s"), sqlcode, CString( szMsg ) );
AppendResult( strMsg );
}
else
{
AppendResult( _T("Table Updated") );
}

isc_dsql_free_statement( status, &stmt, DSQL_close );

// Delete Table
AppendResult( _T("Drop Table!!") );
sprintf_s( szQuery, 1024, "DROP TABLE employee");

isc_dsql_execute_immediate( status, &db, &trans, strlen(szQuery), szQuery, 1, NULL );

// Commit Transaction
isc_commit_transaction( status, &trans );

// Database disconnect
isc_detach_database( status, &db );

AppendResult( _T("Database detached!!") );
AppendResult( _T("Finished!!") );
<

Original Post : http://neodreamer-dev.tistory.com/479

2010/11/01

Firebird C API 로 Firebird Embedded 사용하기

Firebird Embedded 패키기에서 아래 파일을 프로젝트 폴더에 복사를 한다.



  • fbembed.dll

  • firebird.conf

  • firebird.msg

  • ib_util.dll

  • icudt30.dll

  • icuin30.dll

  • icuuc30.dll


fbembed.dll 을 fbclient.dll 로 이름을 바꾸고 일반적인 Firebird 를 사용하듯 하면 된다.






아래 코드는 테스트를 위한 코드이다.




isc_db_handle        db = NULL;        /* database handle */
isc_tr_handle trans = NULL; /* transaction handle */
ISC_STATUS_ARRAY status; /* status vector */
long sqlcode; /* SQLCODE */

char *szDBName = "e:\ est.fdb";

// 데이터베이스 생성 DDL
std::string strQuery = "CREATE DATABASE 'e:\ est.fdb' USER 'sysdba' PASSWORD 'masterkey';";

// 데이터베이스 생성 시도
isc_dsql_execute_immediate(status, &db, &trans, 0, strQuery.c_str(), 1, NULL);

if ( status[0] == 1 && status[1] > 0 )
{
sqlcode = isc_sqlcode(status);

char szMsg[512];
isc_sql_interprete( (short)sqlcode, szMsg, 512 );
char szMsg2[512];
ISC_STATUS* pStatus = status;
isc_interprete( szMsg2, &pStatus );
TRACE( "Fail to create database : %d - %s (%s)\n", sqlcode, szMsg, szMsg2 );

if ( sqlcode == -902 )
{
TRACE( "Database exists!!\n" );
}
else
{
return;
}
}
else
{
TRACE( "Database created!!!\n" );
}

isc_detach_database( status, &db );

char *dpb_buffer = 0; // Database Parameter Buffer
short dpb_length = 0;

// Set parameter User Name and Password
/*
isc_expand_dpb( &dpb_buffer, &dpb_length
, isc_dpb_num_buffers, 80
, isc_dpb_user_name, "sysdba"
, isc_dpb_password, "masterkey"
, isc_dpb_connect_timeout, 180
);
//*/

// Database Parameter Block (DPB) 준비
std::string strDPB;

strDPB.append( 1, isc_dpb_version1 ); // DPB 버전
strDPB.append( 1, isc_dpb_user_name ); // User Account
strDPB.append( 1, (char)strlen("sysdba") );
strDPB.append( "sysdba" );
strDPB.append( 1, isc_dpb_password ); // Password
strDPB.append( 1, (char)strlen("masterkey") );
strDPB.append( "masterkey" );
strDPB.append( 1, isc_dpb_num_buffers );
strDPB.append( 1, (char)1 );
strDPB.append( 1, (char)90 );
strDPB.append( 1, isc_dpb_connect_timeout );
strDPB.append( 1, (char)4 );
strDPB.append( 1, (char)180 );
strDPB.append( 1, (char)(180 >> 8) );
strDPB.append( 1, (char)(180 >> 16) );
strDPB.append( 1, (char)(180 >> 24) );

int nParam = (int)strDPB.length();

// 데이터베이스 연결
//isc_attach_database( status, (int)strlen( szDBName ), szDBName, &db, dpb_length, dpb_buffer );
isc_attach_database( status, (int)strlen( szDBName ), szDBName, &db,
(short)strDPB.length(), strDPB.c_str() );

if ( status[0] == 1 && status[1] > 0 )
{
// Error occurred
sqlcode = isc_sqlcode( status );

char szMsg[512];
isc_sql_interprete( (short)sqlcode, szMsg, 512 );
TRACE( "Fail to connect Database : %d - %s\n", sqlcode, szMsg );
return;
}
else
{
TRACE( "Database connected!!\n" );
}

isc_start_transaction( status, &trans, 1, &db, 0, NULL );

// 테이블 생성
isc_dsql_execute_immediate( status, &db, &trans, 0,
"CREATE TABLE member ( name VARCHAR(20), age INTEGER )", 1, NULL );

if ( status[0] == 1 && status[1] > 0 )
{
// Error occurred
sqlcode = isc_sqlcode(status);

char szMsg[512];
isc_sql_interprete( (short)sqlcode, szMsg, 512 );
TRACE( "Fail to Create table : %d - %s\n", sqlcode, szMsg );

isc_rollback_transaction( status, &trans );

// Release parameter buffer
isc_free( dpb_buffer );

isc_detach_database( status, &db );

return;
}
else
{
TRACE( "Table created!!\n" );
}

isc_commit_transaction( status, &trans );

// Release parameter buffer
isc_free( dpb_buffer );

isc_detach_database( status, &db );
<

Original Post : http://neodreamer-dev.tistory.com/474

2010/10/05

Firebird Windows에 수동으로 설치하기

우선 운영체제에 맞는 설치 파일을 선택한다. 32비트는 Firebird-2.5.0.26074-0_Win32.zip 를 64비트는 Firebird-2.5.0.26074-0_x64.zip 를 설치하고자 하는 경로에 압축을 풀어놓는다. (Download Site)






여기서는 F:\Firebird64 경로에 압축을 풀고 작업을 했다.






우선 bin 폴더에 있는 install_super.bat 를 실행하여 서비스를 등록한다.






이제 시스템의 서비스 목록을 확인해 보면 Firebird Guardian 과 Firebird Server 가 등록되어 있음을 확인 할 수 있다.






사실 이것 만으로 설치는 끝난것인데 항상 Firebird 를 운영할 일이 없는 개인 PC 에서 서비스 형태로 돌리는 것이 맘이 들지 않아 Application 형태로 필요할 때에 운영을 하려 한다.






우선 F:\Firebird64\system32 폴더에 있는 Firebird2Control.cpl 를 윈도우의 System 폴더(C:\Windows\System32)에 복사를 한다. 복사를 하고 시작 메뉴의 제어판을 보면 Firebird Server Manager 가 등록 된다.






Firebird Server Manager를 실행하면 Firebird Server Control 이 실행 된다.






Firebird Server Control 에서 현재 운영중이라면 서버를 중지시키고 운영 형태(Run)를 Application 으로  시작(Start)를 Manually로 설정하고 Apply 를 누르고 시작을 한다.






그러면 시스템의 서비스 목록에 등록되었던 두 개의 서비스(Firebird Guardian, Firebird Server)가 사라지고 Firebird 는 Application 형태로 운영이 된다. 시스템의 프로세스 목록을 보면 두개의 프로세스가 동작중인 것을 확인 할 수 있다.





<

Original Post : http://neodreamer-dev.tistory.com/464

2010/10/04

2009/12/02

Firebird C API 데이터베이스 연결하기

char *szDBName = "e:\test.fdb";

char szSQL[2048] = {0,};
isc_db_handle db = NULL; // database handle
isc_tr_handle trans = NULL; // transaction handle
ISC_STATUS_ARRAY status; // status vector
long sqlcode; // SQLCODE
char *dpb_buffer = 0; // Database Parameter Buffer
short dpb_length = 0;

// Prepare parameter buffer
dpb_buffer = (char *)malloc(1);
*dpb_buffer = isc_dpb_version1;
dpb_length = 1;

// Set parameter User Name and Password
isc_expand_dpb( &dpb_buffer, &dpb_length
, isc_dpb_user_name, "SYSDBA"
, isc_dpb_password, "masterkey"
);

// Connect database
isc_attach_database( status, (int)strlen( szDBName ), szDBName, &db, dpb_length, dpb_buffer );

sqlcode = isc_sqlcode( status );
if ( status[0] == 1 && status[1] )
{
// Error occured
TRACE( "Fail to connect Database : %d\n", sqlcode );
return;
}

// Disconnect database
isc_detach_database( status, &db );

// Release parameter buffer
isc_free( dpb_buffer );


+ 2009/12/06
위의 코드는 메모리 1byte 의 메모리 누수가 생긴다. 누수가 발생하는 부분은 12번째 줄의 parameter buffer 에 버퍼 버전을 할당하는 부분으로 이부분을 주석처리하면 메모리 누수가 발생하지 않고 동작을 하게 된다. 버전을 명시하지 않아도 문제가 되는지 그리고 버전을 명시하고서도 메모리 누수가 발생하지 않도록 하는 방법이 있는지는 확인을 해 보아야 겠다

Original Post : http://neodreamer-dev.tistory.com/342

2009/12/01

Firebird C API를 이용하여 데이터베이스 생성하기


isc_db_handle db = NULL; /* database handle */
isc_tr_handle trans = NULL; /* transaction handle */
ISC_STATUS_ARRAY status; /* status vector */
long sqlcode; /* SQLCODE */

char *szSQL = "CREATE DATABASE 'e:\\ew.fdb' USER 'sysdba' PASSWORD 'masterkey';";

if ( isc_dsql_execute_immediate(status, &db, &trans, 0, szSQL, 1, NULL) )
{
sqlcode = isc_sqlcode(status);

TRACE( "Fail to create database : %d\n", sqlcode );
}
else
{
TRACE( "Database created!!!\n" );
}

Original Post : http://neodreamer-dev.tistory.com/341

2009/11/30

Firebird isql을 이용한 데이터베이스 생성하기(Windows)

Firebird 의 Interactive SQL Tool 인 isql 을 이용하여 데이터베이스를 생성하는 방법이다.

일단 Firebird를 설치하고 isql을 실행시켜 데이터베이스 생성 스크립트를 실행을 하면 아래와 같은 에러 메세지를 보게 된다.

C:\Program Files\Firebird\Firebird_2_1\bin>isql
Use CONNECT or CREATE DATABASE to specify a database
SQL> create database 'e: est.fdb';
Statement failed, SQLCODE = -902
Your user name and password are not defined. Ask your database administrator to
set up a Firebird login.


이 메세지는 사용자 이름과 암호를 설정하지 않아서 발생하는 에러이다. 사용자 이름과 암호를 설정하는 방법은 몇가지가 있다. 그중에서 환경 설정에 지정하는 방법과 isql 을 실행할 때 사용자 이름과 암호를 명시하는 방법이 있다.

우선 전자의 경우 도스 명령어의 Set 명령을 이용하여 사용자 이름과 암호를 지정하고 isql을 실행하여 데이터베이스를 생성하는 방법이다.

C:\Program Files\Firebird\Firebird_2_1\bin>SET ISC_USER=sysdba

C:\Program Files\Firebird\Firebird_2_1\bin>SET ISC_PASSWORD=masterkey

C:\Program Files\Firebird\Firebird_2_1\bin>isql
Use CONNECT or CREATE DATABASE to specify a database
SQL> create database 'e: est.fdb';
SQL>


두 번째로 isql 실행시 사용자 이름과 암호를 지정하는 방법이다.

C:\Program Files\Firebird\Firebird_2_1\bin>isql -user sysdba -password masterkey

Use CONNECT or CREATE DATABASE to specify a database
SQL> create database 'e: est1.fdb';
SQL>

Original Post : http://neodreamer-dev.tistory.com/340