Author Archive

大したリリースではないのですが、記載します。

https://github.com/shigenobu/ebonyrack/releases

0.6.1と比べて、

・マルチディスプレイの修正

・tableのカラムのテキスト部分をダブルクリックで選択可能(コピーしやすいように)

・読み込み専用モードで開く環境変数追加

という薄い内容です。

tableのカラムのテキストを選択可能とするのは意外と難しく、

もともろJLabelでやっていたのですが、JLabelではテキスト選択ができないため、

JTextFieldにして、ダブルクリックイベントで、コメントの部分の選択範囲を修正するなどの対応を行っています。

やりたいことが難しくて、なかなか進まない現状。。

外部キーのANTLRのパースとかも入れたほうがいい気がしてきています。。

以上

投稿日時:2024年07月09日 23:37   カテゴリー:java, mariadb   [コメントがあればどうぞ]

OS: Pop!_OS 22.04 LTS

dotnet: 8.0.204

という環境で、

ASP.NET coreのWEBアプリケーションから、

mysql, memcached, redisへのアクセスをするのベンチマークをしてみたところ、

同期>非同期

となる局面があったので、書いておきます。

使用したライブラリは、

mysql: https://github.com/mysql-net/MySqlConnector

memcached: https://github.com/cnblogs/EnyimMemcachedCore

redis: https://github.com/StackExchange/StackExchange.Redis

です。

行ったベンチマークは、1回のリクエスト〜レスポンス処理の間に、上記データベースに複数回問い合わせるというもので、

よくあるWEBアプリケーションみたいな感じのものです。

で、結果を載せるほうがよいのですが、環境によって大きく左右されるので、

「こういうときは同期が速い」という所感レベルなものとさせていただきます。


というか、なんでこんなことをしたのかというと、

C#界隈では、どうしてもasync/awaitを使った非同期がベストプラクティスと言われているのですが、

async/awaitを使った非同期って、

・await一箇所でも書かなかったら実行時に気づかないような不具合を生むことがあり、

大きいプロジェクトほど、そのミスに気づけなくなる。

・呼び出し階層がすべて非同期になっている必要がある。

・ローカルネットワーク内にあるmysqlのような高速なデータベースに、

主キーで問い合わせるなどの高速なIOのケースにおいて、

CPUのコンテキストスイッチのほうがコスト高いときがあるんじゃないか?という疑問をもっていた。

のような課題もあるなとずっと思っていました。

とはいえ、同期の欠点は「詰まりやすい」ということで、

確かに1つの処理が遅れると、全体の遅れに影響してくるというのも経験しています。

しかしながら、エンドレスにハイトラフィックな事例というのもごく一部であり、

アプリケーションサーバのCPUを常に100%近く使うようにさせられている(つまり無駄を削ぎ落とす)

ようなことも稀かと思います。

ITの世界では、大は小を兼ねるかと思いますが、予算も限られた中でやるとして、

一定の余裕がある構成で、トラフィックも読めているのであれば、

無理にすべてをasync/awaitの非同期でやる必要もないとは個人的には考えています。

とはいいつつも、昨今のデータベースなどのミドルウェア事情として、ITの巨人が開発した巨大なソフトウェアを利用する局面も増えており、

こういったものは、mysqlのスタンドアロンとは違い、内部的になんども通信しているため、

IOレイテンシーは悪くなっています。

となると、結局、こういったものを利用することを想定して、

IOレイテンシーが悪くなっても耐えうるアプリケーションを用意しておかないといけないなと思いったわけです。

だけど、やっぱり計測してみないといけないなと思い、同期と非同期のベンチマークを取ったということです。


話が少しそれましたが、

同期>非同期

となるのは、

・同一ネットワーク内で高速なIOが見込めるとき

・アプリケーションに負荷がかかっていないとき

という条件を同時に満たすときです。

これが満たせなければ非同期のほうが良いと思われます。

たとえば、

・インターネット越しにIOを行う

