プログラマーのメモ書き

伊勢在住のプログラマーが気になることを気ままにメモったブログです

SQL Server の互換性レベル変更のための検証

仕事で使ってる SQL Server があります。以前は、RDS の SQL Server 2014 を使っていたのですが、監査機能(のある機能)を使いたかったので、 SQL Server 2019 に移行しました。 RDS では、メジャーバージョンアップしても、互換性レベルをアップグレード前に合わせてくれるというのがあるので、互換性レベル 120 ( SQL Server 2014 相当) で使ってました。

いままでは、この形の運用で問題なかったのですが、ちょっと試してみたい機能(というより関数)が出てきました。が、自分で互換性を確認することを考えるとなかなか大変なので当初は躊躇してました。

ですが、ちょっと調べてみたら DMA(Data Migration Assistant)というツールがあり、これを使えば、SQL Server 間のアップグレード時の問題が簡単に確認できることが分かりました。

ということで、実際に試してみましたので、メモを残しておきます。

DMA のインストールと起動

DMA は、 Microsoft のサイトからダウンロードできます。早速、ダウンロードして、インストーラをダブルクリックすれば簡単んいインストールできます。インストールに成功したら、早速起動してみます。

無事起動できましたね。

アセスメントの実施

DMA にはアセスメントと移行の2つの機能があるようです。今回はアセスメントを使います。

まず『+』を押して、新しいプロジェクトを設定します。

今回は次のようにしました。

項目 設定内容
プロジェクトタイプ Assesment (デフォルト)
プロジェクト名 適当な名前(testにしました)
Assesment Type Database Engine (デフォルト)
Source Server Type AWS RDS for SQL Server
Target server type SQL Server

設定後 create ボタンを押すと、設定画面に移ります。

Select target version は SQL Server on Windows を選択します(デフォルトのまま)。

検査する内容を選択するのですが、 Compatibility Issue しか選べないので、そのままとして、nextを押します。

Assesment したい source server のアドレスとログイン情報を設定します。

このとき、 Trust server certificate にもチェックを入れときます。

Connect を押して、接続できればOKです。無事に接続すると、下記のような画面が表示されて、SQL Server のどのデータベースに接続するかを聞かれます。今回は、すべてのデータベースとしました。

ここまでの設定でよければ、addを押します。

もう一度、 source の確認画面が表示されるので、

問題がなければ、 Start Assesment を押してアセスメントを行います。

結果の確認

しばらく、下記のような画面が出てる状態で待ちます。

Assesment が終わると結果画面が表示されます。

おぉ、問題ないようです。Compatibility Level 毎に評価結果も出してくれるようです。今回の場合は Compatibility Level 150 (SQL Server 2019 相当)に上げても問題ないようですね。

まあ、そんなにややこしいことをやってる覚えもないので、妥当っちゃ妥当な結果なのですが、確認できるのは、精神衛生上いいですね。

最後に、念のため、 Export report で結果を保存しておきます。

まとめ

一応、機械的にですが、互換性レベルを上げても問題ないことが確認でした。あとは、こちらの記事などを参考に、実際に互換性レベルを変更します。

にしても、これで検証できるのは楽ですね。また、使ってみよう。

おまけ

以前、 Access を SQL Server に移行する際に SSMA ( SQL Server Migration Assistant ) というのを使いました(こちらの記事参照)。今回の DMA と何が違うんだろうか?と思ったので、調べてみると

  • SSMA : 異なるデータベースを SQL Server に移行する際の手助けをしてくれるツール
  • DMA : SQL Server のアップグレード時の互換性の手助けしてくれるツール

ということでした(詳しくはこちらの記事などを参照)。

なるほどね。にしても、名前が紛らわしいな。

スマホの写真バックアップに dropbox を使ってみようとしたが諦めました

スマホ( Nexus 6P, Android 8.1.0 )で撮った写真のバックアップ先として、スマホへのログイン時の Google アカウント( Google Drive)を利用していました。Google アカウントは無料枠として 15GB の Google Drive の容量があり、写真のバックアップもここに含まれています。

以前はバックアップとして『高画質』を選択していれば、容量にはカウントされずに無制限だったりしました(2021年5月末で終了)。ですが、個人的には写真の画質は落としたくないので、元の画質で保存していました。いまはもう画質に関係なく容量にカウントされますね。

