diff --git a/src/main/java/com/alibaba/druid/pool/DruidDataSource.java b/src/main/java/com/alibaba/druid/pool/DruidDataSource.java index 4ed010ef30..ccc568a0a6 100644 --- a/src/main/java/com/alibaba/druid/pool/DruidDataSource.java +++ b/src/main/java/com/alibaba/druid/pool/DruidDataSource.java @@ -1477,19 +1477,26 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat && activeCount >= onFatalErrorMaxActive) { connectErrorCountUpdater.incrementAndGet(this); - SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); - String errorMsg = "onFatalError, activeCount " + activeCount - + ", onFatalErrorMaxActive " + onFatalErrorMaxActive; + StringBuilder errorMsg = new StringBuilder(); + errorMsg.append("onFatalError, activeCount ") + .append(activeCount) + .append(", onFatalErrorMaxActive ") + .append(onFatalErrorMaxActive); if (lastFatalErrorTimeMillis > 0) { - errorMsg += ", time '" + format.format(new Date(lastFatalErrorTimeMillis)) + "'"; + errorMsg.append(", time '") + .append(StringUtils.formatDateTime19( + lastFatalErrorTimeMillis, TimeZone.getDefault())) + .append("'"); } if (lastFatalErrorSql != null) { - errorMsg += ", sql \n" + lastFatalErrorSql; + errorMsg.append(", sql \n") + .append(lastFatalErrorSql); } - throw new SQLException(errorMsg, lastFatalError); + throw new SQLException( + errorMsg.toString(), lastFatalError); } connectCount++; diff --git a/src/main/java/com/alibaba/druid/util/StringUtils.java b/src/main/java/com/alibaba/druid/util/StringUtils.java index 8ea8b6e6d3..770dfe538d 100644 --- a/src/main/java/com/alibaba/druid/util/StringUtils.java +++ b/src/main/java/com/alibaba/druid/util/StringUtils.java @@ -18,6 +18,9 @@ package com.alibaba.druid.util; import com.alibaba.druid.support.logging.Log; import com.alibaba.druid.support.logging.LogFactory; +import java.util.Calendar; +import java.util.TimeZone; + /** * @author sandzhang[sandzhangtoo@gmail.com] */ @@ -347,4 +350,40 @@ public class StringUtils { // found digit it to make sure weird stuff like '.' and '1E-' doesn't pass return !allowSigns && foundDigit; } + + public static String formatDateTime19(long millis, TimeZone timeZone) { + Calendar cale = timeZone == null + ? Calendar.getInstance() + : Calendar.getInstance(timeZone); + cale.setTimeInMillis(millis); + + int year = cale.get(Calendar.YEAR); + int month = cale.get(Calendar.MONTH) + 1; + int dayOfMonth = cale.get(Calendar.DAY_OF_MONTH); + int hour = cale.get(Calendar.HOUR_OF_DAY); + int minute = cale.get(Calendar.MINUTE); + int second = cale.get(Calendar.SECOND); + + char[] chars = new char[19]; + chars[0] = (char) (year/1000 + '0'); + chars[1] = (char) ((year/100)%10 + '0'); + chars[2] = (char) ((year/10)%10 + '0'); + chars[3] = (char) (year%10 + '0'); + chars[4] = '-'; + chars[5] = (char) (month/10 + '0'); + chars[6] = (char) (month%10 + '0'); + chars[7] = '-'; + chars[8] = (char) (dayOfMonth/10 + '0'); + chars[9] = (char) (dayOfMonth%10 + '0'); + chars[10] = ' '; + chars[11] = (char) (hour/10 + '0'); + chars[12] = (char) (hour%10 + '0'); + chars[13] = ':'; + chars[14] = (char) (minute/10 + '0'); + chars[15] = (char) (minute%10 + '0'); + chars[16] = ':'; + chars[17] = (char) (second/10 + '0'); + chars[18] = (char) (second%10 + '0'); + return new String(chars); + } } diff --git a/src/test/java/com/alibaba/druid/benckmark/sql/SqlHolder.java b/src/test/java/com/alibaba/druid/benckmark/sql/SqlHolder.java index dc90f84cc9..5661e64603 100644 --- a/src/test/java/com/alibaba/druid/benckmark/sql/SqlHolder.java +++ b/src/test/java/com/alibaba/druid/benckmark/sql/SqlHolder.java @@ -12,10 +12,7 @@ import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectQueryBlock; import com.alibaba.druid.sql.dialect.mysql.parser.MySqlSelectParser; import com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser; import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor; -import com.alibaba.druid.sql.parser.LayoutCharacters; -import com.alibaba.druid.sql.parser.ParserException; -import com.alibaba.druid.sql.parser.SQLParserFeature; -import com.alibaba.druid.sql.parser.Token; +import com.alibaba.druid.sql.parser.*; import com.alibaba.druid.sql.visitor.SQLASTOutputVisitor; import com.alibaba.druid.sql.visitor.SchemaStatVisitor; import com.alibaba.druid.stat.TableStat; @@ -36,6 +33,40 @@ public class SqlHolder { private boolean parsed; public SQLStatement ast; + private boolean isParam; + + public static SQLSelectListCache selectListCache = new SQLSelectListCache(JdbcConstants.MYSQL); + static { + selectListCache.add("select id as id, gmt_create as gmtCreate, gmt_modified as gmtModified, name as name, owner as owner, type as type, statement as statement, datasource as datasource, meta as meta, param_file as paramFile, sharable as sharable, data_type as dataType, status as status, config as config, project_id as projectId, plugins as plugins, field_compare as fieldCompare, field_ext as fieldExt, openx as openx from"); + selectListCache.add("SELECT id, dispute_id, buyer_id, seller_id, total_fee, refund_fee, max_apply_goods_fee, apply_goods_fee, apply_carriage_fee, refund_goods_fee, refund_carriage_fee, refund_point, refund_coupon, refund_return_point, refund_cash, real_deduct_refund_point, real_refund_return_point, refund_return_commission, gmt_create, gmt_modified, attributes, attributes_cc FROM"); +// selectListCache.add("select `auction_relation`.`id`,`auction_relation`.`item_id`,`auction_relation`.`sku_id`,`auction_relation`.`user_id`,`auction_relation`.`target_id`,`auction_relation`.`extra_id`,`auction_relation`.`type`,`auction_relation`.`target_type`,`auction_relation`.`type_attr`,`auction_relation`.`status`,`auction_relation`.`target_user_id`,`auction_relation`.`options`,`auction_relation`.`features`,`auction_relation`.`version`,`auction_relation`.`sub_type`,`auction_relation`.`gmt_create`,`auction_relation`.`gmt_modified` from"); +// selectListCache.add("SELECT biz_order_id, value_type, key_value, gmt_create, gmt_modified\n" + +// "\t, attribute_cc, buyer_id\n" + +// "FROM"); +// selectListCache.add("SELECT biz_order_id, value_type, key_value, gmt_create, gmt_modified\n" + +// "\t, attribute_cc, buyer_id\n" + +// "FROM"); +// selectListCache.add("SELECT sub_logistics_order_id, consign_time, attribute_cc, attributes, out_logistics_id\n" + +// "\t, parent_id, gmt_create, gmt_modified, detail_order_id, is_last\n" + +// "\t, ship_amount, buyer_id, seller_id, ship_status, step_order_id\n" + +// "FROM"); + selectListCache.add("SELECT biz_order_id, out_order_id, seller_nick, buyer_nick, seller_id\n" + + "\t, buyer_id, auction_id, auction_title, auction_price, buy_amount\n" + + "\t, biz_type, sub_biz_type, fail_reason, pay_status, logistics_status\n" + + "\t, out_trade_status, snap_path, gmt_create, status\n" + + "\t, ifnull(buyer_rate_status, 4) AS buyer_rate_status\n" + + "\t, ifnull(seller_rate_status, 4) AS seller_rate_status, auction_pict_url\n" + + "\t, seller_memo, buyer_memo, seller_flag, buyer_flag, buyer_message_path\n" + + "\t, refund_status, attributes, attributes_cc, gmt_modified, ip\n" + + "\t, end_time, pay_time, is_main, is_detail, point_rate\n" + + "\t, parent_id, adjust_fee, discount_fee, refund_fee, confirm_paid_fee\n" + + "\t, cod_status, trade_tag, shop_id, sync_version, options\n" + + "\t, ignore_sold_quantity, from_group, attribute1, attribute2, attribute3\n" + + "\t, attribute4, attribute11\n" + + "FROM"); + selectListCache.add("select `member_cart`.`CART_ID`,`member_cart`.`SKU_ID`,`member_cart`.`ITEM_ID`,`member_cart`.`QUANTITY`,`member_cart`.`USER_ID`,`member_cart`.`SELLER_ID`,`member_cart`.`STATUS`,`member_cart`.`EXT_STATUS`,`member_cart`.`TYPE`,`member_cart`.`SUB_TYPE`,`member_cart`.`GMT_CREATE`,`member_cart`.`GMT_MODIFIED`,`member_cart`.`ATTRIBUTE`,`member_cart`.`ATTRIBUTE_CC`,`member_cart`.`EX2` from"); + } + public static SqlHolder of(String sql) { return new SqlHolder(sql); } @@ -44,6 +75,11 @@ public class SqlHolder { this(text, JdbcConstants.MYSQL); } + public SqlHolder(String text, String dbType, boolean isParam) { + this(text, dbType); + this.isParam = isParam; + } + SqlHolder(String text, String dialect) { if (!"mysql".equalsIgnoreCase(dialect)) { throw new IllegalArgumentException("only mysql is"); @@ -78,9 +114,21 @@ public class SqlHolder { // } // ast = SQLUtils.parseStatements(text, dialect).get(0); - SQLParserFeature[] features = {SQLParserFeature.EnableSQLBinaryOpExprGroup, SQLParserFeature.OptimizedForParameterized}; + SQLParserFeature[] features; + + if (isParam) { + features = new SQLParserFeature[]{SQLParserFeature.EnableSQLBinaryOpExprGroup, SQLParserFeature.OptimizedForParameterized}; + } else { + features = new SQLParserFeature[]{SQLParserFeature.EnableSQLBinaryOpExprGroup + , SQLParserFeature.OptimizedForParameterized + , SQLParserFeature.UseInsertColumnsCache + }; + } + try { - ast = new SqlHolderParser(text, features).parseStatement(); + MySqlStatementParser parser = new MySqlStatementParser(text, features); + parser.setSelectListCache(selectListCache); + ast = parser.parseStatement(); } catch (ParserException e) { throw new UnsupportedOperationException(e); } @@ -238,75 +286,4 @@ public class SqlHolder { } return tableName; } - - public static class SqlHolderParser extends MySqlStatementParser { - - public SqlHolderParser(String sql, SQLParserFeature... features) { - super(sql, features); - } - - public void parseStatementList(List statementList, int max, SQLObject parent) { - // special optimized - if (lexer.token() == Token.SELECT) { - String source = lexer.getSource(); - if ("select @@session.tx_read_only".equals(source)) { - SQLSelect select = new SQLSelect(); - MySqlSelectQueryBlock queryBlock = new MySqlSelectQueryBlock(); - queryBlock.addSelectItem(new SQLPropertyExpr(new SQLVariantRefExpr("@@session"), "tx_read_only")); - select.setQuery(queryBlock); - - SQLSelectStatement stmt = new SQLSelectStatement(select); - statementList.add(stmt); - - lexer.reset(29, '\u001A', Token.EOF); - return; - } - - int pos = lexer.pos(); - if (source.startsWith(" id, dispute_id, buyer_id, seller_id, total_fee, refund_fee, max_apply_goods_fee, apply_goods_fee, apply_carriage_fee, refund_goods_fee, refund_carriage_fee, refund_point, refund_coupon, refund_return_point, refund_cash, real_deduct_refund_point, real_refund_return_point, refund_return_commission, gmt_create, gmt_modified, attributes, attributes_cc FROM", pos)) { - MySqlSelectQueryBlock queryBlock = new MySqlSelectQueryBlock(); - queryBlock.addSelectItem(new SQLIdentifierExpr("id")); - queryBlock.addSelectItem(new SQLIdentifierExpr("dispute_id")); - queryBlock.addSelectItem(new SQLIdentifierExpr("buyer_id")); - queryBlock.addSelectItem(new SQLIdentifierExpr("seller_id")); - queryBlock.addSelectItem(new SQLIdentifierExpr("total_fee")); - - queryBlock.addSelectItem(new SQLIdentifierExpr("refund_fee")); - queryBlock.addSelectItem(new SQLIdentifierExpr("max_apply_goods_fee")); - queryBlock.addSelectItem(new SQLIdentifierExpr("apply_goods_fee")); - queryBlock.addSelectItem(new SQLIdentifierExpr("apply_carriage_fee")); - queryBlock.addSelectItem(new SQLIdentifierExpr("refund_goods_fee")); - - queryBlock.addSelectItem(new SQLIdentifierExpr("refund_carriage_fee")); - queryBlock.addSelectItem(new SQLIdentifierExpr("refund_point")); - queryBlock.addSelectItem(new SQLIdentifierExpr("refund_coupon")); - queryBlock.addSelectItem(new SQLIdentifierExpr("refund_return_point")); - queryBlock.addSelectItem(new SQLIdentifierExpr("refund_cash")); - - queryBlock.addSelectItem(new SQLIdentifierExpr("real_deduct_refund_point")); - queryBlock.addSelectItem(new SQLIdentifierExpr("real_refund_return_point")); - queryBlock.addSelectItem(new SQLIdentifierExpr("refund_return_commission")); - queryBlock.addSelectItem(new SQLIdentifierExpr("gmt_create")); - queryBlock.addSelectItem(new SQLIdentifierExpr("gmt_modified")); - - queryBlock.addSelectItem(new SQLIdentifierExpr("attributes")); - queryBlock.addSelectItem(new SQLIdentifierExpr("attributes_cc")); - - lexer.reset(430, ' ', Token.FROM); - - MySqlSelectParser selectParser = new MySqlSelectParser(this.exprParser); - selectParser.parseFrom(queryBlock); - selectParser.parseWhere(queryBlock); - - SQLSelect select = new SQLSelect(queryBlock); - SQLSelectStatement stmt = new SQLSelectStatement(select); - stmt.setDbType(JdbcConstants.MYSQL); - statementList.add(stmt); - return; - } - } - - super.parseStatementList(statementList, max, parent); - } - } }