Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.redkalex.source.mysql.MysqlDataSource Maven / Gradle / Ivy
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.redkalex.source.mysql;
import java.io.Serializable;
import java.net.URL;
import java.nio.ByteBuffer;
import java.nio.channels.CompletionHandler;
import java.nio.charset.StandardCharsets;
import java.sql.*;
import java.util.*;
import java.util.concurrent.*;
import java.util.function.*;
import java.util.logging.*;
import org.redkale.net.AsyncConnection;
import org.redkale.service.Local;
import org.redkale.source.*;
import org.redkale.util.*;
/**
* MySQL数据库的DataSource实现
*
* @author zhangjx
*/
@Local
@AutoLoad(false)
@SuppressWarnings("unchecked")
@ResourceType(DataSource.class)
public class MysqlDataSource extends DataSqlSource {
private static final byte[] BYTES_NULL = "NULL".getBytes(StandardCharsets.UTF_8);
private static final byte[] SQL_SET_AUTOCOMMIT_0 = "SET autocommit=0".getBytes(StandardCharsets.UTF_8);
private static final byte[] SQL_SET_AUTOCOMMIT_1 = "SET autocommit=1".getBytes(StandardCharsets.UTF_8);
private static final byte[] SQL_COMMIT = "COMMIT".getBytes(StandardCharsets.UTF_8);
private static final byte[] SQL_ROLLBACK = "ROLLBACK".getBytes(StandardCharsets.UTF_8);
public static void main(String[] args) throws Throwable {
Properties prop = new Properties();
prop.setProperty(DataSources.JDBC_URL, "jdbc:mysql://localhost:3306/platf_core?characterEncoding=utf8");
prop.setProperty(DataSources.JDBC_USER, "root");
prop.setProperty(DataSources.JDBC_PWD, "");
MysqlDataSource source = new MysqlDataSource("", null, prop, prop);
source.getReadPoolSource().poll();
source.directExecute("SET NAMES UTF8MB4");
}
public MysqlDataSource(String unitName, URL persistxml, Properties readprop, Properties writeprop) {
super(unitName, persistxml, readprop, writeprop);
}
@Local
protected PoolSource readPoolSource() {
return readPool;
}
@Local
protected PoolSource writePoolSource() {
return writePool;
}
@Override
protected String prepareParamSign(int index) {
return "$" + index;
}
@Override
protected final boolean isAsync() {
return true;
}
@Override
protected PoolSource createPoolSource(DataSource source, String rwtype, ArrayBlockingQueue queue, Semaphore semaphore, Properties prop) {
return new MyPoolSource(rwtype, queue, semaphore, prop, logger, bufferPool, executor);
}
@Override
protected CompletableFuture insertDB(EntityInfo info, T... values) {
final Attribute[] attrs = info.getInsertAttributes();
final byte[][] sqlBytesArray = new byte[1][];
String presql = info.getInsertPrepareSQL(values[0]);
byte[] prebs = (presql.substring(0, presql.indexOf("VALUES")) + "VALUES").getBytes(StandardCharsets.UTF_8); //不会存在非ASCII字符
ByteArray ba = new ByteArray();
ba.write(prebs);
for (int i = 0; i < values.length; i++) {
if (i > 0) ba.write((byte) ',');
ba.write((byte) '(');
for (int j = 0; j < attrs.length; j++) {
if (j > 0) ba.write((byte) ',');
byte[] param = formatPrepareParam(info, attrs[j], attrs[j].get(values[i]));
if (param == null) {
ba.write(BYTES_NULL);
} else {
ba.write((byte) 0x27);
for (byte b : param) {
if (b == 0x5c || b == 0x27) ba.write((byte) 0x5c);
ba.write(b);
}
ba.write((byte) 0x27);
}
}
ba.write((byte) ')');
}
sqlBytesArray[0] = ba.getBytes();
if (info.isLoggable(logger, Level.FINEST)) {
String realsql = ba.toString(StandardCharsets.UTF_8);
if (info.isLoggable(logger, Level.FINEST, realsql)) logger.finest(info.getType().getSimpleName() + " insert sql=" + realsql);
}
return writePool.pollAsync().thenCompose((conn) -> executeBatchUpdate(info, conn, UpdateMode.INSERT, values[0], sqlBytesArray).thenApply((int[] rs) -> {
int count = 0;
for (int i : rs) count += i;
return count;
}));
}
@Override
protected CompletableFuture deleteDB(EntityInfo info, Flipper flipper, String sql) {
final String realsql = flipper == null || flipper.getLimit() <= 0 ? sql : (sql + " LIMIT " + flipper.getLimit());
if (info.isLoggable(logger, Level.FINEST)) {
if (info.isLoggable(logger, Level.FINEST, realsql)) logger.finest(info.getType().getSimpleName() + " delete sql=" + realsql);
}
return writePool.pollAsync().thenCompose((conn) -> executeOneUpdate(info, conn, UpdateMode.DELETE, realsql.getBytes(StandardCharsets.UTF_8)));
}
@Override
protected CompletableFuture clearTableDB(EntityInfo info, final String table, String sql) {
if (info.isLoggable(logger, Level.FINEST)) {
if (info.isLoggable(logger, Level.FINEST, sql)) logger.finest(info.getType().getSimpleName() + " clearTable sql=" + sql);
}
return writePool.pollAsync().thenCompose((conn) -> {
CompletableFuture future = executeOneUpdate(info, conn, UpdateMode.CLEAR, sql.getBytes(StandardCharsets.UTF_8));
final CompletableFuture newFuture = new CompletableFuture<>();
future.whenComplete((o, ex1) -> {
if (ex1 == null) {
newFuture.complete(o);
return;
}
try {
while (ex1 instanceof CompletionException) ex1 = ex1.getCause();
if (info.isTableNotExist((SQLException) ex1)) {
newFuture.complete(-1);
} else {
newFuture.completeExceptionally(ex1);
}
} catch (Throwable e) {
newFuture.completeExceptionally(ex1);
}
});
return newFuture;
});
}
@Override
protected CompletableFuture dropTableDB(EntityInfo info, final String table, String sql) {
if (info.isLoggable(logger, Level.FINEST)) {
if (info.isLoggable(logger, Level.FINEST, sql)) logger.finest(info.getType().getSimpleName() + " dropTable sql=" + sql);
}
return writePool.pollAsync().thenCompose((conn) -> {
CompletableFuture future = executeOneUpdate(info, conn, UpdateMode.DROP, sql.getBytes(StandardCharsets.UTF_8));
final CompletableFuture newFuture = new CompletableFuture<>();
future.whenComplete((o, ex1) -> {
if (ex1 == null) {
newFuture.complete(o);
return;
}
try {
while (ex1 instanceof CompletionException) ex1 = ex1.getCause();
if (info.isTableNotExist((SQLException) ex1)) {
newFuture.complete(-1);
} else {
newFuture.completeExceptionally(ex1);
}
} catch (Throwable e) {
newFuture.completeExceptionally(ex1);
}
});
return newFuture;
});
}
@Override
protected CompletableFuture updateDB(EntityInfo info, final T... values) {
final Attribute primary = info.getPrimary();
final Attribute[] attrs = info.getUpdateAttributes();
final byte[][] sqlBytesArray = new byte[values.length][];
final char[] sqlChs = info.getUpdatePrepareSQL(values[0]).toCharArray(); //不会存在非ASCII字符
ByteArray ba = new ByteArray();
for (int i = 0; i < values.length; i++) {
int index = -1;
for (char ch : sqlChs) {
if (ch != '?') {
ba.write((byte) ch);
continue;
}
index++;
byte[] param = index < attrs.length ? formatPrepareParam(info, attrs[index], attrs[index].get(values[i])) : formatPrepareParam(info, primary, primary.get(values[i])); //最后一个是主键
if (param == null) {
ba.write(BYTES_NULL);
} else {
ba.write((byte) 0x27);
for (byte b : param) {
if (b == 0x5c || b == 0x27) ba.write((byte) 0x5c);
ba.write(b);
}
ba.write((byte) 0x27);
}
}
sqlBytesArray[i] = ba.getBytes();
if (info.isLoggable(logger, Level.FINEST)) {
String realsql = ba.toString(StandardCharsets.UTF_8);
if (info.isLoggable(logger, Level.FINEST, realsql)) logger.finest(info.getType().getSimpleName() + " update sql=" + realsql);
}
ba.clear();
}
return writePool.pollAsync().thenCompose((conn) -> executeBatchUpdate(info, conn, UpdateMode.UPDATE, null, sqlBytesArray).thenApply((int[] rs) -> {
int count = 0;
for (int i : rs) count += i;
return count;
}));
}
@Override
protected CompletableFuture updateDB(EntityInfo info, Flipper flipper, String sql, boolean prepared, Object... params) {
final String realsql = flipper == null || flipper.getLimit() <= 0 ? sql : (sql + " LIMIT " + flipper.getLimit());
if (info.isLoggable(logger, Level.FINEST)) {
if (info.isLoggable(logger, Level.FINEST, realsql)) logger.finest(info.getType().getSimpleName() + " update sql=" + realsql);
}
if (!prepared) return writePool.pollAsync().thenCompose((conn) -> executeOneUpdate(info, conn, UpdateMode.UPDATE, realsql.getBytes(StandardCharsets.UTF_8)));
ByteArray ba = new ByteArray();
String[] subsqls = realsql.split("\\" + prepareParamSign(1).replace("1", "") + "\\d+");
for (int i = 0; i < params.length; i++) {
ba.write(subsqls[i].getBytes(StandardCharsets.UTF_8));
byte[] param = formatPrepareParam(info, null, params[i]);
if (param == null) {
ba.write(BYTES_NULL);
} else {
ba.write((byte) 0x27);
for (byte b : param) {
if (b == 0x5c || b == 0x27) ba.write((byte) 0x5c);
ba.write(b);
}
ba.write((byte) 0x27);
}
}
for (int i = params.length; i < subsqls.length; i++) {
ba.write(subsqls[i].getBytes(StandardCharsets.UTF_8));
}
return writePool.pollAsync().thenCompose((conn) -> executeOneUpdate(info, conn, UpdateMode.UPDATE, ba.getBytes()));
}
@Override
protected CompletableFuture> getNumberMapDB(EntityInfo info, String sql, FilterFuncColumn... columns) {
return readPool.pollAsync().thenCompose((conn) -> exceptionallyQueryTableNotExist(executeQuery(info, conn, sql), info).thenApply((ResultSet set) -> {
final Map map = new HashMap<>();
try {
if (set.next()) {
int index = 0;
for (FilterFuncColumn ffc : columns) {
for (String col : ffc.cols()) {
Object o = set.getObject(++index);
Number rs = ffc.getDefvalue();
if (o != null) rs = (Number) o;
map.put(ffc.col(col), rs);
}
}
}
} catch (Exception e) {
throw new RuntimeException(e);
}
return map;
}));
}
@Override
protected CompletableFuture getNumberResultDB(EntityInfo info, String sql, Number defVal, String column) {
return readPool.pollAsync().thenCompose((conn) -> exceptionallyQueryTableNotExist(executeQuery(info, conn, sql), info)
.thenApply((ResultSet set) -> {
Number rs = defVal;
try {
if (set.next()) {
Object o = set.getObject(1);
if (o != null) rs = (Number) o;
}
} catch (Exception e) {
throw new RuntimeException(e);
}
return rs;
}));
}
@Override
protected CompletableFuture> queryColumnMapDB(EntityInfo info, String sql, String keyColumn) {
return readPool.pollAsync().thenCompose((conn) -> exceptionallyQueryTableNotExist(executeQuery(info, conn, sql), info).thenApply((ResultSet set) -> {
Map rs = new LinkedHashMap<>();
try {
while (set.next()) {
rs.put((K) set.getObject(1), (N) set.getObject(2));
}
} catch (Exception e) {
throw new RuntimeException(e);
}
return rs;
}));
}
@Override
protected CompletableFuture> queryColumnMapDB(EntityInfo info, String sql, final ColumnNode[] funcNodes, final String[] groupByColumns) {
return readPool.pollAsync().thenCompose((conn) -> executeQuery(info, conn, sql).thenApply((ResultSet set) -> {
Map rs = new LinkedHashMap<>();
try {
while (set.next()) {
int index = 0;
Serializable[] keys = new Serializable[groupByColumns.length];
for (int i = 0; i < keys.length; i++) {
keys[i] = (Serializable) set.getObject(++index);
}
Number[] vals = new Number[funcNodes.length];
for (int i = 0; i < vals.length; i++) {
vals[i] = (Number) set.getObject(++index);
}
rs.put(keys, vals);
}
} catch (Exception e) {
throw new RuntimeException(e);
}
return rs;
}));
}
@Override
protected CompletableFuture findDB(EntityInfo info, String sql, boolean onlypk, SelectColumn selects) {
return readPool.pollAsync().thenCompose((conn) -> exceptionallyQueryTableNotExist(executeQuery(info, conn, sql), info).thenApply((ResultSet set) -> {
T rs = null;
try {
rs = set.next() ? getEntityValue(info, selects, set) : null;
} catch (Exception e) {
throw new RuntimeException(e);
}
return rs;
}));
}
@Override
protected CompletableFuture findColumnDB(EntityInfo info, String sql, boolean onlypk, String column, Serializable defValue) {
return readPool.pollAsync().thenCompose((conn) -> exceptionallyQueryTableNotExist(executeQuery(info, conn, sql), info).thenApply((ResultSet set) -> {
Serializable val = defValue;
try {
if (set.next()) {
final Attribute attr = info.getAttribute(column);
val = getFieldValue(info, attr, set, 1);
}
} catch (Exception e) {
throw new RuntimeException(e);
}
return val == null ? defValue : val;
}));
}
@Override
protected CompletableFuture existsDB(EntityInfo info, String sql, boolean onlypk) {
return readPool.pollAsync().thenCompose((conn) -> exceptionallyQueryTableNotExist(executeQuery(info, conn, sql), info).thenApply((ResultSet set) -> {
try {
boolean rs = set.next() ? (set.getInt(1) > 0) : false;
return rs;
} catch (Exception e) {
throw new RuntimeException(e);
}
}));
}
@Override
protected CompletableFuture> querySheetDB(EntityInfo info, final boolean readcache, boolean needtotal, final boolean distinct, SelectColumn selects, Flipper flipper, FilterNode node) {
final SelectColumn sels = selects;
final Map joinTabalis = node == null ? null : getJoinTabalis(node);
final CharSequence join = node == null ? null : createSQLJoin(node, this, false, joinTabalis, new HashSet<>(), info);
final CharSequence where = node == null ? null : createSQLExpress(node, info, joinTabalis);
final String listsql = "SELECT " + (distinct ? "DISTINCT " : "") + info.getQueryColumns("a", selects) + " FROM " + info.getTable(node) + " a" + (join == null ? "" : join)
+ ((where == null || where.length() == 0) ? "" : (" WHERE " + where)) + createSQLOrderby(info, flipper) + (flipper == null || flipper.getLimit() < 1 ? "" : (" LIMIT " + flipper.getLimit() + " OFFSET " + flipper.getOffset()));
if (readcache && info.isLoggable(logger, Level.FINEST, listsql)) logger.finest(info.getType().getSimpleName() + " query sql=" + listsql);
if (!needtotal) {
return readPool.pollAsync().thenCompose((conn) -> exceptionallyQueryTableNotExist(executeQuery(info, conn, listsql), info)
.thenApply((ResultSet set) -> {
try {
final List list = new ArrayList();
while (set != null && set.next()) {
list.add(getEntityValue(info, sels, set));
}
return Sheet.asSheet(list);
} catch (Exception e) {
throw new RuntimeException(e);
}
}));
}
final String countsql = "SELECT " + (distinct ? "DISTINCT COUNT(" + info.getQueryColumns("a", selects) + ")" : "COUNT(*)") + " FROM " + info.getTable(node) + " a" + (join == null ? "" : join)
+ ((where == null || where.length() == 0) ? "" : (" WHERE " + where));
return getNumberResultDB(info, countsql, 0, countsql).thenCompose(total -> {
if (total.longValue() <= 0) return CompletableFuture.completedFuture(new Sheet<>(0, new ArrayList()));
return readPool.pollAsync().thenCompose((conn) -> executeQuery(info, conn, listsql).thenApply((ResultSet set) -> {
try {
final List list = new ArrayList();
while (set.next()) {
list.add(getEntityValue(info, sels, set));
}
return new Sheet(total.longValue(), list);
} catch (Exception e) {
throw new RuntimeException(e);
}
}));
});
}
protected CompletableFuture exceptionallyQueryTableNotExist(CompletableFuture future, EntityInfo info) {
if (info == null || info.getTableStrategy() == null) return future;
return future.exceptionally(ex -> {
Throwable sqlex = ex;
while (sqlex instanceof CompletionException) sqlex = sqlex.getCause();
if (info.getTableStrategy() != null && sqlex instanceof SQLException && info.isTableNotExist((SQLException) sqlex)) {
return new MyResultSet(info, new MyColumnDescPacket[0], new ArrayList<>());
} else {
future.obtrudeException(sqlex);
return null;
}
});
}
protected CompletableFuture exceptionallyUpdateTableNotExist(CompletableFuture future,
EntityInfo info, final AsyncConnection conn, final UpdateMode mode, final byte[] array, final T oneEntity, final byte[] sqlBytes) {
final CompletableFuture newFuture = new CompletableFuture<>();
future.whenComplete((o, ex1) -> {
if (ex1 == null) {
newFuture.complete(o);
return;
}
try {
while (ex1 instanceof CompletionException) ex1 = ex1.getCause();
if (info.getTableStrategy() != null && ex1 instanceof SQLException && info.isTableNotExist((SQLException) ex1)) {
if (mode != UpdateMode.INSERT) { //update、delete、clear或drop
newFuture.complete((mode == UpdateMode.DROP || mode == UpdateMode.CLEAR) ? -1 : 0);
return;
}
//分表分库
final String newTable = info.getTable(oneEntity);
final byte[] createTableSqlBytes = info.getTableCopySQL(newTable).getBytes(StandardCharsets.UTF_8);
executeAtomicOneUpdate(info, conn, array, createTableSqlBytes).whenComplete((o2, ex2) -> {
if (ex2 == null) { //建分表成功
info.addDisTable(newTable);
//重新执行一遍sql语句
executeAtomicOneUpdate(info, conn, array, sqlBytes).whenComplete((o3, ex3) -> {
if (ex3 == null) {
newFuture.complete(o3);
} else {
while (ex3 instanceof CompletionException) ex3 = ex3.getCause();
newFuture.completeExceptionally(ex3);
}
});
} else {
while (ex2 instanceof CompletionException) ex2 = ex2.getCause();
if (newTable.indexOf('.') > 0 && ex2 instanceof SQLException
&& ("HY000".equals(((SQLException) ex2).getSQLState()) || "42000".equals(((SQLException) ex2).getSQLState()))) { //可能是database不存在
executeAtomicOneUpdate(info, conn, array, ("CREATE DATABASE " + newTable.substring(0, newTable.indexOf('.'))).getBytes()).whenComplete((o3, ex3) -> {
if (ex3 == null) { //建库成功
executeAtomicOneUpdate(info, conn, array, createTableSqlBytes).whenComplete((o4, ex4) -> { //建表
if (ex4 == null) { //建表成功
info.addDisTable(newTable);
//重新执行一遍sql语句
executeAtomicOneUpdate(info, conn, array, sqlBytes).whenComplete((o5, ex5) -> {
if (ex5 == null) {
newFuture.complete(o5);
} else {
while (ex5 instanceof CompletionException) ex5 = ex5.getCause();
newFuture.completeExceptionally(ex5);
}
});
} else {
while (ex4 instanceof CompletionException) ex4 = ex4.getCause();
newFuture.completeExceptionally(ex4);
}
});
} else {
while (ex3 instanceof CompletionException) ex3 = ex3.getCause();
newFuture.completeExceptionally(ex3);
}
});
} else { //不是建库的问题
newFuture.completeExceptionally(ex2);
}
}
});
} else {
newFuture.completeExceptionally(ex1);
}
} catch (Throwable t) {
newFuture.completeExceptionally(t);
}
});
return newFuture;
}
protected static byte[] formatPrepareParam(EntityInfo info, Attribute attr, Object param) {
if (param == null && info.isNotNullJson(attr)) return new byte[0];
if (param == null) return null;
if (param instanceof CharSequence) {
return param.toString().getBytes(StandardCharsets.UTF_8);
}
if (param instanceof Boolean) {
return (Boolean) param ? new byte[]{0x31} : new byte[]{0x30};
}
if (param instanceof byte[]) {
return (byte[]) param;
}
if (param instanceof java.sql.Blob) {
java.sql.Blob blob = (java.sql.Blob) param;
try {
return blob.getBytes(1, (int) blob.length());
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
if (!(param instanceof Number) && !(param instanceof CharSequence) && !(param instanceof java.util.Date)
&& !param.getClass().getName().startsWith("java.sql.") && !param.getClass().getName().startsWith("java.time.")) {
if (attr == null) return info.getJsonConvert().convertTo(param).getBytes(StandardCharsets.UTF_8);
return info.getJsonConvert().convertTo(attr.genericType(), param).getBytes(StandardCharsets.UTF_8);
}
return String.valueOf(param).getBytes(StandardCharsets.UTF_8);
}
protected CompletableFuture executeOneUpdate(final EntityInfo info, final AsyncConnection conn, final UpdateMode mode, final byte[] sqlBytes) {
return executeBatchUpdate(info, conn, mode, null, sqlBytes).thenApply(a -> a[0]);
}
protected CompletableFuture executeBatchUpdate(final EntityInfo info, final AsyncConnection conn, final UpdateMode mode, final T oneEntity, final byte[]... sqlBytesArray) {
final byte[] array = conn.getAttribute(MyPoolSource.CONN_ATTR_BYTES_NAME);
if (sqlBytesArray.length == 1) {
return executeAtomicOneUpdate(info, conn, array, SQL_SET_AUTOCOMMIT_1).thenCompose(o
-> mode == UpdateMode.INSERT ? exceptionallyUpdateTableNotExist(executeAtomicOneUpdate(info, conn, array, sqlBytesArray[0]), info, conn, mode, array, oneEntity, sqlBytesArray[0])
: executeAtomicOneUpdate(info, conn, array, sqlBytesArray[0])).thenApply(a -> new int[]{a}).whenComplete((o, t) -> {
if (t == null) {
writePool.offerConnection(conn);
} else {
conn.dispose();
}
});
}
//多个
final int[] rs = new int[sqlBytesArray.length + 2];
CompletableFuture future = executeAtomicOneUpdate(info, conn, array, SQL_SET_AUTOCOMMIT_0);
future.thenAccept((Integer a) -> rs[0] = a);
for (int i = 0; i < sqlBytesArray.length; i++) {
final int index = i + 1;
final byte[] sqlBytes = sqlBytesArray[i];
future = future.thenCompose(a -> {
CompletableFuture nextFuture = executeAtomicOneUpdate(info, conn, array, sqlBytes);
nextFuture.thenAccept(b -> rs[index] = b);
if (mode == UpdateMode.INSERT && info != null && info.getTableStrategy() != null) nextFuture = exceptionallyUpdateTableNotExist(nextFuture, info, conn, mode, array, oneEntity, sqlBytes);
nextFuture.whenComplete((o, t) -> {
if (t != null) executeAtomicOneUpdate(info, conn, array, SQL_ROLLBACK).join();
});
return nextFuture;
});
}
future = future.thenCompose(a -> {
CompletableFuture nextFuture = executeAtomicOneUpdate(info, conn, array, SQL_COMMIT);
nextFuture.thenAccept(b -> rs[sqlBytesArray.length] = b);
return nextFuture;
});
return future.thenApply(a -> Arrays.copyOfRange(rs, 1, sqlBytesArray.length + 1)).whenComplete((o, t) -> {
if (t == null) {
writePool.offerConnection(conn);
} else {
conn.dispose();
}
});
}
protected CompletableFuture executeAtomicOneUpdate(final EntityInfo info, final AsyncConnection conn, final byte[] array, final byte[] sqlBytes) {
final ByteBufferWriter writer = ByteBufferWriter.create(bufferPool);
{
new MyQueryPacket(sqlBytes).writeTo(writer);
}
final ByteBuffer[] buffers = writer.toBuffers();
final CompletableFuture future = new CompletableFuture();
conn.write(buffers, buffers, new CompletionHandler() {
@Override
public void completed(Integer result, ByteBuffer[] attachment1) {
if (result < 0) {
failed(new SQLException("Write Buffer Error"), attachment1);
return;
}
int index = -1;
for (int i = 0; i < attachment1.length; i++) {
if (attachment1[i].hasRemaining()) {
index = i;
break;
}
bufferPool.accept(attachment1[i]);
}
if (index == 0) {
conn.write(attachment1, attachment1, this);
return;
} else if (index > 0) {
ByteBuffer[] newattachs = new ByteBuffer[attachment1.length - index];
System.arraycopy(attachment1, index, newattachs, 0, newattachs.length);
conn.write(newattachs, newattachs, this);
return;
}
final List readBuffs = new ArrayList<>();
conn.read(new CompletionHandler() {
@Override
public void completed(Integer result, ByteBuffer attachment2) {
if (result < 0) {
failed(new SQLException("Read Buffer Error"), attachment2);
return;
}
if (result == 16 * 1024 || !attachment2.hasRemaining()) { //mysqlsql数据包上限为16*1024还有数据
attachment2.flip();
readBuffs.add(attachment2);
conn.read(this);
return;
}
attachment2.flip();
readBuffs.add(attachment2);
final ByteBufferReader bufferReader = ByteBufferReader.create(readBuffs);
MyOKPacket okPacket = new MyOKPacket(-1, bufferReader, array);
//System.out.println("执行sql=" + new String(sqlBytes, StandardCharsets.UTF_8) + ", 结果: " + okPacket);
if (!okPacket.isOK()) {
future.completeExceptionally(new SQLException(okPacket.toMessageString("MySQLOKPacket statusCode not success") + " sql=" + new String(sqlBytes, StandardCharsets.UTF_8), okPacket.sqlState, okPacket.vendorCode));
//不能关conn
} else {
for (ByteBuffer buf : readBuffs) {
bufferPool.accept(buf);
}
future.complete((int) okPacket.updateCount);
}
}
@Override
public void failed(Throwable exc, ByteBuffer attachment2) {
conn.offerBuffer(attachment2);
future.completeExceptionally(exc);
//不能关conn
}
});
}
@Override
public void failed(Throwable exc, ByteBuffer[] attachment1) {
for (ByteBuffer attach : attachment1) {
bufferPool.accept(attach);
}
future.completeExceptionally(exc);
}
});
return future;
}
//info可以为null,供directQuery
protected CompletableFuture executeQuery(final EntityInfo info, final AsyncConnection conn, final String sql) {
final byte[] array = conn.getAttribute(MyPoolSource.CONN_ATTR_BYTES_NAME);
final ByteBufferWriter writer = ByteBufferWriter.create(bufferPool);
{
new MyQueryPacket(sql.getBytes(StandardCharsets.UTF_8)).writeTo(writer);
}
final ByteBuffer[] buffers = writer.toBuffers();
final CompletableFuture future = new CompletableFuture();
conn.write(buffers, buffers, new CompletionHandler() {
@Override
public void completed(Integer result, ByteBuffer[] attachment1) {
if (result < 0) {
failed(new SQLException("Write Buffer Error"), attachment1);
return;
}
int index = -1;
for (int i = 0; i < attachment1.length; i++) {
if (attachment1[i].hasRemaining()) {
index = i;
break;
}
bufferPool.accept(attachment1[i]);
}
if (index == 0) {
conn.write(attachment1, attachment1, this);
return;
} else if (index > 0) {
ByteBuffer[] newattachs = new ByteBuffer[attachment1.length - index];
System.arraycopy(attachment1, index, newattachs, 0, newattachs.length);
conn.write(newattachs, newattachs, this);
return;
}
final List readBuffs = new ArrayList<>();
conn.read(new CompletionHandler() {
@Override
public void completed(Integer result, ByteBuffer attachment2) {
if (result < 0) {
failed(new SQLException("Read Buffer Error"), attachment2);
return;
}
if (result == 16 * 1024 || !attachment2.hasRemaining()) { //mysqlsql数据包上限为16*1024还有数据
attachment2.flip();
readBuffs.add(attachment2);
conn.read(this);
return;
}
attachment2.flip();
readBuffs.add(attachment2);
final ByteBufferReader bufferReader = ByteBufferReader.create(readBuffs);
boolean endok = false;
boolean futureover = false;
boolean success = false;
SQLException ex = null;
int packetLength = Mysqls.readUB3(bufferReader);
MyResultSet resultSet = null;
if (packetLength < 4) {
MyColumnCountPacket countPacket = new MyColumnCountPacket(packetLength, bufferReader, array);
//System.out.println("查询sql=" + sql + ", 字段数: " + countPacket.columnCount);
//System.out.println("--------- column desc start -------------");
MyColumnDescPacket[] colDescs = new MyColumnDescPacket[countPacket.columnCount];
for (int i = 0; i < colDescs.length; i++) {
colDescs[i] = new MyColumnDescPacket(bufferReader, array);
}
//读取EOF包
MyEOFPacket eofPacket = new MyEOFPacket(-1, -1000, bufferReader, array);
//System.out.println("字段描述EOF包: " + eofPacket);
List rows = new ArrayList<>();
int colPacketLength = Mysqls.readUB3(bufferReader);
int packetIndex = bufferReader.get();
int typeid = bufferReader.preget() & 0xff;
while (typeid != Mysqls.TYPE_ID_EOF) { //EOF包
final MyRowDataPacket rowData = new MyRowDataPacket(colDescs, colPacketLength, packetIndex, bufferReader, countPacket.columnCount, array);
while (!rowData.readColumnValue(bufferReader) || bufferReader.remaining() < 3 + 6) {
final CompletableFuture patchFuture = new CompletableFuture<>();
conn.read(new CompletionHandler() {
@Override
public void completed(Integer result3, ByteBuffer attachment3) {
if (result3 < 0) {
failed(new SQLException("Read Buffer Error"), attachment3);
return;
}
attachment3.flip();
patchFuture.complete(attachment3);
}
@Override
public void failed(Throwable exc, ByteBuffer attachment3) {
patchFuture.completeExceptionally(exc);
}
});
bufferReader.append(patchFuture.join());
}
colPacketLength = Mysqls.readUB3(bufferReader);
packetIndex = bufferReader.get();
typeid = bufferReader.preget() & 0xff;
rows.add(rowData);
}
eofPacket = new MyEOFPacket(colPacketLength, packetIndex, bufferReader, array);
//System.out.println("查询结果包解析完毕: " + eofPacket);
resultSet = new MyResultSet(info, colDescs, rows);
success = true;
endok = true;
futureover = true;
} else {
MyOKPacket okPacket = new MyOKPacket(packetLength, bufferReader, array);
//System.out.println("查询sql=" + sql + ", 异常: " + okPacket);
ex = new SQLException(okPacket.toMessageString("MySQLOKPacket statusCode not success"), okPacket.sqlState, okPacket.vendorCode);
}
if (!futureover) future.completeExceptionally(ex == null ? new SQLException("SQL(" + sql + ") executeQuery error") : ex);
if (endok) {
readPool.offerConnection(conn);
future.complete(resultSet);
} else {
conn.dispose();
}
}
@Override
public void failed(Throwable exc, ByteBuffer attachment2) {
//不用bufferPool.accept
future.completeExceptionally(exc);
conn.dispose();
}
});
}
@Override
public void failed(Throwable exc, ByteBuffer[] attachment1) {
for (ByteBuffer attach : attachment1) {
bufferPool.accept(attach);
}
future.completeExceptionally(exc);
}
});
return future;
}
@Local
@Override
public int directExecute(String sql) {
return writePool.pollAsync().thenCompose((conn) -> executeOneUpdate(null, conn, UpdateMode.OTHER, sql.getBytes(StandardCharsets.UTF_8))).join();
}
@Local
@Override
public int[] directExecute(String... sqls) {
byte[][] sqlBytesArray = new byte[sqls.length][];
for (int i = 0; i < sqls.length; i++) {
sqlBytesArray[i] = sqls[i].getBytes(StandardCharsets.UTF_8);
}
return writePool.pollAsync().thenCompose((conn) -> executeBatchUpdate(null, conn, UpdateMode.OTHER, null, sqlBytesArray)).join();
}
@Local
@Override
public V directQuery(String sql, Function handler) {
return readPool.pollAsync().thenCompose((conn) -> executeQuery(null, conn, sql).thenApply((ResultSet set) -> {
return handler.apply(set);
})).join();
}
}