Derbyソースコード分析--JDBC実現(二)


JDBC 4.0に対して、java.sql.Connectionのネットワークサーバと組み込みの実現類は、それぞれNetConnection 40とEmbodConnection 40であることが分かりました。
次に、組み込み方式を例にとって、ResultSetの取得手順を説明します。
一般的な呼び出しプロセスは次のようになるべきです。
	Connection conn = DriverManager.getConnection(url, "username", "password");
	Statement stmt = conn.createStatement();
	ResultSet rs = stmt.executeQuery("select * from table");
	while(rs.next()){
		......
	}
EmbodConnection 40の父親クラスorg.apache.dersby.impl.jdbc.EmbodConnectionで龚骱createStation()の実現を見つけることができます。
	public final Statement createStatement() throws SQLException {
		return createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY, connectionHoldAbility);
	}

	public final Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability)
			throws SQLException {
		checkIfClosed();
		/*    factory                Connection     ,  JDBC4.0  Driver40    */
		return factory.newEmbedStatement(this, false, setResultSetType(resultSetType), resultSetConcurrency,
				resultSetHoldability);
	}
次はnewEmbodStatiment()の実現を見て、JDBC 4.0に対してorg.apache.dersby.jdbc.Driver 40にこの方法の実現を探しに行きます。
	public java.sql.Statement newEmbedStatement(EmbedConnection conn, boolean forMetaData, int resultSetType,
			int resultSetConcurrency, int resultSetHoldability) {
		return new EmbedStatement40(conn, forMetaData, resultSetType, resultSetConcurrency, resultSetHoldability);
	}
Sttementの実現はorg.apache.dersby.impl.jdbc.EmbodStartement 40であることが分かります。その親タイプのEmbodStatementでexecuteQueryを定義しました。
	public java.sql.ResultSet executeQuery(String sql) throws SQLException {
		execute(sql, true, false, Statement.NO_GENERATED_KEYS, null, null);

		if (SanityManager.DEBUG) {
			if (results == null)
				SanityManager.THROWASSERT("no results returned on executeQuery()");
		}

		return results;
	}

	private boolean execute(String sql, boolean executeQuery, boolean executeUpdate, int autoGeneratedKeys,
			int[] columnIndexes, String[] columnNames) throws SQLException {
		synchronized (getConnectionSynchronization()) {

			checkExecStatus();
			if (sql == null) {
				throw newSQLException(SQLState.NULL_SQL_TEXT);
			}
			checkIfInMiddleOfBatch();

			/*      Statement   ResultSet */
			clearResultSets();

			setupContextStack();

			SQLText = sql;

			try {
				/*   Activation   */
				Activation activation;
				try {
					PreparedStatement preparedStatement = lcc.prepareInternalStatement(lcc.getDefaultSchema(), sql,
							resultSetConcurrency == java.sql.ResultSet.CONCUR_READ_ONLY, false);
					activation = preparedStatement.getActivation(lcc,
							resultSetType == java.sql.ResultSet.TYPE_SCROLL_INSENSITIVE);
					checkRequiresCallableStatement(activation);
				} catch (Throwable t) {
					throw handleException(t);
				}

				activation.setSingleExecution();

				if (autoGeneratedKeys == Statement.RETURN_GENERATED_KEYS)
					activation.setAutoGeneratedKeysResultsetInfo(columnIndexes, columnNames);

				/*   Statement */
				return executeStatement(activation, executeQuery, executeUpdate);
			} finally {
				restoreContextStack();
			}
		}
	}
ここではまずlccという実例に対応するorg.apache.dersby.iapi.sql.com.Language Connection Contect類の役割を見ます。
まずlccの実用化はEmbodStatitementの構造関数で行い、
	public EmbedStatement(EmbedConnection connection, boolean forMetaData, int resultSetType, int resultSetConcurrency,
			int resultSetHoldability) {
		super(connection);
		this.forMetaData = forMetaData;
		this.resultSetType = resultSetType;
		this.resultSetConcurrency = resultSetConcurrency;
		this.resultSetHoldability = resultSetHoldability;

		/*     lcc      */
		lcc = getEmbedConnection().getLanguageConnection();
		applicationConnection = getEmbedConnection().getApplicationConnection();
		applicationStatement = this;
	}
この方法はEmbodConnectionで見つけられます。finalです。
	public final LanguageConnectionContext getLanguageConnection() {

		if (SanityManager.DEBUG)
			SanityManager.ASSERT(!isClosed(), "connection is closed");

		return getTR().getLcc();
	}
ここではgetTR()の方法があります。finalのクラスTransactional ResourceImplに戻りました。この種類のJavaDocを見て、データベースとの接続、事務の文脈など、Langugenection Contectの実例を得ることができます。
	LanguageConnectionContext getLcc() {
		return lcc;
	}
ここでlccの例は、startTransation方法で初期化され、
	void startTransaction() throws StandardException, SQLException {
		lcc = database.setupConnection(cm, username, drdaID, dbname);
	}