そんなに大量に写真を撮ることもないのですが、何年も使っているとそれなりに容量を使ってしまい、最近、容量がいっぱいになりました、と警告が出るようになりました。PCのブラウザで Google Photo を開くと、こんな感じに警告が表示されます。

写真のバックアップが取れないだけならまだしも、同じアカウントの Gmail もメールの受信ができなくなる、とあります。

これは困りますね。スマホのアカウントのメールは、子どもの学校からの緊急通知などを受けるようにしているので、いざという時に使えないのでは話になりません。

素直に考えれば、 Google One にアップグレードして、上納金 お金を払って、快適に使うことになると思いますが、なんかいやです。 ということで、いろいろとあがいてみたのをメモにまとめておきます。

とはいえ、結局、最終的には Google One にしたんですけどね。

Dropbox

スマホの写真のバックアップの選択肢が、 Google One 以外にないものか調べてみると、いろいろとあるにはあるようです。でも、一番身近なものとしては Dropbox が対応しているので、それを使うのが手っ取り早そうです。

Dropbox は仕事の関係で使っているため、有料プラン(Plus)を契約しているのですが、 2TB の容量は大きすぎて余りまくってます。なので、写真の保存先としてはよさそうです。スマホ側でも普段から使ってますしね。

使ってみる

写真のバックアップは、 Dropbox では『カメラアップロード』という機能になるようです。

使い方は簡単で、スマホ上で Dropbox アプリを開いて『設定』->『カメラアップロード』を選択して、『写真をバックアップ』を押して、オンにすれば終わりです。

オンにすれば、自動的に写真のアップロードが始まります。これはよさそうですね。

他の設定として、WiFi接続時のみアップロードするようにするとか、バッテリー残量に応じてアップロードを中止する、というようなオプションがありますので、お好みに合わせて設定してください。

で、実際に使ってみると、個人的に気になる点がいくつか出てきたので、以下にまとめておきます。

問題点1

Dropbox のカメラアップロードを有効にして、どれぐらいデータがあるのか確認するため、PC のブラウザで Google Photo を見ると、 2014 年~今年( 2022 年)まで写真があります。結構な量ですね。ということで、しばらくほっけばいいやと思って仕事してました。

しばらくしてから、ふと、 Dropbox のフォルダを見ると、 2022 年の新しいほうからアップロードが始まっていたのですが、 2018 年ごろの写真をアップロードしたあたりで処理が終わっています。 ここで、昼ご飯だったのでいったんアップロード処理を中断して(というか、スマホをもって外に出て)、帰ってから原因を調べてみました。

Dropbox のトラブルシューティングなどを見ると、カメラアップロードが中断される場合

  • WiFi 接続がない
  • バッテリー残量が少ない
  • Dropbox の空き容量がない

あたりがよくある原因だそうですが、どれにも該当しません。また、スマホ上の Dropbox アプリを再起動してみても状況は変わりません。

ここで、 Dropbox に問い合わせしてみようと思って、写真フォルダのパスなどの情報を確認するために、スマホ本体を PC につなげて写真の保存先を確認すると

あれ?

日付を元にして、付けられているファイル名ですが、2018年より昔のものがありません。

なんだろうな?と思って、ブラウザで Google Photo にログインして、スマホ内にファイルがあるものの日付より古い日付の画像を選択して確認してみると、昔使っていた機種の名前が出てきます。

あ、そういうことか!

スマホ上の Google Photo のアプリだと、常にクラウドと連携してバックアップをしています。なので、スマホを交換した際も、同じ Google アカウントでセットアップさえしてやれば、昔の写真を見ることができます。が、この時、新しい端末内に写真はありません(せいぜいキャッシュが作られるぐらい?明示的にダウンロードしたら別でしょうけど)。 なので、 Dropbox からしたら、端末内にないファイルのことなんてしらないよ、ということなんでしょうね。

これについては、最悪、 Google Photo からデータをダウンロードして Dropbox 側にアップロードすればいいかな?と思われます。

問題点2

むしろこっちのほうが面倒そうなんですが、どうもカメラアップロードの場合、一部のファイルがアップロードされてないようです。 こちらはファイルそのものは、端末内にちゃんと存在しています。なんでアップロード対象にならないのかは、今一つわかりませんでした。

