MySQL5.1のDBのダンプをMySQL5.7のDBにインポートしたらSQL エラー (1118): Row size too large (> 8126)

MySQL5.1のDBのダンプをMySQL5.7おDBにインポートしたらSQL エラー (1118): Row size too large (> 8126)が発生した。
特定のテーブルでこのエラーが発生しており、このテーブルではvarcharで定義された項目が400程度もある。
InnoDBではレコードサイズが8192を超えてはだめらしい。
MySQL5.1ではチェックが甘いためか?
このSQLが通っていたがMySQL5.7ではそれがだめになったようだ。
根本的な解決策はQiitaを参照するとして、
今回はとりあえずエラーを回避するためにエラーチェックを緩くする。

確認のために以下のSQLを実行するとエラーが発生。
[code]
create table TESTSIZE
(
FLD01 varchar(12),
FLD02 varchar(12),
省略
FLD298 varchar(12),
FLD299 varchar(12),
FLD300 varchar(12)
)ENGINE=InnoDB
[/code]

その後、以下のコマンドで環境変数を変更してSQLを実行すると警告は表示されるが無事にテーブルは作成される。
[code]
set innodb_strict_mode=0;
[/code]

恒久的な処置としてはmy.cnfに以下を追加
[code]
innodb_strict_mode = 0
[/code]

MySQLを再起動して対応

こちらも参考にさせていただきました
teratail

QGIS 選択したFeatureを新規レイヤーに貼り付け

TOOLバーの「領域またはシングルクリックによるチ物選択」ボタンを選択し対象のFeatureを選択

編集メニューのチ物のコピーを選択

編集メニューの新規レイヤへの地物貼り付けを選択

レイヤ名を入力してレイヤを作成

git 既存ファイルを編集

既存のファイルを編集後リモートリポジトリに反映

変更されたファイルをインデックスに追加
[code]
git add -u
[/code]

ファイルをローカルリポジトリにコミット
[code]
git commit -a -m "コメント"
[/code]

ファイルをリモートレポジトリに反映
[code]
git push origin master
Enter passphrase for key ‘/c/Users/tarumi/.ssh/id_rsa’: SSLキーのパスワードを入力
[/code]

git ファイルの追加

プロジェクトディレクトリ以下にファイルを追加した時は以下の操作でリモートのレポジトリに反映する

ファイルをインデックスに追加
[code]
git add .
[/code]

特定のファイルのみを追加
[code]
git add ファイル名
[/code]

インデックスに追加されたファイルをローカルレポジトリにcommit
[code]
git commit -m "コメント"
[/code]

リモートレポジトリに反映

[code]
git push origin master
Enter passphrase for key ‘/c/Users/tarumi/.ssh/id_rsa’:SSLキーのパスワードを入力
[/code]

git for windowsをインストールしてgitlabのプロジェクトを操作

Git for windowsのサイトよりインストーラーをダウンロードし、インストール。
インストーラーは「Git-2.16.2-64-bit.exe」
Windows10の場合はWindowsの設定より「アプリのインストール」を「ストアのアプリのみ許可する」以外を選択しておく

インストーラーを実行して以下に従ってインストール

インストール先のディレクトリはC:\Gitに変更

インストールするコンポーネントはデフォルト

デフォルトのエディタ
※後ほど秀丸に変更の予定

bashではwindowsのDOSを使用

SSLの設定

改行の処理の設定

その他のオプション

インストール終了

Gitの初期設定

DOSコマンドを開きメールアドレス、ユーザー名等を設定
※core.quotepathをoffにするとgit statusで変更ファイル一覧を表示するときに、日本語のファイル名が文字化けしないでちゃんと表示される
ユーザー名、メールアドレスはGitlabに設定した値を入力
[code]
C:\Users\tarumi>git config –global user.email ‘メールアドレス’
C:\Users\tarumi>git config –global user.name ‘ユーザー名’
C:\Users\tarumi>git config –global core.quotepath off
[/code]

SSHのキーを作成
カレントをc:\git\usr\binに移動
以下のコマンドを実行
パスフレーズには任意の値を入力

[code]
C:\Git\usr\bin>ssh-keygen -t rsa -C ‘メールアドレス’
Generating public/private rsa key pair.
Enter file in which to save the key (/c/Users/tarumi/.ssh/id_rsa):
Created directory ‘/c/Users/tarumi/.ssh’.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:[/code]
[/code]

GitLabのサイトを開きメニューより設定を選択

サイドばーよりSSHきーを選択してSSHキーを入力するページを表示

先ほど作成したid_rsa.pubの内容を張り付ける

以上で設定は終了

最初にプロジェクトのクローンを作成

