Sybaseの件

manholeさんが、調査して下さいました。ありがとうございます。




早速、付属していた、「SQL Advantage」と言うツールを使って以下のクエリを実行してみました。

sp_dboption 'tempdb' , 'ddl in tran', true


おおおおっ。確かにエラーが出ずに処理が終了します。
んで、昨日は分らなかった、作成されようとしているテーブルはなんだろう…と。
deptテーブルとempテーブルが、tempdbに出来ています……。
何となく感覚的には、メタデータを取るためのシステムテーブルが出来るのかと思ったのですが…。
違ったようです。
え?……。一時表なのに、トランザクションが終了した後も残ってる…不思議だ…。


これは、全く持って、メタデータを取りに行く時にトランザクションが発生しているのがマズいって事なんでしょうか。
と、言う訳で、アヤシイDaoMetaDataFactoryを作ってみました。
DaoMetaDataを生成するタイミングで、Transactionをresumeしてみます。
エラーハンドリングが超テキトーな上に、コピペなのは僕がヘタレだからです。

package org.seasar.dao.impl;

import java.util.HashMap;
import java.util.Map;

import javax.sql.DataSource;
import javax.transaction.Status;
import javax.transaction.Transaction;
import javax.transaction.TransactionManager;

import org.seasar.dao.DaoMetaData;
import org.seasar.dao.DaoMetaDataFactory;
import org.seasar.extension.jdbc.ResultSetFactory;
import org.seasar.extension.jdbc.StatementFactory;
import org.seasar.framework.log.Logger;

/**
 * 
 * @author taichi S. 2005/04/26
 */
public class TransactionalDaoMetaDataFactory implements DaoMetaDataFactory {
    
    private Logger logger = Logger.getLogger(TransactionalDaoMetaDataFactory.class);
    
    private Map daoMetaDataCache_ = new HashMap();

    private DataSource dataSource_;

    private StatementFactory statementFactory_;

    private ResultSetFactory resultSetFactory_;

    private TransactionManager transactionManager_;

    public TransactionalDaoMetaDataFactory(DataSource dataSource,
            StatementFactory statementFactory,
            ResultSetFactory resultSetFactory,
            TransactionManager transactionManager) {

        dataSource_ = dataSource;
        statementFactory_ = statementFactory;
        resultSetFactory_ = resultSetFactory;
        transactionManager_ = transactionManager;
    }

    public synchronized DaoMetaData getDaoMetaData(Class daoClass) {
        String key = daoClass.getName();
        DaoMetaData dmd = (DaoMetaData) daoMetaDataCache_.get(key);
        if (dmd != null) {
            return dmd;
        }
        dmd = create(daoClass);
        daoMetaDataCache_.put(key, dmd);
        return dmd;
    }

    private DaoMetaData create(Class daoClass) {
        Transaction tx = null;
        try {
            if (transactionManager_.getStatus() != Status.STATUS_NO_TRANSACTION) {
                tx = transactionManager_.suspend();
            }
            
            return new DaoMetaDataImpl(daoClass, dataSource_,
                    statementFactory_, resultSetFactory_);
        } catch (Exception e) {
            logger.log(e);
            throw new IllegalStateException();
        } finally {
            if(tx != null) {
                try {
                    transactionManager_.resume(tx);
                } catch(Exception e) {
                    logger.log(e);
                    throw new IllegalStateException();
                }
            }
        }
    }
}


と、言う訳で、動作を確認します。

sp_dboption 'tempdb' , 'ddl in tran', false

を流し、昨日と同じエラーが再現するのを確認しつつ、tempdbに出来たテーブル2つをdropします。
更に、dao.diconを修正します。

<?xml version="1.0" encoding="Shift_JIS"?>
<!DOCTYPE components PUBLIC "-//SEASAR//DTD S2Container//EN"
"http://www.seasar.org/dtd/components.dtd">
<components namespace="dao">
  <include path="j2ee.dicon"/>
  <component class="org.seasar.dao.impl.TransactionalDaoMetaDataFactory"/>
  <component name="interceptor" class="org.seasar.dao.interceptors.S2DaoInterceptor"/>
</components>


実行っとな…………動いた…エラーが出ないデスヨ。
しかし、ddl in tranがtrueの時と動きが違うようです。
何故なら、何度実行してもtempdbにdeptとempが作成されないのです…。
これは一体どういう事なんでしょうか…。
むつかしいです…。


引き続き、太一はSybaseを良く知っている方を募集しています。
コメントかトラックバックを下さい。


今日は眠いので、これ以上調査出来ません。ごめんなさい。