ただ、Windows PC にスマホをつないでカメラフォルダを見ていたら、サムネイルが生成されない jpg ファイルがいくつかあって、カメラアップロードされていないものと対応しているように見えました(数個のファイル見ただけなので、確定的なことは何もいえないですが)。

jpg の詳細なファイル形式の差異なのか、スマホ側で何かイレギュラーな情報を付加しているのか・・・、実際のところ、どういう理由かまでは分かりませんが、カメラアップロードの対象から漏れるファイルが存在し、バックアップとしては、中途半端な状態になっていることは確かなようです。

これへの対応はちょっと面倒ですね。どのファイルがまだアップロードされていないのか調べるなんてやりたくないです。 もしやるなら、

  • いったんカメラアップロードはオフにして
  • アップロード済みのデータをすべて消去して
  • Google Photo から全画像データをダウンロードして
  • Dropbox の『カメラアップロード』フォルダにデータをアップロードする

というような方法ですかね?で、その後追加で撮った写真は、カメラアップロードで Dropbox にバックアップする、という形が現実的なようです。

にしてもやりたくないな・・・

結論

ということで、今回の結論としては、使ってるスマホは Android 端末というのもあり、素直に Google One を使うことにしました。

とはいえ、せっかく調べたので、 Dropbox を写真のバックアップ先に使う場合のケースを考えてみると、

  • Dropbox の容量が余っている場合
  • または Google One の費用がかさむようになった場合
  • 1台目のスマホを使いだして以降同じ機種をずっと使ってるような場合
  • 写真の数が少なくて、バックアップが正しい状態であることを簡単に確認できる場合

などになりそうです。私の場合だと、当面は Google One を使うにしても、理由の2番目の Google One の費用が気になり、先々は Dropbox に切り替えることになるかもしれないですね。

また、もし、Dropbox を写真のバックアップ先に使う場合は、次の点を事前に考えておくのがいいかと思います。

  • スマホを替えたときは、(そのままでは)昔の写真を Google photo (Androd の標準の写真をみるアプリ)で見れない(はず)
  • カメラフォルダ以外(スクリーンショットとか)の写真もバックアップ対象になってる

というのがありそうです(2つ目については今回試したスマホがこの状態でした)。

なんにせよ、使う前にはいろいろとテストをすることをお勧めします。

LINE ボット 『リフティング回数レコーダー』を作成してみた

第25回伊勢IT交流会でネタがなかったので、ちょうど作りたいと思っていた、 LINE ボットを GAS を利用して作ってみました。

作ったボットは『リフティング回数レコーダー』というものです。

子どもがサッカーやってるんですが、そこではリフティングを頑張るのが推奨されてます。で、毎日、リフティングやって、保護者が回数を数えているので、どうせなら簡単に記録しておきたいなと思ったのが発端です。

LINE ボットを作るには、 Webhook を受け取るサーバーが必要になります。サーバーを立てるとなると面倒だし、第一お金もかかってしまいます。その点、 GAS を使えば、ウェブアプリとしてデプロイすることができるので、これならお金もかからずにお手軽に遊べそうです。

ということで、ボットとしては、まだ未完成なのですが、作っていく際に気づいたあれこれをメモっておきます。

GAS を Web アプリとして仕立てる

GAS のリファレンスを見ると、 doGet() と doPost() を関数として用意して、デプロイする際に『ウェブアプリ』を選択すれば、それだけでよいようです。

たとえば、こんな風に定義してみます。

function doGet(e) {
  let param = e;
  Logger.log("GET: " + JSON.stringify(param));

  return ContentService.createTextOutput(JSON.stringify(param)).setMimeType(ContentService.MimeType.JSON);
}

function doPost(e) {
  let param = e;
  Logger.log("POST: " + JSON.stringify(param));

  return ContentService.createTextOutput(JSON.stringify(param)).setMimeType(ContentService.MimeType.JSON);  
}

関数を定義したら、Apps Script の編集画面の右上にある『デプロイ』を選択します。

デプロイの設定画面で、『デプロイタイプを選択してください』とあるので、

左上あたりにある歯車アイコンをクリックして、『ウェブアプリ』を選びます。ウェブアプリ用の設定画面が表示されるので、

  • 『次のユーザーとして実行』:自分
  • 『アクセスできるユーザー』:全員