GitLabで対象のプロジェクトを開き画面上のURLをコピー

PC上にローカルディレクトリを作成してカレントに移動し以下のコマンドを実行

[code]
git clone git@gitlab.comから始まるURL(上記でコピーした値)
[/code]

以上でローカルにcloneが作成される

gitlabを始める

gitlabには自分でサイト構築から始める方法とgithubと同様にサービスを使用する方法の2種類がある。
今回は後者を使ってみる

以下のサイトを開いて
https://gitlab.com/users/sign_in
申し込みを行う。

申し込みを行うとメールが送信されるのでリンクをクリックしてログイン

最初に「New Group」ボタンを押してグループを作成する

グループ名、スコープ等を入力して「Create Group」ボタンを押す。

privateなグループであっても名称はユニークな名称の必要があるようだ。

既に使われている名称を入力すると「Path has already been taken」と表示される。

次にグループ内にプロジェクトを作成

グループの一覧を表示してプロジェクトを作成するグループを選択

「New project」を選択

プロジェクト名、説明、スコープを入力して「Create Project」を選択

以上でプロジェクトが作成される

作成されたプロジェクトのTOPにはプロジェクトのcloneの方法等が記載

MySqlDataReaderがハングアップ

.NET Connector6.0.4.0のMySqlDataReaderを10分以上使用しているとハングアップしてしまいエラーも発生せずにCPUをどんどん消費してしまう。

[code]
MySqlCommand my_cmd = my_con.CreateCommand();
my_cmd.CommandText = sql;
MySqlDataReader my_dr = my_cmd.ExecuteReader();
while (my_dr.Read())
{
ここで処理を行う
}
[/code]

上記のwhileが10分以上かかるとReadメソッドでハングアップする。
net_read_timeout、net_read_timeoutそれぞれに3600を設定して回避

LeafletでL.Layerから派生した独自レイヤを作る

Leafletでとりあえず500mメッシュを表示させたいと思いL.Layerからの派生を調査。
※jsonやwmsは何も使わずに!

Leafletでは個々のMarkerもL.Layerから派生されている。

L.Layerからの派生したクラスを作成するにはGithubのleafletjs-plugin-templatesを改造するのが最短コース。
LeafletLayerTemplate.jsをダウンロードして眺めればどのように作成すればよいのか、分かり易い。

以下はダウンロードしたLeafletLayerTemplateのコメントを削除したソース。

LeafletLayerTemplateはMarkerと同様の動作を意識して各関数内に実装がされている。

関数initialize
L.LeafletLayerTemplateのインスタンス作成時に呼ばれる関数
L.LeafletLayerTemplateのインスタンスの作成は
[code]
var layer = new L.LeafletLayerTemplate();
[/code]
または
[code]
var layer = L.LeafletLayerTemplate();
[/code]
で作成される。

引数に座標を指定すると関数initializeに座標が渡る。
この引数についてはoptions以外も指定が可能。
例えばlatとlngをそれぞれ渡してもよい。
例)
[code]
initialize: function(lat, lng) {
}
[/code]

関数onAdd
レイヤをmapに追加すると呼ばれる関数。
以下ではdivを作成しmap.getPanes().overlayPaneに追加。
map.on(‘viewreset’, this._updatePosition, this);
は地図の移動時にthis._updatePositionをリスナーとして登録。
※現在はviewresetは機能しないためmoveやmoveendなどを使用する必要がある。
その後、強制的に_updatePositionを呼び出して位置を設定
※_updatePositionはユーザー関数

関数_updatePosition
mapの位置にあわせてdivの位置を移動。

関数onRemove
リスナーを削除し、divを削除

[code]
L.LeafletLayerTemplate = L.Layer.extend({

initialize: function(options) {
this._latLng = options.latLng;
},

onAdd: function(map) {
this._map = map;
var layerElementTag = ‘div’;
var layerElementClasses = ‘.leaflet-layer-template leaflet-zoom-hide’;
this._layerElement = L.DomUtil.create(layerElementTag, layerElementClasses);
map.getPanes().overlayPane.appendChild(this._layerElement);
map.on(‘viewreset’, this._updatePosition, this);
this._updatePosition();
},

_updatePosition: function() {
var position = this._map.latLngToLayerPoint(this._latLng);
L.DomUtil.setPosition(this._layerElement, position);
},

onRemove: function(map) {
map.getPanes().overlayPane.removeChild(this._layerElement);
map.off(‘viewreset’, this._updatePosition, this);
}

});
L.leafletLayerTemplate = function(options) {
return new L.LeafletLayerTemplate(options);
};
[/code]

もちろん独自レイヤだからといって必ずしもdivを作成してdomを操作する必要もない。
L.Polygonなどを使用してレイヤの描画を行うのも正しい。