・IOが高速でないデータベースを使う

・アプリケーションへの負荷が高いことが予想される

などの場合は、非同期に分があるでしょう。

C#のASP.NETでkerstrelを使う場合、スピンアップの悪さも、

非同期を使うことで抑え込めるという利点もあります。

「結局非同期のほうがいいじゃないか」という結論とも捉えられますが、

いろいろ考えると「結局非同期のほうがいい」のです。

ただ、1回でもawait書き忘れた場合のリスクについては、

開発エンジニアへの教育であったり、レビューなどでカバーしないといけないか思います。

私は、C#を利用している側の人間に過ぎないのですが、

こういったリスクについても、ふっとばされているようにも感じます。

「当たり前」なのかもしれませんが、開発エンジニアの知識レベルは様々であり、

ただでさえ近年複雑な要求仕様に対応を迫らている上で、

完璧な非同期コードを書くことも一苦労だと思います。

なので、非同期のリスク(お作法)についても、現場の理解力と、教育が大事だなと思う今日この頃です。

駄文失礼いたしました。

以上

投稿日時:2024年06月24日 23:20   カテゴリー:c#   [コメントがあればどうぞ]

忙しくて放置気味でしたが、

MariaDB11.4がLTSとして2024年5月にリリースされました。

https://mariadb.com/kb/en/changes-improvements-in-mariadb-11-4

2029年5月までのサポートとなります。

見落としていたのですが、またリリースサイクルが変わったようで、

次のLTSも1年後とかなのかなと思います。

注目していたtimestamp型の拡張は、11.5に見送られたようですね。

また、自分の作成している

https://github.com/shigenobu/magentadesk

もv0.6.2で11.4対応しました。

以上

投稿日時:2024年06月24日 22:33   カテゴリー:mariadb   [コメントがあればどうぞ]

TAPベースに非同期処理に関連して、

ネットを調べると、「同期と非同期の混在によるデッドロック」みたいな記事が多い。

これ、よく調べてみると、.NET FRAMEWORKの話だったりして、

.NET(core以降)のASPでは、どうやら事情が違うようです。

(※GUIについては、ここでは触れません)

CUI(コンソール)アプリケーションについては、もともとSyncronizedContextがないから、

デッドロックしないよ、みたいな話はあるのですが、

ASP.NET Core以降は、SyncronizedContextがなくなったため、よくあるデッドロックというのは起きません。

(参考)

https://blog.stephencleary.com/2017/03/aspnetcore-synchronization-context.html

https://qiita.com/jun1s/items/c178d37a2cbcd8594461

というわけで、デッドロックしそうなコードをかき集めて検証してみました。

下記コードの検証環境は以下の通りです。

$ dotnet --version
8.0.204

$ cat /etc/os-release
NAME="Pop!_OS"
VERSION="22.04 LTS"

(パターン1)

app.MapGet("/test1", async () =>
{
    Console.WriteLine("test 1-------------------------");
    Console.WriteLine($"before - {Thread.CurrentThread.ManagedThreadId}");  // 1: スレッドIDは15
    var ret = MyClass.Get().Result;
    Console.WriteLine($"after - {Thread.CurrentThread.ManagedThreadId}");  // 4: スレッドIDは15
    return ret;
});

class MyClass
{
    public static async Task<string> Get()
    {
        Console.WriteLine($"before in - {Thread.CurrentThread.ManagedThreadId}"); // 2: スレッドIDは15
        var ret = await Task.Run(() => "ok");
        Console.WriteLine($"after in - {Thread.CurrentThread.ManagedThreadId}");  // 3: スレッドIDは14 ★ここでスレッドが変わっている
        return ret;
    }
}

(パターン2)

app.MapGet("/test4", async () =>
{
    Console.WriteLine("test 4-------------------------");
    Console.WriteLine($"before - {Thread.CurrentThread.ManagedThreadId}");  // 1: スレッドIDは9
    var result = MyClass.GetFromHttp().Result;
    Console.WriteLine($"after - {Thread.CurrentThread.ManagedThreadId}");   // 4: スレッドIDは9
    return result;
});