として、デプロイします。『アクセスできるユーザー』の『全員』は Google アカウントを持たない場合も含まれており、LINE の Webhook から呼び出す場合は、こちらを選んでおく必要があります。

デプロイに成功したら、curl で呼び出してみます。

mor@DESKTOP-DE7IL4F:~$ curl -L https://script.google.com/macros/s/デプロイID/exec
{"contextPath":"","parameters":{},"contentLength":-1,"parameter":{},"queryString":""}mor@DESKTOP-DE7IL4F:~$
mor@DESKTOP-DE7IL4F:~$

こんな感じで返ってきました。問題なく動作しているようです。

なお、上記のサンプルコードでは認証は求められないのですが、コード内部で Google Drive へのアクセスがあったりすると、最初にデプロイする際に、

という感じで承認を求められますので、画面の指示に従って、承認を行います(実行ユーザーに対する承認ということですね)。

LINE ボット

GAS をウェブアプリとしてデプロイできるようになったので、本題の LINE ボットを作ります。

LINE ボットは Messaging API の Webhook URL で指定した URL に POST でイベントが送られてくるので、それを処理するようにしてやればOKです。

おおまか処理としては

  • LINE からイベントが送られてくる(複数の可能性あり)
  • 複数イベントをループでひとつづく処理する
  • イベント種類に応じて、ボットで行いたい処理を決める

という感じです。今回は、 message イベントにのみ対応するように実装しました。message イベントではメッセージの最初に行いたい処理を記述することで、リフティング回数の登録と確認ができるようにしました。

スプレッドシート

リフティング回数の記録は、せっかく GAS を使うので、スプレッドシートにユーザーごとのシートを用意して、そこに記入していくようにします。

ユーザー名は、 LINE の Webhook で取得できる『ユーザーID』を使ってます。GAS だと簡易的に DB の代わりもさせられるので、その点も楽ですね。

スプレッドシート(というより Google Drive)を扱ううえで、ちょっと注意が必要だったのが、

  • ファイルを新規作成すると必ずルートフォルダに作られるので、所定のフォルダに動かすのは自分でやる
  • 同名ファイル/フォルダ をいくつでも作成可能

なので、コードでファイルを指定して開くときも、ファイル名で指定すると複数のファイルが取得されたりします。そのあたりの扱いが WIndows などとはちょっと違うので注意が必要です。

具体的な中身は GitHub にアップしたコードを見てください。

github.com

(参考)

Messaging API と GAS を連携

LINE ボットは以前試した際に理解したのですが、LINE Official Account manager で公式アカウントを作り Messaging API を有効にして、 Webhook URL を指定してやればOKです(LINE Developer Console から作る方法ありですが、公式アカウントが勝手に作られます)。

なので、GAS 側の処理を記述したら、デプロイを行って、URLを Messaging API の Webhook URL として入力します。

ちなみに、このとき、 LINE Developer Console を開いて、 Messaging API の設定画面で

Webhook URL のところにある『検証』を押しても、下記のようなエラーになり検証できません。

GAS をウェブアプリとして公開している場合、一度リダイレクトされるので、それが影響しているっぽいですね。 ただ、実際に Webhook として用いることはできるので、ご安心を。

GCP プロジェクトへの切り替え

GAS 側の処理を書いて、 LINE のボットの設定も行ったので、これで動作するはずです。

でも、GAS のエディタ上で実行した場合は、画面上でログ(Logger.log や console.log の出力)を見ることができますが、doGet や doPost で呼び出した場合は、このままではログを見ることができません(以前は、何も設定を変えなくても見れたように思いますが、いつのころからか設定が変わったようです)。

LINE とかで連携して動作させる場合、このままログが見れないとデバッグ時とかなかなかつらいものがあります。

で、ログを見れるようにするには、 GAS のプロジェクトの設定を、デフォルトのものから、標準の GCP のプロジェクト (standard GCP Project) に切り替える必要があるそうです。

ということで、この切り替え作業を行っておきます。

標準の GCP プロジェクト (standard GCP Project) への切り替え

標準の GCP プロジェクトへの切り替えは、いろいろな記事で紹介されているので、ここでは詳しく触れません。

