353
pgjdbc/src/test/java/org/postgresql/jdbc/FullTraceTest.java
Normal file
353
pgjdbc/src/test/java/org/postgresql/jdbc/FullTraceTest.java
Normal file
@ -0,0 +1,353 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Huawei Technologies Co., Ltd. 2024-2024. All rights reserved.
|
||||||
|
*
|
||||||
|
* openGauss is licensed under Mulan PSL v2.
|
||||||
|
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||||
|
* You may obtain a copy of Mulan PSL v2 at:
|
||||||
|
*
|
||||||
|
* http://license.coscl.org.cn/MulanPSL2
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||||
|
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||||
|
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||||
|
* See the Mulan PSL v2 for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.postgresql.jdbc;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.postgresql.test.TestUtil;
|
||||||
|
import org.postgresql.test.jdbc2.BaseTest4PG;
|
||||||
|
|
||||||
|
import java.sql.Connection;
|
||||||
|
import java.sql.PreparedStatement;
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.Statement;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* test full trace.
|
||||||
|
*
|
||||||
|
* @author hwhbj
|
||||||
|
* @since 2024-08-20
|
||||||
|
*/
|
||||||
|
public class FullTraceTest extends BaseTest4PG {
|
||||||
|
private static final Integer WAIT_FLUSH_TIME = 1000;
|
||||||
|
private static final String QUERY_STMT_HISTORY = "select db_time, net_trans_time from statement_history "
|
||||||
|
+ "where query like '%s'";
|
||||||
|
private static final String RECORD_FULL_SQL = "set track_stmt_stat_level = 'L0,L0'";
|
||||||
|
private static final String ENABLE_TRACE_SQL = "set enable_record_nettime = on";
|
||||||
|
|
||||||
|
private static Connection createConnection() throws Exception {
|
||||||
|
return TestUtil.openDB();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Connection createConnection(Properties props) throws Exception {
|
||||||
|
return TestUtil.openDB(props);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Connection createConnection(String dbName) throws Exception {
|
||||||
|
return TestUtil.openDB(dbName);
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Integer> recordCount(String sql) throws Exception {
|
||||||
|
String querySql = String.format(QUERY_STMT_HISTORY, sql);
|
||||||
|
try (Connection conn = createConnection("postgres");
|
||||||
|
PreparedStatement pstmt = conn.prepareStatement(querySql);
|
||||||
|
ResultSet rs = pstmt.executeQuery()) {
|
||||||
|
int count1 = 0;
|
||||||
|
int count2 = 0;
|
||||||
|
int count3 = 0;
|
||||||
|
while (rs.next()) {
|
||||||
|
int dbTime = rs.getInt(1);
|
||||||
|
int netTransTime = rs.getInt(2);
|
||||||
|
if (dbTime == 0 && netTransTime == 0) {
|
||||||
|
count1++;
|
||||||
|
} else if (dbTime > 0 && netTransTime == 0) {
|
||||||
|
count2++;
|
||||||
|
} else if (dbTime > 0 && netTransTime > 0) {
|
||||||
|
count3++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Arrays.asList(count1, count2, count3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setRecordFullSql(Connection conn) throws Exception {
|
||||||
|
try (PreparedStatement pstmt = conn.prepareStatement(ENABLE_TRACE_SQL + ";" + RECORD_FULL_SQL)) {
|
||||||
|
pstmt.execute();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void sendPreTimeAndFlush(Connection conn) throws Exception {
|
||||||
|
/* send previous net_time */
|
||||||
|
try (PreparedStatement pstmt = conn.prepareStatement("select 1;")) {
|
||||||
|
pstmt.executeQuery();
|
||||||
|
Thread.sleep(WAIT_FLUSH_TIME);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testExecuteMultiSqlPBE() throws Exception {
|
||||||
|
String sql1 = "drop table if exists t1";
|
||||||
|
String sql2 = "create table t1(id int)";
|
||||||
|
List<Integer> beforeInfoSql1 = recordCount(sql1);
|
||||||
|
List<Integer> beforeInfoSql2 = recordCount(sql2);
|
||||||
|
|
||||||
|
/* PBEPBES */
|
||||||
|
try (Connection conn = createConnection();
|
||||||
|
PreparedStatement pstmt = conn.prepareStatement(sql1 + ";" + sql2)) {
|
||||||
|
setRecordFullSql(conn);
|
||||||
|
pstmt.execute();
|
||||||
|
sendPreTimeAndFlush(conn);
|
||||||
|
|
||||||
|
List<Integer> afterInfoSql1 = recordCount(sql1);
|
||||||
|
List<Integer> afterInfoSql2 = recordCount(sql2);
|
||||||
|
|
||||||
|
assertTrue(beforeInfoSql1.get(0) + 1 == afterInfoSql1.get(0));
|
||||||
|
assertTrue(beforeInfoSql1.get(1) + 1 == afterInfoSql1.get(1));
|
||||||
|
assertTrue(beforeInfoSql1.get(2) == afterInfoSql1.get(2));
|
||||||
|
|
||||||
|
assertTrue(beforeInfoSql2.get(0) + 1 == afterInfoSql2.get(0));
|
||||||
|
assertTrue(beforeInfoSql2.get(1) == afterInfoSql2.get(1));
|
||||||
|
assertTrue(beforeInfoSql2.get(2) + 1 == afterInfoSql2.get(2));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testExecuteBatchPBENoCache() throws Exception {
|
||||||
|
Properties props = new Properties();
|
||||||
|
props.setProperty("prepareThreshold", "0");
|
||||||
|
String sql1 = "drop table if exists t1; create table t1(id int);";
|
||||||
|
String sql2 = "insert into t1 values(?)";
|
||||||
|
String sql2Record = "insert into t1 values(%)";
|
||||||
|
List<Integer> beforeInfoSql2 = recordCount(sql2Record);
|
||||||
|
/* PUES / PUES */
|
||||||
|
try (Connection conn = createConnection(props);
|
||||||
|
Statement stmt = conn.createStatement();
|
||||||
|
PreparedStatement pstmt = conn.prepareStatement(sql2)) {
|
||||||
|
stmt.execute(sql1);
|
||||||
|
setRecordFullSql(conn);
|
||||||
|
|
||||||
|
for (int i = 0; i < 5000; ++i) {
|
||||||
|
pstmt.setInt(1, i);
|
||||||
|
pstmt.addBatch();
|
||||||
|
}
|
||||||
|
pstmt.executeBatch();
|
||||||
|
for (int i = 0; i < 5000; ++i) {
|
||||||
|
pstmt.setInt(1, i);
|
||||||
|
pstmt.addBatch();
|
||||||
|
}
|
||||||
|
pstmt.executeBatch();
|
||||||
|
sendPreTimeAndFlush(conn);
|
||||||
|
|
||||||
|
List<Integer> afterInfoSql2 = recordCount(sql2Record);
|
||||||
|
|
||||||
|
assertTrue(beforeInfoSql2.get(0) + 2 == afterInfoSql2.get(0));
|
||||||
|
assertTrue(beforeInfoSql2.get(1) == afterInfoSql2.get(1));
|
||||||
|
assertTrue(beforeInfoSql2.get(2) + 2 == afterInfoSql2.get(2));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testExecuteBatchPBEUseCache() throws Exception {
|
||||||
|
Properties props = new Properties();
|
||||||
|
props.setProperty("prepareThreshold", "1");
|
||||||
|
String sql1 = "drop table if exists t1; create table t1(id int);";
|
||||||
|
|
||||||
|
String sql2 = "insert into t1 values(?)";
|
||||||
|
String sql2Record = "insert into t1 values(%)";
|
||||||
|
List<Integer> beforeInfoSql2 = recordCount(sql2Record);
|
||||||
|
|
||||||
|
/* P/DS/S / UES / UES */
|
||||||
|
try (Connection conn = createConnection(props);
|
||||||
|
Statement stmt = conn.createStatement();
|
||||||
|
PreparedStatement pstmt = conn.prepareStatement(sql2)) {
|
||||||
|
stmt.execute(sql1);
|
||||||
|
setRecordFullSql(conn);
|
||||||
|
for (int i = 0; i < 5000; ++i) {
|
||||||
|
pstmt.setInt(1, i);
|
||||||
|
pstmt.addBatch();
|
||||||
|
}
|
||||||
|
pstmt.executeBatch();
|
||||||
|
for (int i = 0; i < 5000; ++i) {
|
||||||
|
pstmt.setInt(1, i);
|
||||||
|
pstmt.addBatch();
|
||||||
|
}
|
||||||
|
pstmt.executeBatch();
|
||||||
|
sendPreTimeAndFlush(conn);
|
||||||
|
|
||||||
|
List<Integer> afterInfoSql2 = recordCount(sql2Record);
|
||||||
|
|
||||||
|
assertTrue(beforeInfoSql2.get(0) + 1 == afterInfoSql2.get(0));
|
||||||
|
assertTrue(beforeInfoSql2.get(1) == afterInfoSql2.get(1));
|
||||||
|
assertTrue(beforeInfoSql2.get(2) + 2 == afterInfoSql2.get(2));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testExecutePBENoCache() throws Exception {
|
||||||
|
Properties props = new Properties();
|
||||||
|
props.setProperty("prepareThreshold", "0");
|
||||||
|
String sql1 = "drop table if exists t1; create table t1(id int, age int);";
|
||||||
|
|
||||||
|
String sql2 = "select ? from t1;";
|
||||||
|
String sql2Record = "select%from t1";
|
||||||
|
List<Integer> beforeInfoSql2 = recordCount(sql2Record);
|
||||||
|
|
||||||
|
/* PBES / PBES */
|
||||||
|
try (Connection conn = createConnection(props);
|
||||||
|
Statement stmt = conn.createStatement();
|
||||||
|
PreparedStatement pstmt = conn.prepareStatement(sql2)) {
|
||||||
|
stmt.execute(sql1);
|
||||||
|
setRecordFullSql(conn);
|
||||||
|
|
||||||
|
pstmt.setString(1, "id");
|
||||||
|
pstmt.execute();
|
||||||
|
pstmt.setString(1, "age");
|
||||||
|
pstmt.execute();
|
||||||
|
sendPreTimeAndFlush(conn);
|
||||||
|
|
||||||
|
List<Integer> afterInfoSql2 = recordCount(sql2Record);
|
||||||
|
assertTrue(beforeInfoSql2.get(0) + 2 == afterInfoSql2.get(0));
|
||||||
|
assertTrue(beforeInfoSql2.get(1) == afterInfoSql2.get(1));
|
||||||
|
assertTrue(beforeInfoSql2.get(2) + 2 == afterInfoSql2.get(2));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testExecutePBEUseCache() throws Exception {
|
||||||
|
Properties props = new Properties();
|
||||||
|
props.setProperty("prepareThreshold", "1");
|
||||||
|
String sql1 = "drop table if exists t1; create table t1(id int, age int);";
|
||||||
|
|
||||||
|
String sql2 = "select ? from t1;";
|
||||||
|
String sql2Record = "select%from t1";
|
||||||
|
List<Integer> beforeInfoSql2 = recordCount(sql2Record);
|
||||||
|
|
||||||
|
/* PBES/BES */
|
||||||
|
try (Connection conn = createConnection(props);
|
||||||
|
Statement stmt = conn.createStatement();
|
||||||
|
PreparedStatement pstmt = conn.prepareStatement(sql2)) {
|
||||||
|
stmt.execute(sql1);
|
||||||
|
setRecordFullSql(conn);
|
||||||
|
|
||||||
|
pstmt.setString(1, "id");
|
||||||
|
pstmt.execute();
|
||||||
|
pstmt.setString(1, "age");
|
||||||
|
pstmt.execute();
|
||||||
|
sendPreTimeAndFlush(conn);
|
||||||
|
|
||||||
|
List<Integer> afterInfoSql2 = recordCount(sql2Record);
|
||||||
|
assertTrue(beforeInfoSql2.get(0) + 1 == afterInfoSql2.get(0));
|
||||||
|
assertTrue(beforeInfoSql2.get(1) == afterInfoSql2.get(1));
|
||||||
|
assertTrue(beforeInfoSql2.get(2) + 2 == afterInfoSql2.get(2));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testExecuteFetchSize() throws Exception {
|
||||||
|
String sql1 = "drop table if exists t1; create table t1(id int)";
|
||||||
|
String sql2 = "insert into t1 values(?)";
|
||||||
|
String sql3 = "select * from t1";
|
||||||
|
List<Integer> beforeInfoSql3 = recordCount(sql3);
|
||||||
|
ResultSet rst = null;
|
||||||
|
|
||||||
|
try (Connection conn = createConnection();
|
||||||
|
Statement stmt = conn.createStatement();
|
||||||
|
PreparedStatement pstmt = conn.prepareStatement(sql2);
|
||||||
|
PreparedStatement pstmt1 = conn.prepareStatement(sql3)) {
|
||||||
|
/* prepare data */
|
||||||
|
stmt.execute(sql1);
|
||||||
|
|
||||||
|
for (int i = 0; i < 5000; ++i) {
|
||||||
|
pstmt.setInt(1, i);
|
||||||
|
pstmt.addBatch();
|
||||||
|
}
|
||||||
|
pstmt.executeBatch();
|
||||||
|
|
||||||
|
conn.setAutoCommit(false);
|
||||||
|
setRecordFullSql(conn);
|
||||||
|
|
||||||
|
pstmt1.setFetchSize(1000);
|
||||||
|
/* PBDES/ES/ES/ES/ES/ES */
|
||||||
|
rst = pstmt1.executeQuery();
|
||||||
|
while (rst.next()) {
|
||||||
|
rst.getInt(1);
|
||||||
|
}
|
||||||
|
sendPreTimeAndFlush(conn);
|
||||||
|
|
||||||
|
List<Integer> afterInfoSql3 = recordCount(sql3);
|
||||||
|
assertTrue(beforeInfoSql3.get(0) + 1 == afterInfoSql3.get(0));
|
||||||
|
assertTrue(beforeInfoSql3.get(1) == afterInfoSql3.get(1));
|
||||||
|
assertTrue(beforeInfoSql3.get(2) + 6 == afterInfoSql3.get(2));
|
||||||
|
} finally {
|
||||||
|
if (rst != null) {
|
||||||
|
rst.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testExecuteMultiSqlQ() throws Exception {
|
||||||
|
Properties props = new Properties();
|
||||||
|
props.setProperty("preferQueryMode", "simple");
|
||||||
|
|
||||||
|
String sql1 = "drop table if exists t1";
|
||||||
|
String sql2 = "create table t1(id int)";
|
||||||
|
List<Integer> beforeInfoSql1 = recordCount(sql1);
|
||||||
|
List<Integer> beforeInfoSql2 = recordCount(sql2);
|
||||||
|
try (Connection conn = createConnection(props);
|
||||||
|
PreparedStatement pstmt = conn.prepareStatement(sql1 + ";" + sql2)) {
|
||||||
|
setRecordFullSql(conn);
|
||||||
|
/* Q -> Q */
|
||||||
|
pstmt.execute();
|
||||||
|
sendPreTimeAndFlush(conn);
|
||||||
|
|
||||||
|
List<Integer> afterInfoSql1 = recordCount(sql1);
|
||||||
|
List<Integer> afterInfoSql2 = recordCount(sql2);
|
||||||
|
|
||||||
|
assertTrue(beforeInfoSql1.get(0) == afterInfoSql1.get(0));
|
||||||
|
assertTrue(beforeInfoSql1.get(1) + 1 == afterInfoSql1.get(1));
|
||||||
|
assertTrue(beforeInfoSql1.get(2) == afterInfoSql1.get(2));
|
||||||
|
|
||||||
|
assertTrue(beforeInfoSql2.get(0) == afterInfoSql2.get(0));
|
||||||
|
assertTrue(beforeInfoSql2.get(1) == afterInfoSql2.get(1));
|
||||||
|
assertTrue(beforeInfoSql2.get(2) + 1 == afterInfoSql2.get(2));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testExecuteQ() throws Exception {
|
||||||
|
Properties props = new Properties();
|
||||||
|
props.setProperty("preferQueryMode", "simple");
|
||||||
|
|
||||||
|
String sql1 = "drop table if exists t1; create table t1(id int, age int)";
|
||||||
|
String sql2 = "select ? from t1";
|
||||||
|
String sql2Record = "select%from t1";
|
||||||
|
List<Integer> beforeInfoSql2 = recordCount(sql2Record);
|
||||||
|
|
||||||
|
try (Connection conn = createConnection(props);
|
||||||
|
Statement stmt = conn.createStatement();
|
||||||
|
PreparedStatement pstmt = conn.prepareStatement(sql2)) {
|
||||||
|
stmt.execute(sql1);
|
||||||
|
setRecordFullSql(conn);
|
||||||
|
|
||||||
|
/* Q / Q */
|
||||||
|
pstmt.setString(1, "id");
|
||||||
|
pstmt.execute();
|
||||||
|
pstmt.setString(1, "age");
|
||||||
|
pstmt.execute();
|
||||||
|
sendPreTimeAndFlush(conn);
|
||||||
|
|
||||||
|
List<Integer> afterInfoSql2 = recordCount(sql2Record);
|
||||||
|
assertTrue(beforeInfoSql2.get(0) == afterInfoSql2.get(0));
|
||||||
|
assertTrue(beforeInfoSql2.get(1) == afterInfoSql2.get(1));
|
||||||
|
assertTrue(beforeInfoSql2.get(2) + 2 == afterInfoSql2.get(2));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -365,6 +365,10 @@ public class TestUtil {
|
|||||||
return openDB(props,getDatabase());
|
return openDB(props,getDatabase());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Connection openDB(String dbName) throws Exception {
|
||||||
|
return openDB(new Properties(), dbName);
|
||||||
|
}
|
||||||
|
|
||||||
public static Connection openDBPG(Properties props) throws Exception {
|
public static Connection openDBPG(Properties props) throws Exception {
|
||||||
return openDB(props,getDatabasePG());
|
return openDB(props,getDatabasePG());
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user