以下は500mメッシュを描画する独自レイヤ

leafletで地図上にラベルを表示

WMS、GeoJsonを使わずに地図上にラベルを表示する方法

leafletでラベルを表示するにはプラグイン Leaflet.labelを使う方法とL.divIconを使う2つの方法があるようだ。
※Leaflet.labelが今でも使えるかは不明。
今回はL.divIconを使う方法を採用。
参考Text labels in leaflet

[code]
var icon = L.divIcon({
className: ‘meshno’,
html: "123456789"
});
var marker = L.marker(new L.LatLng(lat, lng), {icon:icon})
marker.addTo(this._map);
[/code]

EventEmitterをちょっと改造

EventEmitterはDOMを使用せずにイベント機能をクラスに与えることが可能なとても便利なクラス。
但し最大の不満はListener登録時にListener内でのthisを指定できない点。
※バージョンは5.2.4

例)リスナーの登録
[code]
var eventEmitter = new EventEmitter();
・・・
eventEmitter.addListener(‘click’, this.on_clicked.bind(this));
[/code]
上記のようにListener登録してしまうとremoveListenerが正しく機能せずにListenerが残ってしまう。
例)リスナーの削除
[code]
eventEmitter.removeListener(‘click’, this.on_clicked.bind(this));
[/code]

これらの問題を対応するためにEventEmitterを以下に従って修正

addListenerの修正

変更前
[code]
proto.addListener = function addListener(evt, listener) {
if (!isValidListener(listener)) {
throw new TypeError(‘listener must be a function’);
}

var listeners = this.getListenersAsObject(evt);
var listenerIsWrapped = typeof listener === ‘object’;
var key;

for (key in listeners) {
if (listeners.hasOwnProperty(key) && indexOfListener(listeners[key], listener) === -1) {
listeners[key].push(listenerIsWrapped ? listener : {
listener: listener,
once: false
});
}
}

return this;
};
[/code]

変更後
[code]
proto.addListener = function addListener(evt, listener) {
if (!isValidListener(listener)) {
throw new TypeError(‘listener must be a function’);
}
// tarumi custom
var bind_instance = null;
if(arguments.length > 2){
bind_instance = arguments[2];
}
// tarumi custom

var listeners = this.getListenersAsObject(evt);
var listenerIsWrapped = typeof listener === ‘object’;
var key;

for (key in listeners) {
if (listeners.hasOwnProperty(key) && indexOfListener(listeners[key], listener) === -1) {
listeners[key].push(listenerIsWrapped ? listener : {
listener: listener,
// tarumi custom
instance: bind_instance,
// tarumi custom
once: false
});
}
}

return this;
};
[/code]

関数:emitEventの修正

変更前
[code]
proto.emitEvent = function emitEvent(evt, args) {
var listenersMap = this.getListenersAsObject(evt);
var listeners;
var listener;
var i;
var key;
var response;

for (key in listenersMap) {
if (listenersMap.hasOwnProperty(key)) {
listeners = listenersMap[key].slice(0);

for (i = 0; i < listeners.length; i++) {
// If the listener returns true then it shall be removed from the event
// The function is executed either with a basic call or an apply if there is an args array
listener = listeners[i];

if (listener.once === true) {
this.removeListener(evt, listener.listener);
}
response = listener.listener.apply(this, args || []);

if (response === this._getOnceReturnValue()) {
this.removeListener(evt, listener.listener);
}
}
}
}

return this;
};
[/code]

変更後
[code]
proto.emitEvent = function emitEvent(evt, args) {
var listenersMap = this.getListenersAsObject(evt);
var listeners;
var listener;
var i;
var key;
var response;

for (key in listenersMap) {
if (listenersMap.hasOwnProperty(key)) {
listeners = listenersMap[key].slice(0);

for (i = 0; i < listeners.length; i++) {
// If the listener returns true then it shall be removed from the event
// The function is executed either with a basic call or an apply if there is an args array
listener = listeners[i];

if (listener.once === true) {
this.removeListener(evt, listener.listener);
}

if(listener.instance===null || listener.instance === ‘null’ || listener.instance === ‘undefined’ || listener.instance === undefined){
response = listener.listener.apply(this, args || []);
}
else{
response = listener.listener.apply(listener.instance, args || []);
}

if (response === this._getOnceReturnValue()) {
this.removeListener(evt, listener.listener);
}
}
}
}

return this;
};
[/code]

リスナーの登録の変更
[code]
eventEmitter.addListener(‘click’, this.on_clicked,this);
[/code]

リスナーの削除の変更
[code]
eventEmitter.removeListener(‘click’, this.on_clicked);
[/code]