« 2006年1月 | トップページ | 2006年3月 »

2006年2月22日 (水)

ORA-00918: column ambiguously defined

こんにちは。
技術系のネタは超がつく久々ですね…
ネタは割とあるんですけど、
守秘義務に引っかかりそうな気がしないでもないです。

さて、現在、携わるシステムの機能追加を実装しています。
DBのカラム追加が伴う修正で、
とある時点のとある情報を保持する必要が出てきたらしく、
とあるテーブルと同じカラム名で関連するとあるテーブルにカラムを追加したんです。
(データベース的にこの対応はどうなのかというのはよく分かりません…)

このシステム、DBアクセスは割と、というか、かなりベタなJDBCでやっておりまして、直接関連する機能のアクセスクラスのSQLを修正したり、その他諸々修正してテストしていたんです。

すると、目的の機能の前画面ぐらいのところで、

ORA-00918: column ambiguously defined(列の定義が未確定です)

なんて言うエラーが出て動作確認したい画面まで到達できません。
直接関係無い機能ですが、エラーが出る以上調査しないといけません。
他人の書いたコードを辿っていきます…

まあ、このエラーコードをググッて出てくる情報の通り、JOINやら何やらしているSQLで複数テーブルに同一のカラム名が存在する場合に、このSQLではどっちのカラムのデータのことか分かりませんぜ、って時に出るんですが、パッと該当SQLを見ても、エイリアスでもなく、フルでテーブル名を先頭に記述して「大体は」記述しています。

おかしいなぁと思いながらSQL先頭から舐めるように見ていくと、ありました。
DECODE関数の第1引数に1個だけテーブル指定の無いカラムが。

今までJOINするテーブル片方にしかカラムがなかったので通っていましたが、同じカラム名でもう片方のテーブルに追加したため、エラーになっていたのでした。

えーっと、これって、ほぼ全てのSQLをチェックしないとまずいかも…
と途方にくれる午後4時半…

P.S.
後から追加するカラムはあえてどことも被らない名前にする、とか決めたりするもんなんでしょうかね?

| | コメント (0) | トラックバック (1)

2006年2月 2日 (木)

[Log4j]設定ファイル(log4j.xml)

私が参加するシステムも一部で本稼動が始まりました。
東京ガスのシステムほど費用はかかっていないようですが、
まぁ、致命的なシステムダウンなどは今のところないようです…

そこで、今まで基本的にデバッグモードだったログ出力も、
本格的に運用が始まると、デバッグ出力は必要ありません。

そこで、Log4jの設定ファイル、log4j.xmlを見直していました。
気になった点は、rootロガーの子要素、priority要素の指定方法です。

[log4j.dtd抜粋]
<!-- If no priority element is specified, then the configurator MUST not -->
<!-- touch the priority of root. -->
<!-- The root category always exists and cannot be subclassed. -->
<!ELEMENT root (param*, (priority|level)?, appender-ref*)>

[log4j.xml抜粋]
<root>
  <priority value="trace" />
  <appender-ref ref="CONSOLE" />
</root>

今まで深くこの設定ファイルを見たことがなく、
元々他人が設定した内容だったので、
深く考えていませんでしたが、
パッと見て私が解釈したのは、

rootロガーがアプリケーションからログ出力として受けたメッセージは、
traceプライオリティに変換してCONSOLEアペンダーに渡される。

でも、この解釈が正解ならば、ちょっとおかしなことになるはずなんです。
というのも、今まで何回かログの出力レベルを変更した時は、
アペンダーの子要素のfilter要素でLevelRangeFilterを定義していて、
そのパラメータのlevelMinをDEBUGにしたりINFOにしたりしていました。

プライオリティが変換されると、levelMinをINFOにした時は、
アプリケーションからたとえプライオリティFATALで出力がきても、
traceに変換されてしまうため、TRACE < INFOとなり、
アペンダーで出力されないことになりますが、
そうではありませんでした。

そこでWebを検索して見つけたページは、

第9回 効率的なログ出力をCommonsで実現

で、そこには、

すべてのカテゴリに対するログを設定するには、
次のように<root>要素で設定します。

<root>
  <priority value="info" />
  <appender-ref ref="STDOUT" />
  <appender-ref ref="DAILY" />
</root>

この例では、<appender>要素で定義したSTDOUTアペンダと
DAILYアペンダのすべてのカテゴリに対して
infoレベルでログを出力します。

とあります。
これを私なりに解釈すると、
やっぱりinfoレベルに変換されるように思える(思えていた)のですが、
ひょっとして、rootロガーの前にcategory要素を定義すると、
そこに対しては変換されるんでしょうか?(未確認)

Log4jってrootロガーだけで運用することは想定していない?
rootロガー単独の場合はpriority要素の設定は意味をなさない?
と疑問に思いながら、rootロガーのpriority要素の値と、
appenderのLevelRangeFilterのフィルター範囲をいじり倒して出した結論。

プライオリティ(レベル)が変換されるのではなく、フィルタされる。
※ただし、現状確認できたのはrootロガーのみの場合

例えば、rootロガーの子要素でpriorityをinfoに設定した場合、
アプリケーションからのLogger.debug("hoge")はappenderに渡らない。
よって、appenderのレベルフィルタが定義されていなくても、
ロギングされない。
(同じプライオリティのLogger.info("hoge")は渡るようです)
要は2回フィルタリングされるわけですね、
appenderでLevelRangeFilterも定義した場合は。

ということは、誰ぞが設定したpriorityのtraceって意味無いんじゃ?
(最も低い優先度でフィルタする = フィルタなし)
DTD見ても必須じゃないし…

何とか、現状の設定ファイル内容における動作結果は把握できたんですが、
@ITさんの記事の内容がまだイマイチ理解できないなぁ。
categoryを別途定義した時の動作、
同じappenderを複数のロガー(という表現でよいのか?rootとcategoryのこと)で参照した時の動作、
categoryとloggerの違い…

Log4jのこの辺の仕様を深く理解することは、
自分にとっても有用だろうなとは思うんですが、
現状機能追加を実装するにあたって、
どこぞのプロプライエタリなWebアプリケーションフレームワークの
知識の方が必要な状況がイヤだ。(笑)
こんな時代遅れのフレームワークの知識を…(省略)

| | コメント (0) | トラックバック (0)

« 2006年1月 | トップページ | 2006年3月 »