日記帳
本ページはプロモーションが含まれています
カテゴリー
Links
blog(ブログ)マスター
アンドロイドの巣
ゼロから始めるベランダ菜園
タイトル
2024年11月
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30

sqlite.exe .dumpで文字化け 【& patch p2 編】

2011-12-09
sqlite.exe .dumpで文字化け 【& patch p2 編】

執筆:2011.12.09
編集:2011.12.10


概要
・sqlite.exe の dumpにHEXモードを追加する方法
・sqlite の 「dump」と「インポート」の仕方
・sqlite の構築の仕方
・php PDO sqlite versionの自動選択手法
ソースコードのダウンロード先

sqlite3に完全移行していたつもりだったのですが
今回、サーバーのDBファイルがあちこちのフォルダに散らばっているため
保存先を統一して整理した結果
version3シリーズへの移行をしていないデータがいくつかありました。

そして dumpすると ビープ音 ビ ビー。
インポートも書式エラーでできない始末。
もー、出力をエスケープしていないようです。

sqlite3に移行するのが目的なので、強引に HEXモードを加えました。
一緒に前回(昨年のパッチ1、set_table_name関数)の修正も入っています

sqlite3.exeの .dumpでは、BLOB型にしていれば、HEX出力されるようです。

とりあえず、
1個のDBを移行するのに使うだけで、
cygwinで動いて 、無事に移行できたのでよしとします。



【修正コード】
コードを使う際は、利用者の自己責任でのみご利用できます。
利用前に コードが安全かどうか、ご自分で確認をお願いします。

また、操作していたアプリケーション固有のエンコード・デコード方式があったりして、
dumpにより データが壊れる可能性がありますので、ご注意ください。
phpのデコード方式には対応したつもりですが、ご自分で確認をお願いします。

※移行した際は、旧DBと新しいDBのデータを完全照合するなどして、
  データが破損したりしていないか確認をしましょう。
※万が一のため、移行前のDBも保管しておくことをお勧めします。



ファイルは、
  こちらに置いておきます。
↓↓↓

↑↑↑

リンク切れの際は、下のコードをどうぞ。

sqlite version 2.8x.の修正
--- SQLite-47fee16ba9bd8ab2/VERSION     2007-01-09 01:20:28.000000000 +0900
+++ SQLite-47fee16ba9bd8ab2/VERSION 2011-12-09 21:58:33.703125000 +0900
@@ -1 +1 @@
-2.8.17
+2.8.17-p2
--- SQLite-47fee16ba9bd8ab2/src/shell.c 2007-01-09 01:20:28.000000000 +0900
+++ SQLite-47fee16ba9bd8ab2/src/shell.c 2011-12-10 10:50:15.031250000 +0900
@@ -82,6 +82,8 @@
*/
extern int sqliteIsNumber(const char*);