class MyClass
{
    public static async Task<string> GetFromHttp()
    {
        var client = new HttpClient();
        Console.WriteLine($"before in - {Thread.CurrentThread.ManagedThreadId}");  // 2: スレッドIDは9
        var response = await client.GetAsync("http://localhost:8080");
        Console.WriteLine($"after in - {Thread.CurrentThread.ManagedThreadId}");    // 3: スレッドIDは7 ★ここでスレッドが変わっている
        return response.Content.ReadAsStringAsync().Result;
    }
}

というわけで、色々勘違いしそうなんですが、

ASP.NET Core以降では、「同期と非同期の混在」によるデッドロックは起きないようです。

つまり、「ConfigureAwait(false)」がなくても良いのです。

※すいません、間違ってたら教えて下さい。

とはいえ、ライブラリアプリケーションの場合は、

どの実行基盤で使われるかわからないので、「ConfigureAwait(false)」はつけておいたほうが良いかと思います。

C#のasync/awaitは沼だなといつも思う。

わからないことだらけです。

ちょっとしか見てないんですが、Restsharp なんかでは内部でSyncronizedContextを持っているようで、

どうしてこうなっているのかは謎が深まるばかりです。

いつか、スッキリ整理してまとめたいと思うこの頃。

できれば、IO待ちに関しては、「AWAIT」ではなく「NOWAIT」にして欲しかったりする。

つまり、非同期をデフォルトってことですかね。(新しいMSの言語まで待ちかな?)

以上

投稿日時:2024年04月25日 00:43   カテゴリー:c#   [コメントがあればどうぞ]

ちょこちょこ作業してます。

https://github.com/shigenobu/ebonyrack/releases

たまには画面もつけてみよう。(GITHUBに載せたままですが)

v0.5.2からv0.6.1までの主な変更は以下のとおりです。

  • テーブル・シーケンスの右クリックに「Edit」追加(ダブルクリック以外でも開けるように)
  • DDLインポート修正(DOCコメントの不具合、カラムオプションに生成列とチェック制約を登録できるように)
  • 起動時に最新バージョンのチェックを行う(古いバージョンの場合最新バージョンのリンクが表示されます)
  • HTMLにおいて、ダイアログの外側をクリックしたときに、ダイアログを閉じる処理を追加

やりたいことはたくさんあるのですが、なかなか実装が難しいので、

とりあえず未来のTODOを記録しておきます。

  • VIEWの対応
  • TRIGGERの対応
  • FUNCTIONの対応
  • PROCEDUREの対応
  • まとめて行う処理諸々(テーブルやパーティションに対してのグループの一括付与・除去とか、テーブルからカラムをまとめて付与・除去とか)
  • カラムを選択可能にしたい(JEditorPaneとか)
  • オブジェクトの複数一括移動
  • オブジェクトのグループ化みたいなもの

うーん、どれも難しい。。

以上

投稿日時:2024年04月25日 00:22   カテゴリー:java, mariadb, mysql   [コメントがあればどうぞ]

1ヶ月ほど立ちましたが、MariaDB 11.3がGAされました。

https://mariadb.com/kb/en/mariadb-11-3-2-release-notes/

※debianパッケージで不具合があるようですが。。

11系のGAはまだですが、11系のリリースを少しピックアップしてみます。


(11.0)

・オプティマイザのコストが進化

(11.1)

・DATE関数、YEAR関数の左辺配置でもINDEXが利用されるよう修正

(11.2)

・オンラインDDLの修正

(11.3)

・リダイレクトの導入

・DATE_FORMAT関数にタイムゾーンの書式追加


ぱらっと見た限り、日付系の対応がちょこちょこはいっており、

タイムゾーン(datetime with timezone みたいな)に対応していくような動きですね。

次の11.4では、timestampの変更(intからunsignedへの変更、ドライバー影響を抑えるため)が予定されており、

2039年問題が伸びるので、それまでに新しい型の導入を進めていく感じになるのでしょうか。

このあたりは、MySQL側の動きにも注目ですね。

で、個人的にちょっと気になったのは、11.2でのオンラインDDLの修正でしょうか。

(参考)

https://mariadb.com/resources/blog/alter-table-is-now-universally-online/

MySQLではオンラインDDLというと、「LOCK=NONE」なもの、

つまりALTER中も並行してDMLを受け入れるというものです。

「LOCK=NONE」なDDLというと、基本的には「ALGORITHM=NOCOPY」のもの、

「INSTANT」や「INPLACE」のみでした。

11.2の対応では、「ALGORITHM=COPY」も「LOCK=NONE」で動作するようになりました。

すべての動作ではないようですが、参考ページによるとおおよそ以下のDDLが「LOCK=NONE」となったようです。

  • カラムのデータ型変更
  • カラムをNOT NULLに変更
  • 制約のないカラムに対してDEFAULTの追加
  • STOREDの生成列の追加
  • チェック制約の追加
  • 主キーの削除
  • パーティションテーブルへの変更または削除
  • システムバージョニングの追加
  • オートインクリメントの追加

細かい制約もあるようなので、参考ページをちゃんと読んでもらえばと思います。

MySQLでは、

https://dev.mysql.com/doc/refman/8.0/ja/innodb-online-ddl-operations.html#online-ddl-foreign-key-operations

ということで、見比べてみると、拡張されたことがわかるかと思います。

とはいえ、DDLの適用コストは、INSTANTのような軽さはないので、油断はせずいてもらればと思います。

ちなみに、INSTANTの適用範囲は、以前書いたものから変わっていないようです。

※metaデータロックはかかりますのでご注意を。

また、magentadeskのv0.6.1が、MariaDB 11.3対応しています。

https://github.com/shigenobu/magentadesk

以上

投稿日時:2024年03月21日 23:20   カテゴリー:mariadb, mysql   [コメントがあればどうぞ]

MySQLあたりをよくさわっていたエンジニアにとって、

GCPのSpannerは非常に難しい。

難しいというより、MySQLの感覚でやると上手く行かないのです。

