⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mysqlio.java

📁 基于b/s的网上书店
💻 JAVA
📖 第 1 页 / 共 5 页
字号:
/*
   Copyright (C) 2002 MySQL AB

      This program is free software; you can redistribute it and/or modify
      it under the terms of the GNU General Public License as published by
      the Free Software Foundation; either version 2 of the License, or
      (at your option) any later version.

      This program is distributed in the hope that it will be useful,
      but WITHOUT ANY WARRANTY; without even the implied warranty of
      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      GNU General Public License for more details.

      You should have received a copy of the GNU General Public License
      along with this program; if not, write to the Free Software
      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

 */
package com.mysql.jdbc;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.EOFException;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;

import java.lang.ref.SoftReference;

import java.net.Socket;

import java.security.NoSuchAlgorithmException;

import java.sql.SQLException;
import java.sql.SQLWarning;

import java.util.ArrayList;
import java.util.Properties;
import java.util.zip.Deflater;
import java.util.zip.Inflater;


/**
 * This class is used by Connection for communicating with the MySQL server.
 *
 * @author Mark Matthews
 * @version $Id: MysqlIO.java,v 1.32.2.46 2004/02/06 00:54:42 mmatthew Exp $
 *
 * @see java.sql.Connection
 */
public class MysqlIO {
    static final int NULL_LENGTH = ~0;
    static final int COMP_HEADER_LENGTH = 3;
    static final int MIN_COMPRESS_LEN = 50;
    static final int HEADER_LENGTH = 4;
    private static int maxBufferSize = 65535;
    private static final int CLIENT_COMPRESS = 32; /* Can use compression
    protcol */
    private static final int CLIENT_CONNECT_WITH_DB = 8;
    private static final int CLIENT_FOUND_ROWS = 2;
    private static final int CLIENT_IGNORE_SPACE = 256; /* Ignore spaces
    before '(' */
    private static final int CLIENT_LOCAL_FILES = 128; /* Can use LOAD DATA
    LOCAL */

    /* Found instead of
       affected rows */
    private static final int CLIENT_LONG_FLAG = 4; /* Get all column flags */
    private static final int CLIENT_LONG_PASSWORD = 1; /* new more secure
    passwords */
    private static final int CLIENT_PROTOCOL_41 = 512; // for > 4.1.1
    private static final int CLIENT_INTERACTIVE = 1024;
    private static final int CLIENT_SSL = 2048;
    private static final int CLIENT_RESERVED = 16384; // for 4.1.0 only
    private static final int CLIENT_SECURE_CONNECTION = 32768;
    private static final String FALSE_SCRAMBLE = "xxxxxxxx";

    /**
     * We store the platform 'encoding' here, only used to avoid munging
     * filenames for LOAD DATA LOCAL INFILE...
     */
    private static String jvmPlatformCharset = null;

    static {
        OutputStreamWriter outWriter = null;

        //
        // Use the I/O system to get the encoding (if possible), to avoid
        // security restrictions on System.getProperty("file.encoding") in
        // applets (why is that restricted?)
        //
        try {
            outWriter = new OutputStreamWriter(new ByteArrayOutputStream());
            jvmPlatformCharset = outWriter.getEncoding();
        } finally {
            try {
                outWriter.close();
            } catch (IOException ioEx) {
                // ignore
            }
        }
    }

    //
    // Use this when reading in rows to avoid thousands of new()
    // calls, because the byte arrays just get copied out of the
    // packet anyway
    //
    private Buffer reusablePacket = null;
    private Buffer sendPacket = null;
    private Buffer sharedSendPacket = null;

    /** Data to the server */

    //private DataOutputStream     _Mysql_Output             = null;
    private BufferedOutputStream mysqlOutput = null;
    private com.mysql.jdbc.Connection connection;
    private Deflater deflater = null;
    private Inflater inflater = null;

    /** Buffered data from the server */

    //private BufferedInputStream  _Mysql_Buf_Input          = null;

    /** Buffered data to the server */

    //private BufferedOutputStream _Mysql_Buf_Output         = null;

    /** Data from the server */

    //private DataInputStream      _Mysql_Input              = null;
    private InputStream mysqlInput = null;
    private RowData streamingData = null;

    //
    // For SQL Warnings
    //
    private SQLWarning warningChain = null;

    /** The connection to the server */
    private Socket mysqlConnection = null;
    private SocketFactory socketFactory = null;

    //
    // Packet used for 'LOAD DATA LOCAL INFILE'
    //
    // We use a SoftReference, so that we don't penalize intermittent
    // use of this feature
    //
    private SoftReference loadFileBufRef;

    //
    // Used to send large packets to the server versions 4+
    // We use a SoftReference, so that we don't penalize intermittent
    // use of this feature
    //
    private SoftReference splitBufRef;
    private String host = null;
    private String seed;
    private String serverVersion = null;
    private String socketFactoryClassName = null;
    private byte[] packetHeaderBuf = new byte[4];
    private boolean clearStreamBeforeEachQuery = false;
    private boolean colDecimalNeedsBump = false; // do we need to increment the colDecimal flag?
    private boolean has41NewNewProt = false;

    /** Does the server support long column info? */
    private boolean hasLongColumnInfo = false;
    private boolean isInteractiveClient = false;

    /**
     * Does the character set of this connection match the character set of the
     * platform
     */
    private boolean platformDbCharsetMatches = true;
    private boolean profileSql = false;

    /** Should we use 4.1 protocol extensions? */
    private boolean use41Extensions = false;
    private boolean useCompression = false;
    private boolean useNewLargePackets = false;
    private boolean useNewUpdateCounts = false; // should we use the new larger update counts?
    private byte packetSequence = 0;
    private byte protocolVersion = 0;
    private int clientParam = 0;