ここには2つの場所がありますが、一つはいつからですか?もう一つはdatabaseが初期化されたのですか?この問題を知るためにはまずTransation Resource Implの構造関数を見て、そしてEmbodConnectionの構造関数を見てください。
	TransactionResourceImpl(InternalDriver driver, String url, Properties info) throws SQLException {
		/*   JDBC4.0  driver Driver40     */
		this.driver = driver;

		/* csf   org.apache.derby.iapi.services.context.ContextService    */
		/* ContextService               */
		csf = driver.getContextServiceFactory();

		dbname = InternalDriver.getDatabaseName(url, info);
		this.url = url;

		username = IdUtil.getUserNameFromURLProps(info);

		drdaID = info.getProperty(Attribute.DRDAID_ATTR, null);

		// ContextManager  ,  ContextManager  push  org.apache.derby.iapi.services.context.SystemContext ContextManager 
		cm = csf.newContextManager();
	}
Transation Resource Implのコンストラクタでは、Contect Service(csf)とContect Manager(cm)を初期化しました。
そしてEmbodConnectionの構造関数を見てみます。これは比較的長いです。中間は一部を省略しました。
	public EmbedConnection(InternalDriver driver, String url, Properties info) throws SQLException {
		// rootConnection
		applicationConnection = rootConnection = this;

		//   JDBC4.0  driver Driver40    
		factory = driver;

		//       TransactionResourceImpl
		tr = new TransactionResourceImpl(driver, url, info);

		active = true;

		//  ContextManager  ContextService   Manager
		setupContextStack();

		try {
			//      EmbedConnectionContext  ,  push  Context ContextManager 
			EmbedConnectionContext context = pushConnectionContext(tr.getContextManager());

			boolean shutdown = Boolean.valueOf(info.getProperty(Attribute.SHUTDOWN_ATTR)).booleanValue();

			//   database       , modules.properties     org.apache.derby.impl.db.BasicDatabase
			Database database = (Database) Monitor.findService(Property.DATABASE_MODULE, tr.getDBName());

			//                 
			boolean createBoot = createBoot(info);

			boolean isTwoPhaseEncryptionBoot = (!createBoot && isEncryptionBoot(info));
			boolean isTwoPhaseUpgradeBoot = (!createBoot && isHardUpgradeBoot(info));
			/*              "startSlave",      Replication slave   */
			/*      Master-Slave          */
			boolean isStartSlaveBoot = isStartReplicationSlaveBoot(info);

			boolean slaveDBAlreadyBooted = false;

			boolean isFailoverMasterBoot = false;
			boolean isFailoverSlaveBoot = false;

			......
			......

			if (database != null) {// database     
				tr.setDatabase(database);
				isTwoPhaseEncryptionBoot = false;
				isTwoPhaseUpgradeBoot = false;
			} else if (!shutdown) {
				if (isTwoPhaseEncryptionBoot || isTwoPhaseUpgradeBoot) {
					savedInfo = info;
					info = removePhaseTwoProps((Properties) info.clone());
				}

				if (!bootDatabase(info, isTwoPhaseUpgradeBoot)) {
					tr.clearContextInError();
					setInactive();
					return;
				}
			}

			if (createBoot && !shutdown) {//          database
				if (tr.getDatabase() != null) {
					// database    
					addWarning(SQLWarningFactory.newSQLWarning(SQLState.DATABASE_EXISTS, getDBName()));
				} else {
					checkUserCredentials(null, info);
					//       
					database = createDatabase(tr.getDBName(), info);
					/*   database    TransactionResourceImpl*/
					tr.setDatabase(database);
				}
			}

			if (tr.getDatabase() == null) {// database    
				handleDBNotFound();
			}

			try {
				//          
				checkUserCredentials(tr.getDBName(), info);
			} catch (SQLException sqle) {
				if (isStartSlaveBoot && !slaveDBAlreadyBooted) {
					tr.startTransaction();
					handleException(tr.shutdownDatabaseException());
				}
				throw sqle;
			}

			//     lcc      ,           
			tr.startTransaction();			

			......
			......

		} catch (OutOfMemoryError noMemory) {
			restoreContextStack();
			tr.lcc = null;
			tr.cm = null;

			memoryState.setLowMemory();

			throw NO_MEM;
		} catch (Throwable t) {
			if (t instanceof StandardException) {
				StandardException se = (StandardException) t;
				if (se.getSeverity() < ExceptionSeverity.SESSION_SEVERITY)
					se.setSeverity(ExceptionSeverity.SESSION_SEVERITY);
			}
			tr.cleanupOnError(t);
			throw handleException(t);
		} finally {
			restoreContextStack();
		}
	}
ここでは、EmbodConnectionのコンストラクタにおいて、Transaction Resource Impl(tr)の初期化、databaseの作成と有効化など、多くの研究が必要なところがあります。