+static int dump_mode = 3; // dump of sqlite version
+
/*
** This routine reads a line of text from standard input, stores
** the text in memory obtained from malloc() and returns a pointer
@@ -220,6 +222,91 @@
static void output_quoted_string(FILE *out, const char *z){
int i;
int nSingle = 0;
+ int zlen = strlen(z);
+ int blen = 0; // add HEX mode
+ int hex_mode = 0; // add HEX mode
+ int need_decode = 0; // add HEX mode
+ int need_trim_header0 = 0; // add HEX mode
+ unsigned char *bin_buf = 0; // add HEX mode
+
+ // add HEX output mode
+// if ( dump_mode !=2 )
+ {
+ for(i=zlen-1; i>=0; i--)
+ {
+ if ( i>=1 )
+ if (
+ ( (z[i] == 1) || (z[i] == 2) || (z[i] == 0x28) )
+ &&
+ ( z[i-1] == 1 )
+ )
+ {
+//** 0x00 -> 0x01 0x01
+//** 0x01 -> 0x01 0x02
+//** 0x27 -> 0x01 0x28
+ need_decode = 1;
+ hex_mode = 1;
+ // skip i-1
+ i--;
+ continue;
+ }
+ if ( /*(z[i] >= 1) &&*/ ((unsigned char) z[i] <= 8) )
+ { // my rule
+ hex_mode = 1;
+ }
+// if ( (i != 0) && (z[i] == 1) ) { } // error ? or other rule
+ if ( (i == 0 ) && (z[i] == 1) )
+ {
+ // [0] 0x01 has no paire
+ // perhaps php encode head
+ // php/ext/sqlite/pdo_sqlite2.c : function sqlite2_handle_quoter
+ hex_mode = 1;
+ need_decode = 1;
+ need_trim_header0 = 1;
+ }
+ }
+
+ if ( hex_mode && (zlen > 0) )
+ {
+ if ( need_decode )
+ {
+ bin_buf = malloc( zlen + 1 );
+ if( bin_buf==0 )
+ {
+ fprintf(stderr,"hex_mode: out of memory!\n");
+ exit(1);
+ }
+ if ( need_trim_header0 )
+ blen = sqlite_decode_binary((unsigned char *) ( z + 1 ) , (unsigned char *) bin_buf);
+ else
+ blen = sqlite_decode_binary((unsigned char *) z , (unsigned char *) bin_buf);
+ }
+ else
+ {
+ bin_buf = (unsigned char *) z;
+ blen = zlen;
+ }
+
+ if ( blen > 0)
+ {
+ fprintf(out,"X'");
+ for(i=0; i < blen; i++)
+ {
+ fprintf(out,"%02x" , (unsigned char ) bin_buf[i]);
+ }
+ fprintf(out,"'");
+ }
+ else
+ {
+ fprintf(out,"''");
+ }
+ if ( need_decode )
+ free(bin_buf);
+ return ;
+ }
+ }
+ // end add HEX output mode
+
for(i=0; z[i]; i++){
if( z[i]=='\'' ) nSingle++;
}
@@ -415,19 +502,32 @@
int i, n;
int needQuote;
char *z;
+ char quote_char;

if( p->zDestTable ){
free(p->zDestTable);
p->zDestTable = 0;
}
if( zName==0 ) return;
- needQuote = !isalpha(*zName) && *zName!='_';
+
+ if ( dump_mode != 2 )
+ {
+ quote_char = '"';
+ needQuote = 1;
+ }
+ else
+ {
+ quote_char = '\'';
+ needQuote = !isalpha(*zName) && *zName!='_';
+ }
+
for(i=n=0; zName[i]; i++, n++){
- if( !isalnum(zName[i]) && zName[i]!='_' ){
+ if( !needQuote && !isalnum(zName[i]) && zName[i]!='_' ){
needQuote = 1;
- if( zName[i]=='\'' ) n++;
}
+ if( zName[i]==quote_char ) n++;
}
+
if( needQuote ) n += 2;
z = p->zDestTable = malloc( n+1 );
if( z==0 ){
@@ -435,12 +535,12 @@
exit(1);
}
n = 0;
- if( needQuote ) z[n++] = '\'';
+ if( needQuote ) z[n++] = quote_char;
for(i=0; zName[i]; i++){
z[n++] = zName[i];
- if( zName[i]=='\'' ) z[n++] = '\'';
+ if( zName[i]==quote_char ) z[n++] = quote_char;
}
- if( needQuote ) z[n++] = '\'';
+ if( needQuote ) z[n++] = quote_char;
z[n] = 0;
}

パッチの当てかた、ソースのルートフォルダで
patch -p1 -i SQLite-47fee16ba9bd8ab2-p2.diff.txt

【構築(ビルド、コンパイル)のメモ】
cygwin , Linux
  ./configure \
   --enable-utf8 \
   --enable-tempdb-in-ram
make
FreeBSD
  ./configure --prefix=$HOME/local/sqlite2 \
   --enable-utf8 \
   --enable-tempdb-in-ram \
   --enable-static