これらの記事を読んでいて、気になった点だけ補足しておきます。

  • OAuth 同意画面の設定時、スコープおよびテストユーザーは指定しなくてもよい
  • OAuth 同意画面の構成後、『アプリを公開』を実行し、公開ステータス『本番環境』へ変更する
  • 認証情報『 OAuth 2.0 クライアントID』が自動的に作成されるので、これも明示的に作成しなくてよい

といった点に気をつければ、トラブルも少ないかと思います。

承認について

GCP プロジェクトに切り替え後、同じURLでアクセスすると、画面のような表示が出てきます。

じゃあ、承認してやればいいやと思ったのですが、ブラウザ上には認証できそうなリンクやボタンがありません。

ここで、少々はまったのですが、結論としては、下記の記事にあるように、開発環境上で実行してやることで、認証を呼び出すことができました。

Google Apps Scriptの承認エラー 401の対処方法

適当な関数を選んでエディタから『実行』を呼ぶと、

と表示されるので、あとは画面の指示に従って、承認を行います。

承認時のエラー

もし、途中で、

のようなエラーが表示される場合、OAuth 同意画面の設定で『公開ステータス』が『テスト』のままになっていると思われます(上記の記事にもありますね)。

OAuth 同意画面を開いて、『アプリを公開』を押すと、

のような確認画面が表示されるので、確認を押して、公開します。下記のように、公開ステータスが『本番環境』となってれば、OKです。

ちなみに、参考までに、GCP プロジェクトへ切り替える方法を紹介している昔の記事などでは、GCP の『OAuth 同意画面』で認証が出きるっぽいことが書いてありますが、このあたりのフローがどうも若干変わっているようです。

Google Apps Script試行錯誤 Blog: デフォルトのGCPプロジェクトを標準のGCPプロジェクトに切り替えたい

エラー

標準の GCP プロジェクトに切り替えた後、承認もしたので、動くだろうと思って試してみると、動きません。エディタから動かしてみると、こんな感じになります。

ブラウザだとこんな感じのそっけないメッセージです。

さきほど、プロジェクトを切り替えて、ログがみれるようになったので、そちらを見てみると、 permission denied との文が見られますので、どうも権限関係のようです。 ですが、いろいろと調べてみても、どこから権限を有効にするのかが全然わかりません。

ためしに、GASのファイルをコピーして、同じコードでも別ファイルにして動かすと、問題なく動きます。GASのファイルをコピーすると、プロジェクトはデフォルトのプロジェクトに戻るので、どうも、標準のGCPプロジェクトに切り替えたのが要因のようです。

そんなのも踏まえて探してみると、だいぶ苦労しましたが、やっとのことで探し当てた記事に、ずばり解決策が載ってました。

GASでDriveAppクラスを使うと`Exception: We're sorry, a server error occurred. Please wait a bit and try again.`エラーが出る - Qiita

GCP のプロジェクト側で Google Drive API を有効にするというのがポイントのようです。

『有効なAPIとサービス』を選択し、『APIとサービスの有効化』から Google Drive API を検索します。

Google Drive API が出てきたら、これを有効にます。

この設定後、もう一度実行したら、問題なく表示できるようになりました!

にしても、エラーメッセージの内容から一時的な Google 側の問題なのかな?と思ってしまうので、『権限がないよ』というのをもうちょっとわかりやすく示してほしいものです > Google さん

動作

ここまでできたら、あとは動作させてみます。

公式アカウントのQRコードをラインで読み込んで、友達になります。

登録, 2022/7/2, 10

のように、日付と回数を送ると、登録されます。

スプレッドシート側にも間違いなく追加されています。

また、

確認, 2022/7/2

のように、日付を送ると、その日の回数を表示します。

記録が無いときは、ないことを教えてくれます。

これで、とりあえず最低限の機能は実現できました。

今後

これだけだと、ほんとためしに作りました、というだけですし、インターフェースがいかにも使いにくいです。なので、

  • 登録・確認はメニューからできるようにする
  • 指定した期間の推移をグラフで取得する
  • 同じ日付の場合の重複処理、日付が前後した場合の処理などを実装する
  • 目標回数を設定して、達成できたら、おめでとうメッセージを送る

などを作りこんでいきたいと思います。

そこまでできたら、一番怖いユーザー(子供)のレビューですかね。 もうちょっとかんばります。