構文は割と似ていて、「`」なんかも使えるから、なおのこと油断しがちです。

銀の弾丸はないよね、という自戒を込めて、注意すべき点について書いておきます。

なお、「速くない」と表現していますが、同一ネットワーク内のMySQLのOLTPの場合と比較してとなります。

条件が変われば、MySQLもそこまでの速度はでないこともありますし、

分散の仕組みが入っていると事情は変わってくるので、その点は予めご了承ください。


●1回のクエリーのRTT(ラウンドトリップタイム)は速くない

MySQLだと、INDEXが聞いていれば(特に主キー)だと、同一ローカルネットワーク内であれば、

0.01秒もかからずデータが取得できますが、

Spannerだと0.01秒くらい平気でかかってしまいます。

そのため、アプリケーションが非同期IOをサポートしているなら、

非同期IOを使ったほうがアプリケーションのパフォーマンスは上がると思います。

とはいえ、1回のトランザクションで、クエリーの本数が多いとキツイので、

仕様でクエリー数を減らせるよう調整できればそれに越したことはないかと思います。

●Queryじゃない、Prepared Statementが大事

MySQLだと、アプリケーションでサーバサイドPrepared Statementをサポートしているライブラリって少ないはず。

「prepare」とか「bind」とかのメソッドがあっても、実はサーバに送るときはQueryになってたりします。

(いわゆるクライアントサイドPrepared Statementというやつですね)

でもMySQLだと、Queryでも全然問題ないほど、構文解析が速いので、

構文解析キャッシュの恩恵を受けられるPrepared Statementを使う必要性は低いのです。

※Prepared Statementを使うと、バイナリプロトコルになるという話もありますが、ここでは割愛。

しかし、Spannerでは、構文解析の負荷は高く、

Prepared Statementを使って、構文解析キャシュの恩恵を受けに行かないと、パフォーマンスがでません。

これは以下にも書いてあるとおりです。

https://cloud.google.com/spanner/docs/sql-best-practices?hl=ja

Queryだと、本当にびっくりするぐらいパフォーマンスでないです。

●1回のSELECTで効果的にデータを取得する

「INTERLEAVE」と「ARRAY STRUCT」が重要です。

「INTERLEAVE」で親と子のテーブルをできるだけ同じノードに閉じ込め、

「ARRAY STRUCT」でまとめてとってくるのがポイントです。

以下に書いてあるとおりです。

https://medium.com/google-cloud-jp/cloud-spanner-%E3%81%A7%E3%82%A4%E3%83%B3%E3%82%BF%E3%83%BC%E3%83%AA%E3%83%BC%E3%83%96%E3%83%86%E3%83%BC%E3%83%96%E3%83%AB%E3%82%92%E9%AB%98%E9%80%9F%E3%81%AB%E5%8F%96%E5%BE%97%E3%81%99%E3%82%8B-2a955b061d3

とはいえ、ARRAY STRUCTでとってきたデータを、オブジェクトにマッピングするのは結構難しいです。

GO言語なんかはライブラリレベルでサポートされているようですが、

他の言語では、自前で解析する必要があります。

上記3つが大きなポイントとなるかと思います。

それ以外にも注意すべきは、「Writeが速くない」ということでしょうか。

UPDATEやDELETEはある意味仕方ないですが、

BULK INSERTについては、UNNESTを上手く使うことで、パフォーマンス向上は可能かと思います。

UNNESTはWHERE INの文脈で使われることが多いかと思いますが、INSERTでも利用できるようです。

※すいません、自分がこれは試してないです。

PostgreSQLでサポートされているので、対応されているのでしょうか。。

他には最近リリースされたINSERT OR UPDATE構文なんかも使えるかもしれません。

ただし、INSERT OR UPDATEについては、ユニークキーがある場合の挙動について、

↓のドキュメントには記載されていません。

https://cloud.google.com/spanner/docs/reference/standard-sql/dml-syntax#insert-or-update

なので、ちょっと試してみました。

まず、こんなテーブルを作ります。

CREATE TABLE  UsersUnique
  ( Id STRING(255) NOT NULL,
    Name STRING(255) NOT NULL,
    Age INT64 NOT NULL,
    )
PRIMARY KEY  (Id);
  CREATE UNIQUE INDEX uk_UsersUnique_Name ON  UsersUnique(Name);

以下のようなデータを入れておきます。

Id  Name  Age
0123456789  Aさん  20
9876543210  Bさん  40 

次に、以下のようなINSERTを流します。

insert or update UsersUnique (Id, Name, Age) values ('0123456789', 'Bさん', 30);

流した結果、

Unique index violation on index uk_UsersUnique_Name at index key [B343201225343202223,9876543210]. It conflicts with row [9876543210] in table UsersUnique.

となりました。

つまり、主キーで置き換えようとしたが、ユニーク制約で引っ掛かった形となりました。

MySQLでは「replace into」といういわゆるUPSERTがあるのですが、

これを使うと、ユニーク制約で削除され、主キーが置き換えられます。

つまり、以下のような結果になります。

Id  Name  Age
0123456789  Bさん  30

DBMSによって、挙動は違いますが、ユニーク制約がある場合はUPSERTには注意を払いましょう。

あれこれ書いてきましたが、

Spannerは簡単にスケールアウト・スケールインできるのは、本当にすごいなと思いました。

とはいえ、やはり特性をよく知って使わないといけないなということは痛感しています。

(謝辞)

本件のSpanner検証にあたっては、ArmadaSuit さんに尽力いただきました。

ありがとうございました。

彼が作った、cgoによるMySQL/PostgreSQLのUDFは、非常に素晴らしいので、紹介させていただきます。

https://github.com/ArmadaSuit/udf-go

これは、新しいバージョンでのGO言語での書き方で、以前私が作っていたようなUDFより、

洗練されたものとなっています。

以上

投稿日時:2024年03月10日 00:12   カテゴリー:gcp, mariadb, mysql   [コメントがあればどうぞ]

fluentdのHTTP OUTPUTって、意外と使われてないのか、

マニュアルを見たのですが、ちょっと引っかかったので、

備忘録がてら設定晒そうかと。

(fluentd http out の公式マニュアル)

https://docs.fluentd.org/output/http


とりあえず、設定です。

なおバージョンは、1.16.2です。

<source>
  @type forward
  port 24224
</source>
<match **>
  @type http
  endpoint http://host.docker.internal:8080/Store/${tag}
  http_method post 
  json_array false
  open_timeout 3
  read_timeout 3
  retryable_response_codes [503]
  <format>
    @type json
  </format>
  <buffer tag>
    @type file
    path /fluentd/log/transfer/buffer/
    chunk_limit_size 1m
    retry_wait 10s
    retry_max_times 3
    flush_mode interval
    flush_interval 1m
    flush_at_shutdown true
  </buffer>
</match>

endpointに${tag}という変数を使う場合、

bufferに書かないといけないというのがまずつまりました。(必須というのがわからんかった)

あとは、endpointに環境変数とかも使えるのかと思いきや、どうやら使えないようで、

このあたりも同時にハマったポイントでした。

その他、いつのバージョンからか、bufferの書き方もかなり変わっており、

このあたりもマニュアル見つつ、動かしながら確認しました。

fluentdはバージョンアップすると、結構書き方が変わっていたり、

パラメータが変更になっていたりと、なかなか注意が必要です。

とはいえ、相変わらず重宝しているfluentdです。

ちなみに、個人的に作成しているFluentNettingなんてものもあります。

https://www.nuget.org/packages/FluentNetting/

こいつはFORWARD OUPUTを受信するサーバですが、

ヘルスチェックなんかも持っているので、おすすめです。

以上

投稿日時:2024年02月14日 23:51   カテゴリー:fluentd   [コメントがあればどうぞ]

ebonyrack 0.5.2 のリリースとともに、日本語マニュアルを追加しました。

(リリース)

https://github.com/shigenobu/ebonyrack/releases

(マニュアル)

https://github.com/shigenobu/ebonyrack/blob/master/manual/manual.ja.md

これでかなりわかりやすくなったと思うので、

利用者が増えてくれると嬉しいと思っていたりする自分がいます。。


0.5.2 では大掛かりな変更はないのですが、

HTML出力で、これまで<map><area>タグで制御していた部分を、

<svg><rect>タグで制御するように変更しました。

なぜ、svgを採用したかというと、mapだとクリックした場所を目立たせるというようなことが難しく、

そこでsvgとすることでクリックした場所を目立たせるようにすることが可能となりました。

<img usemap="#components" id="image" src="data:image/png;base64,..."/>
<map name="components">
  <area id="a" shape="rect" coords="10,10,20,20"/>
  <area id="b" shape="rect" coords="20,20,30,30"/>
  <area id="c" shape="rect" coords="30,30,40,40"/>
</map>
<script type="text/javascript">
var es = document.querySelectorAll("area");
for (let i = 0; i < es.length; i++) {
  es[i].addEventListener('click', (e) => {
    // ダイアログを表示する処理
  });
}
</script>
<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100">
  <image href="data:image/png;base64,..." width="100" height="100"/>
  <rect id="a" x="10" y="10" width="10" height="10" fill="red" fill-opacity="0" stroke="red" stroke-opacity="0"/>
  <rect id="b" x="20" y="20" width="10" height="10" fill="red" fill-opacity="0" stroke="red" stroke-opacity="0"/>
  <rect id="c" x="30" y="30" width="10" height="10" fill="red" fill-opacity="0" stroke="red" stroke-opacity="0"/>
</svg>
<script type="text/javascript">
var es = document.querySelectorAll("rect");
for (let i = 0; i < es.length; i++) {
  es[i].addEventListener('click', (e) => {
    // opacityの操作(他のrectのopacityを戻す操作は割愛)
    es[i].setAttribute("fill-opacity", "0.2");
    es[i].setAttribute("stroke-opacity", "1");
  
    // ダイアログを表示する処理
  });
}
</script>

見ていただければわかるかと思うのですが、

svgでrectを作っておき、不可視状態(opacityを0)にしておき、

クリックイベントで可視状態(opacityを0以外)にするというものです。

mapだと、areaのどこをクリックしたのかわかりずらかったものが、

svgとrectを使うことでクリックした場所(対応するオブジェクト)をわかりやすく表示できるようになります。

イメージを添付しておきます。

(初期状態)

(クリック後)※ダイアログが立ち上がっていますが、赤くなっていることがわかるかと。

意外とこういうことをコードレベルでやっている人は少ないようで、

svgの仕様見ながら試行錯誤で書いてみました。

今後は、積極的にsvgを活用するのもありだなと思っています。

以上

投稿日時:2024年02月14日 23:36   カテゴリー:html, java, mariadb, mysql   [コメントがあればどうぞ]

ebonyrack 0.5.0 をリリースしました。(最近こればかり。。)

https://github.com/shigenobu/ebonyrack/releases

0.4.0 から 0.5.0 での機能追加は以下のとおりです。

  • テーブルからクラス作成(一括・個別)
  • DDLインポートの個別対応
  • テーブル・シーケンス・ノートのコピー&ペイスト
  • DDLに関連するノートの情報をdocコメントとして記載

その他、諸々細かな修正等はありますが、

今回の中では「テーブルからクラス作成」が比較的大きな機能かなと。

これはテンプレートにテーブル情報を渡して、

そのテンプレートをレンダリングすることでクラス(ソースコード)の生成が出来るというものです。

テンプレートは、Velocityの機能が使えるので、他テンプレートを取り込んだりすることもできます。

テンプレートはカスタマイズ可能です。

テンプレートは、

~/.ebonyrack/template/

ディレクトリ以下に配備します。起動時にサンプルが配備されます。

「Sample.java.vm」というように、「{識別名}.{出力したい拡張子}.vm」としてください。

「コピー&ペイスト」もかなり大変ではあったのですが、ひとまずできてます。

とはいえ、コピー時に参照をコピーするだけで、ペイスト時に複製をかける仕組みにしているため、

コピーからペイストの間に、元データに修正が入ると、ペイストされたデータも同様の変更が入るようになってます。

そもそも、コピー&ペイストとして、これがあっているかはわからないのですが、

ひとまずそんな感じになってます。

だいぶできたのですが、少し忙しくなりそうなので、

ebonyrackの機能追加は見合わせようかなと。

もちろん、不具合あれば修正していきますが、

時間みて、操作マニュアル等のドキュメント作成をしていこうかと考えています。

改めて、0.5.0 での機能は以下のようになってます。

  • テーブル作成
  • シーケンス作成
  • ノート作成
  • データのWrite out → JSONを出力するので、バージョン管理で使えるかも
  • データのRead in → Write outされたJSONを取り込めるので、作業者以外はいいかも
  • DDLのImport(最初に一括と、個別で追加)
  • DDLの出力(一括と個別)
  • 画像の出力
  • HTMLの出力 → 本アプリを使わない作業者にいいかも
  • クラス用ソースコード生成(一括と個別)

機能としては、一通り出揃った感はあるので、

今後としては、使い勝手の向上、見栄えの向上、パフォーマンス調整とかでしょうか。

使ってくれる人がいれば嬉しいです。

以上

投稿日時:2024年01月26日 16:19   カテゴリー:java, mariadb, mysql   [コメントがあればどうぞ]