gmake
   
FreeBSD-mingw : need gcc + mingw package
  途中でエラー:うまく構築できないので、詳細不明。
chmod  700 ./configure
./configure --help
./configure --target=mingw32 --host=mingw32 --enable-static
gmake
  checking for a BSD-compatible install... /usr/bin/install -c
Version set to 2.8.17-p2
checking for mingw32-gcc... (cached) mingw32-gcc
checking whether we are using the GNU C compiler... (cached) yes
checking whether mingw32-gcc accepts -g... (cached) yes
checking for mingw32-gcc option to accept ANSI C... (cached) none needed
configure: error: unable to find a compiler for building build tools
バージョンの確認方法
Windows sqlite.exe -version
Unix ./sqlite -version
 2.8.17-p2 と表示されれば OK.

※sqlite3の./configureは、上のオプションの文字列が違うので
   注意してください。
./configure の違い
sqlite2 sqlite3
--enable-tempdb-in-ram --enable-tempstore
--enable-utf8  


【dumpメモ】
・sqlite2をファイルにダンプする
 ./sqlite old-sqlite.db .dump > old-sqlite.sql.txt

・エラーが多くてインポートログをとりたい場合
sqlite3 new-sqlite.db  < old-sqlite.sql.txt > new-sqlite-inport-log.txt 2<&1

・直接新しいDBに流し込みたい場合
 ./sqlite old-sqlite.db .dump | sqlite3 new-sqlite.db

【その他のメモ】
compile.htmlには、
sqlite3コンパイル時に
SQLITE_OMIT_BLOB_LITERALが定義されていると
X'ABCD' 書式が使えないとあります。


【db自動判別メモ】
移行期間中だけ、コードに組み込むことで、エラーをはかずに済みます。
後々のためにsqlite3も判定にいれています。
php(PDO) で開く前に sqliteのバージョンを自動判別する方法
 $dsn = 'sqlite:'.$db_name;
if (file_exists($db_name))
{
$handle = fopen($db_name, "r");
$head = fread($handle, 100);
fclose($handle);

$head_sqlite2 = '** This file contains an SQLite 2.1 database **';
$head_sqlite3 = 'SQLite format 3';

if (substr_compare($head , $head_sqlite2, 0, strlen($head_sqlite2)) == 0)
{
$dsn = 'sqlite2:'.$db_name;
}
else if (substr_compare($head , $head_sqlite3, 0, strlen($head_sqlite3)) == 0)
{
$dsn = 'sqlite:'.$db_name;
}
}

$dbh = new PDO($dsn);
//sqlite::memory:
// sqlite:filename
// sqlite2:filename


【ソースの場所】 ソースコードのダウンロード先
 3.xは、公式サイトで 普通に配られています。

ログによると ソースの管理は、
 cvsから Fossilというシステムに移行したそうです。
 2009 Sep 11 (3.6.18):  http://www.sqlite.org/changes.html

2.xのコードは、
 http://www.sqlite.org/sqlite-source-2_8_17.zip
 か
 http://www.sqlite.org/download.html
 の Branches → version_2 をクリックしてダウンロードする
 version_2: http://www.sqlite.org/cgi/src/timeline?r=version_2

上記の方法でリンク切れの際は、自力で探してください。
その他のソースを探す方法
・つついてみる
 ローカルにストックしてあるファイル名は下記なので
 そのファイル名で公式サイトのurlをつついてみる。
sqlite-source-2_8_17.zip
sqlite-2_8_17.zip
sqlitedll-2_8_17.zip
sqlite_analyzer-2.8.16.bin.gz
sqlite-2.8.17.bin.gz
・unixなどのリポジトリからソースrpm,tarを展開して取り出す

ブログ内 関連記事: sqlite.exe .dumpで文字化け 【& patch p2 編】


ブログ内 関連記事: sqlite.exe .dumpで文字化け 【& patch p2 編】

PR

[PR]