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/12/09

SQLite Release 3.7.4.0 (정적/동적 라이브러리 포함)

SQLite 가 버전업이 되었다. 3.7.2 버전 미만을 사용하고 있을경우 업그레이드를 권장하고 있다.




SQLite Release 3.7.4 On 2010 December 08 (3.7.4)


  • Added the sqlite3_blob_reopen() interface to allow an existing sqlite3_blob object to be rebound to a new row.

  • Use the new sqlite3_blob_reopen() interface to improve the performance of FTS.

  • VFSes that do not support shared memory are allowed to access WAL databases if PRAGMA locking_mode is set to EXCLUSIVE.

  • Enhancements to EXPLAIN QUERY PLAN.

  • Added the sqlite3_stmt_readonly() interface.

  • Added PRAGMA checkpoint_fullfsync.

  • Added the SQLITE_FCNTL_FILE_POINTER option to sqlite3_file_control().

  • Added support for FTS4 and enhancements to the FTS matchinfo() function.

  • Added the test_superlock.c module which provides example code for obtaining an exclusive lock to a rollback or WAL database.

  • Added the test_multiplex.c module which provides an example VFS that provides multiplexing (sharding) of a DB, splitting it over multiple files of fixed size.

  • A very obscure bug associated with the or optimization was fixed.





이번 버전 역시 정적 라이브러리 컴파일 시도 할 때 sqlite3rtree.h 파일이 없어 sqlite-src-3070400.zip\sqlite-src-3070400\ext\rtree\ 에 포함되어 있던 파일을 이용하였다.




SQLite Homepage




2010/12/08

Windows Server 2008 의 암호 복잡성 만족 기능 해제 하기

R2 버전부터 기본으로 적용되어 있는 것으로 보이는데 Server 2008 에서는 계정에 대한 암호를 설정할 때 정해진 복잡성을 만족해야만 되도록 설정되어 있다.



이 기능은 로컬 그룹 정책 편집기에서 해제할 수 있다.




로컬 그룹 정책 편집기(gpedit.msc) 를 실행하고 "로컬 컴퓨터 정책 -> 컴퓨터 구성 -> Windows 설정 -> 보안설정 -> 계정 정책 -> 보안 정책" 의 "암호는 복잡성을 만족해야 함" 항목을 "사용 안 함"으로 설정 하면 된다.



2010/12/01

Virtual Box 의 Ubuntu 해상도 설정하기

Virtual Box 에 설치한 Ubuntu 의 해상도를 windows 처럼 창크기 변경에 따른 해상도 변경하기.



Ubuntu 9.x

게스트 확장 설치후 /etc/X11/xorg.conf 파일의 Device 섹션에 Driver “vboxvideo” 추가


Section "Device"

Identifier "Configured Video Device"

Driver "vboxvideo"

EndSection




Ubuntu 10.x

sudo apt-get install virtualbox-ose-guest-x11<

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