古い仕様のMT4が使えなくなってしまったので、新しい仕様に対応したSLQLite3用のヘッダーファイルを作成しました。
(※warapperDLL未使用)
はじめに
新しいMT4のエンコードを調べてみたら以下の通りとなりまいた。
- MetaEditorが新規に作成するmq4,mqhは、ANSI(Shift_JIS)
- UNICODE(UTF-16BOM)で作成したmq4.mqhでもコンパイル出来た。
- 内部は、UNICODE(UTF-16BOM)
- logファイルは、ANSI(Shift_JIS)
※毎回ではないが、UNICODE(UTF-16BOM)で作成したファイルをMetaEditorで加工すると文字化けが発生しました。
流れとしては、mq4(ANSI or UNICODE)→MT4(UNICODE)→SQLite3(UTF-8)→MT4(UNICODE)→output(ANSI)となります。
また、MQL5フォームに『
SQL and MQL5: Working with SQLite Database』という記事があったのですが、使用することができませんでした。そのため、この記事を参考にコンパクトな物を作ることにしました。
コード
ココから
DLすることが出来ます。(sqlite3.mqh test.mq4 sqlite3.dll )
#define PTR int
#define sqlite3_stmt PTR
#define sqlite3 PTR
#define PTRPTR PTR
#define SQLITE_OK 0 #define SQLITE_ERROR 1 #define SQLITE_INTERNAL 2 #define SQLITE_PERM 3 #define SQLITE_ABORT 4 #define SQLITE_BUSY 5 #define SQLITE_LOCKED 6 #define SQLITE_NOMEM 7 #define SQLITE_READONLY 8 #define SQLITE_INTERRUPT 9 #define SQLITE_IOERR 10 #define SQLITE_CORRUPT 11 #define SQLITE_NOTFOUND 12 #define SQLITE_FULL 13 #define SQLITE_CANTOPEN 14 #define SQLITE_PROTOCOL 15 #define SQLITE_EMPTY 16 #define SQLITE_SCHEMA 17 #define SQLITE_TOOBIG 18 #define SQLITE_CONSTRAINT 19 #define SQLITE_MISMATCH 20 #define SQLITE_MISUSE 21 #define SQLITE_NOLFS 22 #define SQLITE_AUTH 23 #define SQLITE_ROW 100 #define SQLITE_DONE 101 #import "sqlite3.dll"
int sqlite3_open16(string filename,sqlite3 &paDb);
int sqlite3_close(sqlite3 aDb);
int sqlite3_prepare16_v2(sqlite3 aDb,string sql,int nByte,sqlite3_stmt &pStmt,PTRPTR pzTail);
int sqlite3_exec(sqlite3 aDb,const char &sql[],PTR acallback,PTR apvoid,PTRPTR errmsg);
int sqlite3_step(sqlite3_stmt apstmt);
int sqlite3_finalize(sqlite3_stmt apstmt);
int sqlite3_reset(sqlite3_stmt apstmt);
int sqlite3_errcode(sqlite3 db);
int sqlite3_extended_errcode(sqlite3 db);
const string sqlite3_errmsg16(sqlite3 db);
int sqlite3_bind_null(sqlite3_stmt apstmt,int icol);
int sqlite3_bind_int(sqlite3_stmt apstmt,int icol,int a);
int sqlite3_bind_int64(sqlite3_stmt apstmt,int icol,long a);
int sqlite3_bind_double(sqlite3_stmt apstmt,int icol,double a);
int sqlite3_bind_text16(sqlite3_stmt apstmt,int icol,string a,int len,PTRPTR destr);
const PTR sqlite3_column_name(sqlite3_stmt apstmt,int icol);
int sqlite3_column_count(sqlite3_stmt apstmt);
int sqlite3_column_type(sqlite3_stmt apstmt,int acol);
int sqlite3_column_bytes(sqlite3_stmt apstmt,int acol);
int sqlite3_column_int(sqlite3_stmt apstmt,int acol);
long sqlite3_column_int64(sqlite3_stmt apstmt,int acol);
double sqlite3_column_double(sqlite3_stmt apstmt,int acol);
string sqlite3_column_text16(sqlite3_stmt apstmt, int acol);
const PTR sqlite3_column_blob(sqlite3_stmt apstmt,int acol);
#import
class CSQLite3{
public:
sqlite3 sdb;
sqlite3_stmt stmt;
CSQLite3(){};
CSQLite3(string file_name);
~CSQLite3(){if(stmt){finalize(); sqlite3_close (sdb);}};
void db_set(string file_name); int reset(); int finalize(); void db_close(){sqlite3_close (sdb);}
int execute(string sql); int prepare(string sql); int col_count(); bool next_row(); int bind_text(int col,string txt); int bind_int(int col,int integer); int bind_double(int col, double dbl); int get_int(int col); double get_double(int col); string get_text(int col); void errmsg(); };
CSQLite3::CSQLite3(string file_name){
if(file_name != "")db_set(file_name);
}
void CSQLite3::db_set(string file_name){
int res = sqlite3_open16 (file_name, sdb);
if (res != SQLITE_OK) errmsg();
}
int CSQLite3::reset(){
int ret = 0;
if(stmt)ret = sqlite3_reset(stmt);
return(ret);
}
int CSQLite3::finalize(){
int ret = 0;
if(stmt){
ret = sqlite3_finalize (stmt);
stmt = 0;
}
return(ret);
}
int CSQLite3::execute(string sql){
int sq,res;
uchar qr[];
sq = StringToCharArray(sql,qr);
ArrayResize(qr,sq);
if(stmt)reset();
res = sqlite3_exec (sdb, qr, NULL, NULL, NULL);
return(res);
}
int CSQLite3::prepare(string sql){
int res;
if(stmt)finalize();
res = sqlite3_prepare16_v2(sdb, sql,StringLen(sql)*2 , stmt, NULL);
return(res);
}
int CSQLite3::col_count(){
return(sqlite3_column_count (stmt));
}
bool CSQLite3::next_row (){
if(!stmt)return(false);
int ret = 0;
ret = sqlite3_step (stmt);
return (ret == SQLITE_ROW ? true : false);
}
int CSQLite3::bind_text(int col,string txt){
int ret = 0;
ret = sqlite3_bind_text16(stmt,col,txt,StringLen(txt)*2,0);
return (ret);
}
int CSQLite3::bind_int(int col,int integer){
int ret = 0;
ret = sqlite3_bind_int(stmt,col,integer);
return (ret);
}
int CSQLite3::bind_double(int col, double dbl){
int ret = 0 ;
ret = sqlite3_bind_double(stmt,col,dbl);
return (ret);
}
int CSQLite3::get_int(int col){
int date = 0 ;
date = sqlite3_column_int (stmt, col);
return (date);
}
double CSQLite3::get_double(int col){
double date = 0.0;
date = sqlite3_column_double (stmt, col);
return(date);
}
string CSQLite3::get_text(int col){
string date = "";
date = sqlite3_column_text16(stmt, col);
return(date);
}
void CSQLite3::errmsg(){
Print(sqlite3_errmsg16(sdb));
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
使用例(サンプル)
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#property copyright "Copyright 2012, MetaQuotes Software Corp."
#property link "http://www.metaquotes.net"
#property show_inputs
#include <sqlite3.mqh>
input string dbns="C:\Testdb.db";int start(){
string sql = "";
int i;
CSQLite3 sqlite(dbns);
sql = "CREATE TABLE IF NOT EXISTS `Test` (`id` INTEGER, `time` TEXT, `open_price` DOUBLE)";
if(sqlite.execute(sql)!= SQLITE_OK)sqlite.errmsg();
sql = "INSERT INTO 'Test' VALUES (?,?,?)";
if(sqlite.execute("BEGIN")!=SQLITE_OK)sqlite.errmsg();
for(i=0;i<Bars;i++){
if(sqlite.prepare(sql)!=SQLITE_OK)sqlite.errmsg();
if(sqlite.bind_int(1,Bars-i)!=SQLITE_OK)sqlite.errmsg();
if(sqlite.bind_text(2,TimeToStr(Time[i]))!=SQLITE_OK)sqlite.errmsg();
if(sqlite.bind_double(3,Open[i])!=SQLITE_OK)sqlite.errmsg();
sqlite.next_row();
}
if(sqlite.execute("COMMIT")!=SQLITE_OK)sqlite.errmsg();
sqlite.finalize();
sql = "SELECT COUNT(*) FROM 'Test'";
if(sqlite.prepare(sql)!=SQLITE_OK)sqlite.errmsg();
sqlite.next_row();
Print("Bars=",IntegerToString(Bars)," データベース内のデータ数=",sqlite.get_text(0));
sqlite.finalize();
sql = "SELECT * FROM 'Test'" ;
if(sqlite.prepare(sql)!=SQLITE_OK)sqlite.errmsg();
while(sqlite.next_row()){
Print(IntegerToString(
sqlite.get_int(0))," : ",
sqlite.get_text(1)," : ",
DoubleToStr(sqlite.get_double(2),Digits));
}
sqlite.finalize();
sqlite.db_close();
return (0);
}
まとめ
mq4(ANSI or UNICODE)→MT4(UNICODE)→SQLite3(UTF-8)→MT4(UNICODE)→output(ANSI)
エンコードの統一ってできないものでしょうか(ー_ー)!!。。