DATABASE에 연결 방법 정리
하도 오래 간만에 하려고 하니, 했던 방법을 다 잊어버려 개고생...하다. 나중에 같은 일이 발생할까봐 정리하게 되었습니다.
잠깐, 삼천포로 빠지겠습니다.
pvbrowser는 Qt를 이용하여 만들어진 프로그램입니다. 즉, Qt에 있는 모듈을 모두 사용할 수 있습니다. Qt에서 기본적으로 지원하는 QtSql 모듈은 플랫폼(OS), DATABASE의 종류에 무관하게 사용할 수 있을 뿐 아니라. Qt의 모델/뷰(Model/View) 구조를 지원합니다.
아직 저도 Model/View 개념은 혼동이 있는 상태지만, 익숙해지면 쉬워지겠죠.
Qt에서 Database와 관련된 모듈들을 한번 살펴보면
- QSqlDatabase
- QSqlQuery
- QSqlTableModel
- QSqlRelationalTableModel
- ...
여하튼 많이 있습니다. 이번에는 데이터베이스를 연결하고, 테스트하는 것이 목적이므로 QSqlDatabase, QSqlQuery가 주 관심사이며, pvbrowser에서 어떻게 코딩하여야 하는지 알아보죠.
오늘 하는 내용은 "pvaddon\templates\qtDatabase" 에 있는 내용을 쉽게 풀어 쓴 것이라고 생각해 주시기 바랍니다. pvaddon 패키지는 pvbrwoser 홈페이지에서 다운로드 받으시기 바랍니다. 아니면
GitHub에서 검색하셔도 됩니다. 여하튼, 이 패키지에 있는 qtdatabase.h, qtdatabase.cpp 파일이 필요합니다.
먼저 Qt의 SQL을 모듈을 사용할 수 있게 project 파일을 수정하여야 합니다.
새로 만든 프로젝트 파일의 기본 내용입니다.
아래와 같이 수정해 주시기 바랍니다.
pvbrowser 프로젝트를 생성하면 기본적으로 Qt 관련 내용을 사용하지 않는 것으로 설정되어 있습니다. 하지만 Qt에서 지원하는 SQL 관련 모듈을 사용하기 위해서는 위와 같이 수정해 주셔야 합니다.
두번째로 pvaddon 에 있는 qtdatabase 코드를 사용하도록 설정하겠습니다.
사용하기 전에 한번 qtdatabase 헤더파일을 살펴보죠.
qsqldatabase, qsqlrecord,qsqlfield, qsqlquery, qsqlerror 를 이용하여 qtDatabase 객체를 만들었고, 다음과 같은 함수들을 지원해주는 군요.
- open()
- close()
- query()
- populateTable()
- recordFieldValue()
- nextRecord()
오늘은 qtDatabase 객체에서 지원하는 이 함수들을 이용하여 MariaDB에 접속하고자 합니다
만들어준 pvbrowser 프로젝트 폴더에, 이 함수들을 이용할 수 있게 설정한 후, 사용하고자하는 mask에서 extern 명령을 이용하면 됩니다.(글이 많이 꼬여 있네요...) 여하튼 다음과 같은 코드를 프로젝트 파일에 넣어 주시기 바랍니다.
수정된 프로젝트 코드입니다.
코드를 수정하신 후 다운받은 qtdatabase.h, qtdatabase.cpp를 프로젝트 폴더에 복사하여 주십시오. 만약 위치가 틀릴 경우 HEADERS, SOURCES 에 경로를 함께 적어 주셔야 합니다.
저는 그냥 복사하여 사용하였습니다.
이 단계까지 수정한 후 컴파일 해 보았습니다.
|
그림 1. 컴파일 화면 |
별로 특이한 것이 없는 것 같은데... 여하튼 넘어가죠.
프로젝트 파일에 필요한 수정은 다 끝난 상태입니다. 두가지만 기억하죠.
qtsql 모듈을 사용하도록 설정해야한다는 것과
외부 파일(qtdatabase Header & Source)의 경로를 설정한다는 것.
Mask에 database관련 코드를 직접 코딩할 경우 외부파일이 필요 없습니다. 하지만 그러지 않아도 복잡한 Mask 파일에 부하를 감소시키는 방법이 있으면 활용하는 것이 좋겠죠.
다음은 Main() 함수에서 DATABASE와 연결해 보겠습니다.
Main() 함수에서 qtDatabase 객체를 사용하기 위해 다음과 같이 정의해 주십시오.
Main()함수에 qtDatabase 클래스를 사용하려면 pvapp.h에 다음과 같이 입력해 주셔야 합니다.
컴파일해볼까요.
|
그림 2. 컴파일 화면 |
아직까지는 에러가 발생하지 않고 있네요. 만약 "qtDatabase does not name a type" 에러가 발생하면 pvapp.h 파일에서 qtdatabase.h 파일을 include 하지 않아서 입니다. 주의하시기 바랍니다.
자, SQL 관련 기본 준비는 끝난 것 같군요. 데이터베이스에 접속해 보겠습니다.
데이터베이스 접속코드는 일반적으로 Main() 함수에 넣어줍니다. 그래야 다른 mask에서도 사용할 수 있으니까.
만약, INETD를 사용하는 경우(LINUX,.. 계열)에는 #ifdef USE_INETD 밑에 있는 main()함수에, 윈도우 계열에서는 #else 밑에 있는 main()함수에 다음과 같은 코드를 넣어 주십시오.
qtDatabase class 정의된 open() 함수를 이용하여 "192.168.0.***"에 설치된MariaDB에 MySQL 커넥터를 이용하여 접속하고 있습니다.
open() 함수의 인자는 다음과 같습니다.
- DBType
QMYSQL, QOCI, QODBC, QSQLITE,...
- Hostname
SQL server
- User
- Pass
db.open()이 정상적으로 수행되는 경우ret = 0, 에러가 발생하면 -1 값을 반환합니다. 물론 정상적으로 수행되어야 db 객체가 생성됩니다.
컴파일 해보죠
|
그림3. 컴파일 화면 |
Make를 이용하여 컴파일 한 결과 입니다. 정상적으로 되고 있습니다.
그럼 pvbrowser에서 테스트하기 위해 서버를 시작해 볼까요. Action->Start Server를 눌러 주십시오.
|
그림 4. 서버 실행 화면 |
화면 하단부에 보면 다음과 같은 문구가 나타나내요.
우선 "db.open ret = -1 " DATABASE 를 열지(연결)하지 못했다는 메시지가 나오네요.
이것은 위에 있는 메시지를 보면 해결방법이 나옵니다.
"QMYSQL driver not load" 즉, 드라이버가 설치되어 있지 않기 때문입니다. 이 문제는
Database Connector를 설치하면 해결됩니다.
각 DB마다 필요한 connector를 설치해야합니다. 저의 경우 mysql connector for C/C++을 설치하여야 이 문제가 해결되죠.
그럼 connector는 어떻게 설치하죠. 두가지 방법이 있습니다.
- DB 서버 구축
|
그림 5.MariaDB lib폴더 |
MariaDB가 설치된 위치에 있는 lib 폴더에 보면 libmysql.dll이 설치되어 있습니다.
- DB connector 단독 설치
홈페이지에서 connector 설치프로그램 다운로드 및 설치
MySQL Database도 동일하다고 생각하시면 됩니다.
여하튼 libmysql.dll 라이브러리가 필요합니다. 이 파일을 현재 프로젝트 폴더에 넣어주시거나, pvb가 설치된 디렉토리 하위에 있는 다음의 디렉토리에 복사해 넣어주십시오.
pvb\win-mingw\bin
Action->start server를 눌러 서버를 실행해 보죠
|
그림 6. 서버 실행 화면 |
"QMYSQL driver not load" 메시지가 사라지고 "db.open ret=0" 이라는 메시지가 출력되었네요.
서버에 정상 접속되었습니다.
만약 이 단계에서도 ret=-1이 나타나면 db 서버 상태, 사용자/PASSWORD, DB Connector 지원 방식을 다시 확인해 보시기 바랍니다.
기본적으로 qt를 사용한다면(CONFIG += qt) qt 관련 이벤트를 처리하기 위한 모듈을 로딩하는 것이 필요합니다. "QSqlDatabase: an instance of QCoreApplication is required for loading driver plugins" 이 메시지와 연관이 있는 것 같습니다. 무시해도 사용은 되지만, 잘 모릅니다. 찜찜하죠. 그래서 다음과 같은 것을 넣어 주죠.
#include <QCoreApplication>
QtGUI 를 사용하지 않는 프로그램에서 Qt 이벤트 처리를 지원해주는 것입니다. 위치는 main.cpp에 넣어주시기 바랍니다.
여기까지 하면 qtDatabase 객체인 db가 생성된 것입니다. 이제 이 객체를 이용하면 되죠.
qtdatabase.h 에 정의 되어 있는 query()와 populateTable()를 사용해 보겠습니다.
테스트용으로 아래와 같은 GUI를 하나 만들었습니다.
|
그림 7. 기본 GUI 화면 |
사용하는 mask에 다음의 내용을 입력해 주십시오.
설명을 하지 않았는데, db접속시 multi thread 개념을 사용하여야 합니다. DATABASE는 혼자가 아닌 여러 프로그램들이 사용하므로...
여하튼 rlMutex를 이용해야 하므로 이 객체가 정의되어 있는 rlthread.h를 사용할 수 있게 하여야 합니다. 헤더와 메인 프로그램에 다음과 같이 넣어 주십시오.
>> 헤더 프로그램
>>Main 프로그램
테이블 위젯에 DB 에서 읽어들인 데이터를 표시하기 위해 다음과 같은 코드를 사용하였습니다. pvaddon에 있는 예제를 인용했습니다.
Database 쿼리 관련 작업은 간단할 수도 있지마, 많은 데이터를 처리하는 경우 시간이 소요되는 작업이기 때문에 mutex 방식으로 데이터를 보호하고 있습니다.
sql 명령어 쿼리는 db.query() 함수를 이용하는 군요. 이 함수 내부를 살펴보면 db->exec() 함수를 이용합니다. Qt에서 SQL 명령을 보내기 위한 것과 동일한 함수를 사용하는 것을 알 수 있습니다.
저는 query() 함수에 DB 서버의 arduino 테이블에서 데이터를 몽땅 가져오라는 명령을 주었습니다. 정상적으로 명령이 수행되면 qtDatabase 객체에 정의된 result 변수에 (QVariant)형식의 데이터가 입력됩니다. 쿼리 수행결과에 에러가 발생하면 pvbrowser status에 다음과 같이 에러를 표시해 줍니다.
|
그림 8. Query 실행 에러 표시 |
그림 9는 Query가 정상적으로 처리되었을 때 나타난 화면입니다.
|
그림 9. Query 정상 처리 |
Arduino라는 테이블만 만들어 놓고, 데이터를 입력하지 않았기 때문에 이런식으로 나타나는 군요. Arduino 테이블의 column들이 제대로 표시되고 있습니다.
Database에 연결되었으면 데이터를 넣어보죠.
Database에 데이터를 입력하기 위한 INSERT 버튼과, DB를 다시 읽어 들이기 위한 RELOAD 버튼을 만들었습니다.
RELOAD 버튼 관련 함수는 지난번 것을 그대로 이용하면 되므로 패스...
INSERT 버튼 관련 함수는 다음과 같이 만들었습니다.
똑같죠. 단지 db.query() 함수에 들어가는 것이 다르네요.
insert into Arduino (data00, data01, data02) values (10, 20, 30);
테이블에 데이터를 입력하기 위한 SQL 구문을 그대로 넣으면 됩니다.
|
그림 10. 실행화면 |
pvbrowser 실행화면입니다. 데이터가 잘 들어가네요.