    // changed once we've connected.
    private int maxAllowedPacket = 1024 * 1024;
    private int maxThreeBytes = 255 * 255 * 255;
    private int port = 3306;
    private int serverMajorVersion = 0;
    private int serverMinorVersion = 0;
    private int serverSubMinorVersion = 0;

    /**
     * Constructor:  Connect to the MySQL server and setup a stream connection.
     *
     * @param host the hostname to connect to
     * @param port the port number that the server is listening on
     * @param socketFactoryClassName the socket factory to use
     * @param props the Properties from DriverManager.getConnection()
     * @param conn the Connection that is creating us
     * @param socketTimeout the timeout to set for the socket (0 means no
     *        timeout)
     *
     * @throws IOException if an IOException occurs during connect.
     * @throws java.sql.SQLException if a database access error occurs.
     */
    protected MysqlIO(String host, int port, String socketFactoryClassName,
        Properties props, com.mysql.jdbc.Connection conn, int socketTimeout)
        throws IOException, java.sql.SQLException {
        this.connection = conn;
        this.reusablePacket = new Buffer(this.connection.getNetBufferLength());
        this.port = port;
        this.host = host;
        this.socketFactoryClassName = socketFactoryClassName;
        this.socketFactory = createSocketFactory();
        this.mysqlConnection = socketFactory.connect(this.host, props);
        this.clearStreamBeforeEachQuery = this.connection.alwaysClearStream();

        if (socketTimeout != 0) {
            try {
                this.mysqlConnection.setSoTimeout(socketTimeout);
            } catch (Exception ex) {
                /* Ignore if the platform does not support it */
            }
        }

        this.mysqlConnection = this.socketFactory.beforeHandshake();

        if (!this.connection.isUsingUnbufferedInput()) {
            this.mysqlInput = new BufferedInputStream(this.mysqlConnection
                    .getInputStream(), 16384);
        } else {
            this.mysqlInput = this.mysqlConnection.getInputStream();
        }

        this.mysqlOutput = new BufferedOutputStream(this.mysqlConnection
                .getOutputStream(), 16384);
        this.isInteractiveClient = this.connection.isInteractiveClient();
    }

    /**
     * Should the driver generate SQL statement profiles?
     *
     * @param flag should the driver enable profiling?
     */
    protected void setProfileSql(boolean flag) {
        this.profileSql = flag;
    }

    /**
     * Build a result set. Delegates to buildResultSetWithRows() to build a
     * JDBC-version-specific ResultSet, given rows as byte data, and field
     * information.
     *
     * @param columnCount the number of columns in the result set
     * @param maxRows the maximum number of rows to read (-1 means all rows)
     * @param resultSetType the type of result set (CONCUR_UPDATABLE or
     *        READ_ONLY)
     * @param streamResults should the result set be read all at once, or
     *        streamed?
     * @param catalog the database name in use when the result set was created
     *
     * @return a result set
     *
     * @throws Exception if a database access error occurs
     */
    protected ResultSet getResultSet(long columnCount, int maxRows,
        int resultSetType, boolean streamResults, String catalog)
        throws Exception {
        Buffer packet; // The packet from the server
        Field[] fields = new Field[(int) columnCount];

        // Read in the column information
        for (int i = 0; i < columnCount; i++) {
            packet = readPacket();
            fields[i] = unpackField(packet, false);
        }

        packet = reuseAndReadPacket(this.reusablePacket);

        RowData rowData = null;

        if (!streamResults) {
            ArrayList rows = new ArrayList();

            // Now read the data
            byte[][] rowBytes = nextRow((int) columnCount);
            int rowCount = 0;

            if (rowBytes != null) {
                rows.add(rowBytes);
                rowCount = 1;
            }

            while ((rowBytes != null) && (rowCount < maxRows)) {
                rowBytes = nextRow((int) columnCount);

                if (rowBytes != null) {
                    rows.add(rowBytes);
                    rowCount++;
                } else {
                    if (Driver.TRACE) {
                        Debug.msg(this, "* NULL Row *");
                    }
                }
            }

            //
            // Clear any outstanding data left on the wire
            // when we've artifically limited the number of 
            // rows we retrieve (fix for BUG#1695)
            //
            if (rowCount <= maxRows) {
                clearInputStream();
            }

            if (Driver.TRACE) {
                Debug.msg(this,
                    "* Fetched " + rows.size() + " rows from server *");
            }

            rowData = new RowDataStatic(rows);
            reclaimLargeReusablePacket();
        } else {
            rowData = new RowDataDynamic(this, (int) columnCount);
            this.streamingData = rowData;
        }

        return buildResultSetWithRows(catalog, fields, rowData, resultSetType);
    }

    /**
     * Forcibly closes the underlying socket to MySQL.
     */
    protected final void forceClose() {
        try {
            if (this.mysqlInput != null) {
                this.mysqlInput.close();
            }
        } catch (IOException ioEx) {
            // we can't do anything constructive about this
            // Let the JVM clean it up later
            this.mysqlInput = null;
        }

        try {
            if (this.mysqlOutput != null) {
                this.mysqlOutput.close();
            }
        } catch (IOException ioEx) {
            // we can't do anything constructive about this
            // Let the JVM clean it up later
            this.mysqlOutput = null;
        }

        try {
            if (this.mysqlConnection != null) {
                this.mysqlConnection.close();
            }
        } catch (IOException ioEx) {
            // we can't do anything constructive about this
            // Let the JVM clean it up later
            this.mysqlConnection = null;
        }
    }

    /**

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -