diff --git a/.gitignore b/.gitignore
index 87e2ec70..7b606e9c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -22,4 +22,10 @@ test/jquery*
test/ct_log_cache
logs/*
.#*
+.tags*
+.rebar
include/crypto_compat.hrl
+_build
+rebar3.crashdump
+rebar.lock
+.rebar3
\ No newline at end of file
diff --git a/.travis.yml b/.travis.yml
index 0c3e76c0..03a8d723 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -8,8 +8,12 @@ before_script:
- make
script: "make test"
+
otp_release:
- - 17.0-rc1
+ - 19.1
+ - 19.0
+ - 18.0
+ - 17.5
- R16B03-1
- R16B
- R15B03
diff --git a/CHANGES.md b/CHANGES.md
index 6657b966..a5439cc6 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -5,6 +5,11 @@
**If you run into trouble, please try the 'stable' branch.**
git checkout origin/stable
+#### Apr 27 2017 hd | doc
+* timestamp optimize
+
+#### Aug 26 2014 hd | doc
+* Adapted for R18
#### Jun 21 2013 hd | doc
* Remove utf-8 encoding of binary data
diff --git a/Makefile b/Makefile
index cd06e0a9..e5d78ed9 100644
--- a/Makefile
+++ b/Makefile
@@ -6,6 +6,19 @@ APP_NAME=emysql
MODULES=$(shell ls -1 src/*.erl | awk -F[/.] '{ print $$2 }' | sed '$$q;s/$$/,/g')
MAKETIME=$(shell date)
+## Check if we are on erlang version that has namespaced types
+ERL_NT=$(shell escript ./support/ntype_check.escript)
+
+## Check if we are on erlang version that has erlang:timestamp/0
+ERL_TS=$(shell escript ./support/timestamp_check.escript)
+
+ifeq ($(ERL_NT),true)
+ERLC_NT_FLAG=-Dnamespaced_types
+endif
+ifeq ($(ERL_TS),true)
+ERLC_TS_FLAG=-Dtimestamp_support
+endif
+
all: crypto_compat app
(cd src;$(MAKE))
@@ -80,7 +93,7 @@ CT_RUN = ct_run \
CT_SUITES=environment basics conn_mgr
build-tests:
- erlc -v -o test/ $(wildcard test/*.erl) -pa ebin/
+ erlc -v $(ERLC_NT_FLAG) $(ERLC_TS_FLAG) -o test/ $(wildcard test/*.erl) -pa ebin/
test: all build-tests
@mkdir -p logs
diff --git a/README.md b/README.md
index b603ba72..320dcc5b 100644
--- a/README.md
+++ b/README.md
@@ -1,79 +1,16 @@
# Emysql
-[![Build Status](https://travis-ci.org/Eonblast/Emysql.png?branch=master)](https://travis-ci.org/Eonblast/Emysql)
+[![Build Status](https://travis-ci.org/qingchuwudi/Emysql.svg?branch=master)](https://travis-ci.org/qingchuwudi/Emysql)
-To use this driver, see the [Samples] further down in this README document.
-
-
-
-Emysql implements a stable driver toward the MySQL database. It currently support fairly recent versions (somewhere around 5.3+) and it is considered fairly stable in production.
-
-The driver has several technical shortcomings:
-
-* No clear protocol / connection pool separation
-* No clear protocol / socket separation
-* A very complicated connection pool management
-* Uses the textual protocol in a lot of places where it shouldthe binary protocol
-* The API could be better
-
-*However,* this is probably the best MySQL driver out there for Erlang. The `erlang-mysql-driver` uses a problematic connection pool design for many use cases and is not suitable for general purpose use. This driver is.
-
-# Versioning
-
-Semantic versioning is used. Versions are given as `x.y.z`:
-
-* `x` changes break backward compatibility
-* `y` changes add new functionality—but does not break compatibility backwards
-* `z` changes recognizes a new version, but is not supposed to break anything
-
-# Changelog of recent changes
-
-## Emysql 0.4.1
-
-Spring cleaning in the repository:
+This is from [Eonblast/Emysql](https://github.com/Eonblast/Emysql)
-* Removed a lot of modules which is not part of the official API from the documentation.
-* Deprecated the use of `emysql_util` for `emysql`.
-* Made tests actually do something with the `emysql_util` calls.
-* Moved function calls from `emysql_util` into the modules where they belong.
-
-Change should be backwards compatible.
-
-## Emysql 0.4.0
-
-Introduced changes by Garrett Smith:
-
-* Support connection timeouts in gen_tcp:connect/3. This allows the driver to better handle connection timeouts upon initial connections.
-* Introduce `emysql:add_pool/2` as a proplist-based way of initializing a pool. This is going to be the preferred way of initializing pools in the future.
-
-## Emysql 0.3.2
-
-* We should be on Travis CI now with full tests running
-* Pulled in lots of smaller changes which should be rather cosmetic fixes.
-* R16 warnings eliminated (Jesse Gumm)
-* Tried to consolidate simple parts of the driver
-
-## Emysql 0.3.0
-
-*Note:* Automatic conversion to the encoding of the underlying MySQL
-server was removed in the 0.3.x branch. If you specify, e.g., utf-8
-encoding, then the MySQL server will reject wrongly-encoded strings
-and data, but the *driver* will not perform any encoding by itself
-anymore.
-
-It is now the driver *callers* responsibility to ensure that data is
-properly encoded. This change makes it possible to pass binary BLOB
-data to the MySQL server once again.
-
-# Overview:
-
-This is an Erlang MySQL driver, based on a rewrite at Electronic Arts. [Easy][Samples] to use, strong [connection pooling][Adding_a_Pool], [prepared statements][Executing_Prepared_Statements] & [stored procedures][Executing_Stored_Procedures]. Optimized for a central node architecture and OLTP.
+To use this driver, see the [Samples] further down in this README document.
-While you can use mysql via ODBC, you should see better performance when using a *driver* like Emysql. For [samples][Samples] and [docs][] see below. Read the brief on [choosing][Choosing] a package and about the [history][History] of the various MySQL drivers.
+## Introduction
-[Emysql][1] is a cleaner rewrite of [erlang-mysql-driver][2], see [History][]. This fork is a direct continuation of the original [emysql][1] with [fixes][], [updates][], more [documentation][docs] and [samples][Samples].
+[Eonblast/Emysql/README](https://github.com/Eonblast/Emysql/README.md)
-**This is the master branch. Should you run into problems, please report them by opening an issue at github and try if they go away by checking out the 'stable' branch. Thank you.**
+[inaka/Emysql/README](https://github.com/inaka/Emysql/README.md)
diff --git a/doc/emsql.gliffy b/doc/emsql.gliffy
new file mode 100644
index 00000000..26283893
--- /dev/null
+++ b/doc/emsql.gliffy
@@ -0,0 +1 @@
+{"contentType":"application/gliffy+json","version":"1.1","metadata":{"title":"untitled","revision":0,"exportBorder":false},"embeddedResources":{"index":0,"resources":[]},"stage":{"objects":[{"x":1882,"y":469,"rotation":0,"id":89,"uid":"com.gliffy.shape.basic.basic_v1.default.line","width":100,"height":100,"lockAspectRatio":false,"lockShape":false,"order":89,"graphic":{"type":"Line","Line":{"strokeWidth":2,"strokeColor":"#000000","fillColor":"none","dashStyle":null,"startArrow":0,"endArrow":2,"startArrowRotation":"auto","endArrowRotation":"auto","ortho":true,"interpolationType":"linear","cornerRadius":10,"controlPath":[[-2,201],[43,201],[43,486],[88,486]],"lockSegments":{}}},"children":null,"constraints":{"constraints":[],"startConstraint":{"type":"StartPositionConstraint","StartPositionConstraint":{"nodeId":52,"px":1,"py":0.5}},"endConstraint":{"type":"EndPositionConstraint","EndPositionConstraint":{"nodeId":75,"px":0,"py":0.5}}},"linkMap":[]},{"x":1883,"y":473,"rotation":0,"id":87,"uid":"com.gliffy.shape.basic.basic_v1.default.line","width":100,"height":100,"lockAspectRatio":false,"lockShape":false,"order":87,"graphic":{"type":"Line","Line":{"strokeWidth":2,"strokeColor":"#000000","fillColor":"none","dashStyle":null,"startArrow":0,"endArrow":2,"startArrowRotation":"auto","endArrowRotation":"auto","ortho":true,"interpolationType":"linear","cornerRadius":10,"controlPath":[[-3,197],[42,197],[42,407],[87,407]],"lockSegments":{}}},"children":null,"constraints":{"constraints":[],"startConstraint":{"type":"StartPositionConstraint","StartPositionConstraint":{"nodeId":52,"px":1,"py":0.5}},"endConstraint":{"type":"EndPositionConstraint","EndPositionConstraint":{"nodeId":73,"px":0,"py":0.5}}},"linkMap":[]},{"x":1882,"y":469,"rotation":0,"id":86,"uid":"com.gliffy.shape.basic.basic_v1.default.line","width":100,"height":100,"lockAspectRatio":false,"lockShape":false,"order":86,"graphic":{"type":"Line","Line":{"strokeWidth":2,"strokeColor":"#000000","fillColor":"none","dashStyle":null,"startArrow":0,"endArrow":2,"startArrowRotation":"auto","endArrowRotation":"auto","ortho":true,"interpolationType":"linear","cornerRadius":10,"controlPath":[[-2,201],[43,201],[43,326],[88,326]],"lockSegments":{}}},"children":null,"constraints":{"constraints":[],"startConstraint":{"type":"StartPositionConstraint","StartPositionConstraint":{"nodeId":52,"px":1,"py":0.5}},"endConstraint":{"type":"EndPositionConstraint","EndPositionConstraint":{"nodeId":71,"px":0,"py":0.5}}},"linkMap":[]},{"x":1880,"y":473,"rotation":0,"id":84,"uid":"com.gliffy.shape.basic.basic_v1.default.line","width":100,"height":100,"lockAspectRatio":false,"lockShape":false,"order":84,"graphic":{"type":"Line","Line":{"strokeWidth":2,"strokeColor":"#000000","fillColor":"none","dashStyle":null,"startArrow":0,"endArrow":2,"startArrowRotation":"auto","endArrowRotation":"auto","ortho":true,"interpolationType":"linear","cornerRadius":10,"controlPath":[[0,197],[45,197],[45,237],[90,237]],"lockSegments":{}}},"children":null,"constraints":{"constraints":[],"startConstraint":{"type":"StartPositionConstraint","StartPositionConstraint":{"nodeId":52,"px":1,"py":0.5}},"endConstraint":{"type":"EndPositionConstraint","EndPositionConstraint":{"nodeId":69,"px":0,"py":0.5}}},"linkMap":[]},{"x":1877,"y":466,"rotation":0,"id":83,"uid":"com.gliffy.shape.basic.basic_v1.default.line","width":100,"height":100,"lockAspectRatio":false,"lockShape":false,"order":83,"graphic":{"type":"Line","Line":{"strokeWidth":2,"strokeColor":"#000000","fillColor":"none","dashStyle":null,"startArrow":0,"endArrow":2,"startArrowRotation":"auto","endArrowRotation":"auto","ortho":true,"interpolationType":"linear","cornerRadius":10,"controlPath":[[3,204],[48,204],[48,174],[93,174]],"lockSegments":{}}},"children":null,"constraints":{"constraints":[],"startConstraint":{"type":"StartPositionConstraint","StartPositionConstraint":{"nodeId":52,"px":1,"py":0.5}},"endConstraint":{"type":"EndPositionConstraint","EndPositionConstraint":{"nodeId":67,"px":0,"py":0.5}}},"linkMap":[]},{"x":1879,"y":472,"rotation":0,"id":82,"uid":"com.gliffy.shape.basic.basic_v1.default.line","width":100,"height":100,"lockAspectRatio":false,"lockShape":false,"order":82,"graphic":{"type":"Line","Line":{"strokeWidth":2,"strokeColor":"#000000","fillColor":"none","dashStyle":null,"startArrow":0,"endArrow":2,"startArrowRotation":"auto","endArrowRotation":"auto","ortho":true,"interpolationType":"linear","cornerRadius":10,"controlPath":[[1,198],[46,198],[46,98],[91,98]],"lockSegments":{}}},"children":null,"constraints":{"constraints":[],"startConstraint":{"type":"StartPositionConstraint","StartPositionConstraint":{"nodeId":52,"px":1,"py":0.5}},"endConstraint":{"type":"EndPositionConstraint","EndPositionConstraint":{"nodeId":65,"px":0,"py":0.5}}},"linkMap":[]},{"x":1879,"y":472,"rotation":0,"id":81,"uid":"com.gliffy.shape.basic.basic_v1.default.line","width":100,"height":100,"lockAspectRatio":false,"lockShape":false,"order":81,"graphic":{"type":"Line","Line":{"strokeWidth":2,"strokeColor":"#000000","fillColor":"none","dashStyle":null,"startArrow":0,"endArrow":2,"startArrowRotation":"auto","endArrowRotation":"auto","ortho":true,"interpolationType":"linear","cornerRadius":10,"controlPath":[[1,198],[46,198],[46,26.75],[91,26.75]],"lockSegments":{}}},"children":null,"constraints":{"constraints":[],"startConstraint":{"type":"StartPositionConstraint","StartPositionConstraint":{"nodeId":52,"px":1,"py":0.5}},"endConstraint":{"type":"EndPositionConstraint","EndPositionConstraint":{"nodeId":63,"px":0,"py":0.5}}},"linkMap":[]},{"x":1879,"y":468,"rotation":0,"id":80,"uid":"com.gliffy.shape.basic.basic_v1.default.line","width":100,"height":100,"lockAspectRatio":false,"lockShape":false,"order":80,"graphic":{"type":"Line","Line":{"strokeWidth":2,"strokeColor":"#000000","fillColor":"none","dashStyle":null,"startArrow":0,"endArrow":2,"startArrowRotation":"auto","endArrowRotation":"auto","ortho":true,"interpolationType":"linear","cornerRadius":10,"controlPath":[[1,202],[46,202],[46,-33],[91,-33]],"lockSegments":{}}},"children":null,"constraints":{"constraints":[],"startConstraint":{"type":"StartPositionConstraint","StartPositionConstraint":{"nodeId":52,"px":1,"py":0.5}},"endConstraint":{"type":"EndPositionConstraint","EndPositionConstraint":{"nodeId":60,"px":0,"py":0.5}}},"linkMap":[]},{"x":1878,"y":470,"rotation":0,"id":79,"uid":"com.gliffy.shape.basic.basic_v1.default.line","width":100,"height":100,"lockAspectRatio":false,"lockShape":false,"order":79,"graphic":{"type":"Line","Line":{"strokeWidth":2,"strokeColor":"#000000","fillColor":"none","dashStyle":null,"startArrow":0,"endArrow":2,"startArrowRotation":"auto","endArrowRotation":"auto","ortho":true,"interpolationType":"linear","cornerRadius":10,"controlPath":[[2,200],[47,200],[47,-91.25],[92,-91.25]],"lockSegments":{}}},"children":null,"constraints":{"constraints":[],"startConstraint":{"type":"StartPositionConstraint","StartPositionConstraint":{"nodeId":52,"px":1,"py":0.5}},"endConstraint":{"type":"EndPositionConstraint","EndPositionConstraint":{"nodeId":57,"px":0,"py":0.5}}},"linkMap":[]},{"x":1711,"y":570,"rotation":0,"id":78,"uid":"com.gliffy.shape.basic.basic_v1.default.line","width":100,"height":100,"lockAspectRatio":false,"lockShape":false,"order":78,"graphic":{"type":"Line","Line":{"strokeWidth":2,"strokeColor":"#000000","fillColor":"none","dashStyle":null,"startArrow":0,"endArrow":2,"startArrowRotation":"auto","endArrowRotation":"auto","ortho":true,"interpolationType":"linear","cornerRadius":10,"controlPath":[[-1,305],[34,305],[34,100],[69,100]],"lockSegments":{}}},"children":null,"constraints":{"constraints":[],"startConstraint":{"type":"StartPositionConstraint","StartPositionConstraint":{"nodeId":45,"px":1,"py":0.5}},"endConstraint":{"type":"EndPositionConstraint","EndPositionConstraint":{"nodeId":52,"px":0,"py":0.5}}},"linkMap":[]},{"x":1716,"y":574,"rotation":0,"id":77,"uid":"com.gliffy.shape.basic.basic_v1.default.line","width":100,"height":100,"lockAspectRatio":false,"lockShape":false,"order":77,"graphic":{"type":"Line","Line":{"strokeWidth":2,"strokeColor":"#000000","fillColor":"none","dashStyle":null,"startArrow":0,"endArrow":2,"startArrowRotation":"auto","endArrowRotation":"auto","ortho":true,"interpolationType":"linear","cornerRadius":10,"controlPath":[[-6,301],[29,301],[29,496],[64,496]],"lockSegments":{}}},"children":null,"constraints":{"constraints":[],"startConstraint":{"type":"StartPositionConstraint","StartPositionConstraint":{"nodeId":45,"px":1,"py":0.5}},"endConstraint":{"type":"EndPositionConstraint","EndPositionConstraint":{"nodeId":55,"px":0,"py":0.5}}},"linkMap":[]},{"x":1970,"y":417.5,"rotation":0,"id":60,"uid":"com.gliffy.shape.flowchart.flowchart_v1.default.process","width":100,"height":35,"lockAspectRatio":false,"lockShape":false,"order":37,"graphic":{"type":"Shape","Shape":{"tid":"com.gliffy.stencil.rectangle.basic_v1","strokeWidth":2,"strokeColor":"#333333","fillColor":"#FFFFFF","gradient":false,"dropShadow":false,"state":0,"shadowX":0,"shadowY":0,"opacity":1}},"children":[{"x":2,"y":0,"rotation":0,"id":62,"uid":null,"width":96,"height":28,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Text","Text":{"tid":null,"valign":"middle","overflow":"none","vposition":"none","hposition":"none","html":"has_pool\n
判断是否有
","paddingLeft":2,"paddingRight":2,"paddingBottom":2,"paddingTop":2}},"children":null}],"linkMap":[]},{"x":1970,"y":360,"rotation":0,"id":57,"uid":"com.gliffy.shape.flowchart.flowchart_v1.default.process","width":100,"height":37.5,"lockAspectRatio":false,"lockShape":false,"order":35,"graphic":{"type":"Shape","Shape":{"tid":"com.gliffy.stencil.rectangle.basic_v1","strokeWidth":2,"strokeColor":"#333333","fillColor":"#FFFFFF","gradient":false,"dropShadow":false,"state":0,"shadowX":0,"shadowY":0,"opacity":1}},"children":[{"x":2,"y":0,"rotation":0,"id":59,"uid":null,"width":96,"height":28,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Text","Text":{"tid":null,"valign":"middle","overflow":"none","vposition":"none","hposition":"none","html":"pool\n
查找
","paddingLeft":2,"paddingRight":2,"paddingBottom":2,"paddingTop":2}},"children":null}],"linkMap":[]},{"x":1780,"y":650,"rotation":0,"id":52,"uid":"com.gliffy.shape.flowchart.flowchart_v1.default.process","width":100,"height":40,"lockAspectRatio":false,"lockShape":false,"order":31,"graphic":{"type":"Shape","Shape":{"tid":"com.gliffy.stencil.rectangle.basic_v1","strokeWidth":2,"strokeColor":"#333333","fillColor":"#FFFFFF","gradient":false,"dropShadow":false,"state":0,"shadowX":0,"shadowY":0,"opacity":1}},"children":[{"x":2,"y":0,"rotation":0,"id":54,"uid":null,"width":96,"height":14,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Text","Text":{"tid":null,"valign":"middle","overflow":"none","vposition":"none","hposition":"none","html":"handle_call
","paddingLeft":2,"paddingRight":2,"paddingBottom":2,"paddingTop":2}},"children":null}],"linkMap":[]},{"x":1609,"y":571,"rotation":0,"id":50,"uid":"com.gliffy.shape.basic.basic_v1.default.line","width":100,"height":100,"lockAspectRatio":false,"lockShape":false,"order":30,"graphic":{"type":"Line","Line":{"strokeWidth":2,"strokeColor":"#000000","fillColor":"none","dashStyle":null,"startArrow":0,"endArrow":2,"startArrowRotation":"auto","endArrowRotation":"auto","ortho":true,"interpolationType":"linear","cornerRadius":10,"controlPath":[[1,304],[-39,304],[-39,239],[30.28932188134513,239],[30.28932188134513,279]],"lockSegments":{}}},"children":null,"constraints":{"constraints":[],"startConstraint":{"type":"StartPositionConstraint","StartPositionConstraint":{"nodeId":45,"px":0,"py":0.5}},"endConstraint":{"type":"EndPositionConstraint","EndPositionConstraint":{"nodeId":45,"px":0.2928932188134524,"py":0}}},"linkMap":[]},{"x":1661,"y":300,"rotation":0,"id":48,"uid":"com.gliffy.shape.basic.basic_v1.default.line","width":100,"height":100,"lockAspectRatio":false,"lockShape":false,"order":29,"graphic":{"type":"Line","Line":{"strokeWidth":2,"strokeColor":"#000000","fillColor":"none","dashStyle":null,"startArrow":0,"endArrow":2,"startArrowRotation":"auto","endArrowRotation":"auto","ortho":true,"interpolationType":"linear","cornerRadius":10,"controlPath":[[-1,-30],[-1,163.33333333333337],[-1,356.66666666666674],[-1,550]],"lockSegments":{}}},"children":null,"constraints":{"constraints":[],"startConstraint":{"type":"StartPositionConstraint","StartPositionConstraint":{"nodeId":29,"px":0.5,"py":1}},"endConstraint":{"type":"EndPositionConstraint","EndPositionConstraint":{"nodeId":45,"px":0.5,"py":0}}},"linkMap":[]},{"x":1610,"y":850,"rotation":0,"id":45,"uid":"com.gliffy.shape.flowchart.flowchart_v1.default.subroutine","width":100,"height":50,"lockAspectRatio":false,"lockShape":false,"order":27,"graphic":{"type":"Shape","Shape":{"tid":"com.gliffy.stencil.subroutine.flowchart_v1","strokeWidth":2,"strokeColor":"#333333","fillColor":"#FFFFFF","gradient":false,"dropShadow":false,"state":0,"shadowX":0,"shadowY":0,"opacity":1}},"children":[{"x":2,"y":0,"rotation":0,"id":47,"uid":null,"width":96,"height":14,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Text","Text":{"tid":null,"valign":"middle","overflow":"none","vposition":"none","hposition":"none","html":"loop
","paddingLeft":2,"paddingRight":2,"paddingBottom":2,"paddingTop":2}},"children":null}],"linkMap":[]},{"x":1750,"y":52,"rotation":0,"id":42,"uid":"com.gliffy.shape.uml.uml_v1.default.note","width":100,"height":63,"lockAspectRatio":false,"lockShape":false,"order":25,"graphic":{"type":"Shape","Shape":{"tid":"com.gliffy.stencil.note.uml_v1","strokeWidth":1,"strokeColor":"#000000","fillColor":"#ffe599","gradient":false,"dropShadow":false,"state":0,"shadowX":0,"shadowY":0,"opacity":1}},"children":[{"x":2,"y":0,"rotation":0,"id":44,"uid":null,"width":96,"height":14,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Text","Text":{"tid":null,"valign":"middle","overflow":"none","vposition":"none","hposition":"none","html":"连接池管理进程
","paddingLeft":2,"paddingRight":2,"paddingBottom":2,"paddingTop":2}},"children":null}],"linkMap":[]},{"x":1824,"y":277,"rotation":0,"id":40,"uid":"com.gliffy.shape.basic.basic_v1.default.line","width":100,"height":100,"lockAspectRatio":false,"lockShape":false,"order":24,"graphic":{"type":"Line","Line":{"strokeWidth":2,"strokeColor":"#000000","fillColor":"none","dashStyle":null,"startArrow":0,"endArrow":2,"startArrowRotation":"auto","endArrowRotation":"auto","ortho":true,"interpolationType":"linear","cornerRadius":10,"controlPath":[[6,-21.644660940672622],[-34,-21.644660940672622],[-74,-21.644660940672622],[-114,-21.644660940672622]],"lockSegments":{}}},"children":null,"constraints":{"constraints":[],"startConstraint":{"type":"StartPositionConstraint","StartPositionConstraint":{"nodeId":32,"px":0,"py":0.7071067811865475}},"endConstraint":{"type":"EndPositionConstraint","EndPositionConstraint":{"nodeId":29,"px":0.9999999999999998,"py":0.7071067811865475}}},"linkMap":[]},{"x":1716,"y":244,"rotation":0,"id":39,"uid":"com.gliffy.shape.basic.basic_v1.default.line","width":100,"height":100,"lockAspectRatio":false,"lockShape":false,"order":23,"graphic":{"type":"Line","Line":{"strokeWidth":2,"strokeColor":"#000000","fillColor":"none","dashStyle":null,"startArrow":0,"endArrow":2,"startArrowRotation":"auto","endArrowRotation":"auto","ortho":true,"interpolationType":"linear","cornerRadius":10,"controlPath":[[-6,-9.355339059327378],[79,-9.355339059327378],[79,-64],[164,-64],[164,-24]],"lockSegments":{}}},"children":null,"constraints":{"constraints":[],"startConstraint":{"type":"StartPositionConstraint","StartPositionConstraint":{"nodeId":29,"px":1,"py":0.29289321881345237}},"endConstraint":{"type":"EndPositionConstraint","EndPositionConstraint":{"nodeId":32,"px":0.5,"py":0}}},"linkMap":[]},{"x":1659,"y":141,"rotation":0,"id":38,"uid":"com.gliffy.shape.basic.basic_v1.default.line","width":100,"height":100,"lockAspectRatio":false,"lockShape":false,"order":22,"graphic":{"type":"Line","Line":{"strokeWidth":2,"strokeColor":"#000000","fillColor":"none","dashStyle":null,"startArrow":0,"endArrow":2,"startArrowRotation":"auto","endArrowRotation":"auto","ortho":true,"interpolationType":"linear","cornerRadius":10,"controlPath":[[1,-1],[1,25.666666666666657],[1,52.33333333333334],[1,79]],"lockSegments":{}}},"children":null,"constraints":{"constraints":[],"startConstraint":{"type":"StartPositionConstraint","StartPositionConstraint":{"nodeId":24,"px":0.5,"py":1}},"endConstraint":{"type":"EndPositionConstraint","EndPositionConstraint":{"nodeId":29,"px":0.5,"py":0}}},"linkMap":[]},{"x":1970,"y":188.5,"rotation":0,"id":35,"uid":"com.gliffy.shape.uml.uml_v1.default.note","width":130,"height":63,"lockAspectRatio":false,"lockShape":false,"order":20,"graphic":{"type":"Shape","Shape":{"tid":"com.gliffy.stencil.note.uml_v1","strokeWidth":1,"strokeColor":"#000000","fillColor":"#ffe599","gradient":false,"dropShadow":false,"state":0,"shadowX":0,"shadowY":0,"opacity":1}},"children":[{"x":2.5999999999999996,"y":0,"rotation":0,"id":37,"uid":null,"width":124.79999999999998,"height":28,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Text","Text":{"tid":null,"valign":"middle","overflow":"none","vposition":"none","hposition":"none","html":"初始化一个app.src配置文件中的连接池
","paddingLeft":2,"paddingRight":2,"paddingBottom":2,"paddingTop":2}},"children":null}],"linkMap":[]},{"x":1830,"y":220,"rotation":0,"id":32,"uid":"com.gliffy.shape.flowchart.flowchart_v1.default.process","width":100,"height":50,"lockAspectRatio":false,"lockShape":false,"order":18,"graphic":{"type":"Shape","Shape":{"tid":"com.gliffy.stencil.rectangle.basic_v1","strokeWidth":2,"strokeColor":"#333333","fillColor":"#FFFFFF","gradient":false,"dropShadow":false,"state":0,"shadowX":0,"shadowY":0,"opacity":1}},"children":[{"x":2,"y":0,"rotation":0,"id":34,"uid":null,"width":96,"height":14,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Text","Text":{"tid":null,"valign":"middle","overflow":"none","vposition":"none","hposition":"none","html":"initialize_pools()
","paddingLeft":2,"paddingRight":2,"paddingBottom":2,"paddingTop":2}},"children":null}],"linkMap":[]},{"x":1610,"y":220,"rotation":0,"id":29,"uid":"com.gliffy.shape.flowchart.flowchart_v1.default.subroutine","width":100,"height":50,"lockAspectRatio":false,"lockShape":false,"order":16,"graphic":{"type":"Shape","Shape":{"tid":"com.gliffy.stencil.subroutine.flowchart_v1","strokeWidth":2,"strokeColor":"#333333","fillColor":"#FFFFFF","gradient":false,"dropShadow":false,"state":0,"shadowX":0,"shadowY":0,"opacity":1}},"children":[{"x":2,"y":0,"rotation":0,"id":31,"uid":null,"width":96,"height":14,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Text","Text":{"tid":null,"valign":"middle","overflow":"none","vposition":"none","hposition":"none","html":"init
","paddingLeft":2,"paddingRight":2,"paddingBottom":2,"paddingTop":2}},"children":null}],"linkMap":[]},{"x":1590,"y":90,"rotation":0,"id":24,"uid":"com.gliffy.shape.flowchart.flowchart_v1.default.start_end","width":140,"height":50,"lockAspectRatio":false,"lockShape":false,"order":14,"graphic":{"type":"Shape","Shape":{"tid":"com.gliffy.stencil.start_end.flowchart_v1","strokeWidth":2,"strokeColor":"#333333","fillColor":"#FFFFFF","gradient":false,"dropShadow":false,"state":0,"shadowX":0,"shadowY":0,"opacity":1}},"children":[{"x":2.7999999999999994,"y":0,"rotation":0,"id":26,"uid":null,"width":134.39999999999998,"height":14,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Text","Text":{"tid":null,"valign":"middle","overflow":"none","vposition":"none","hposition":"none","html":"emysql_conn_mgr
","paddingLeft":2,"paddingRight":2,"paddingBottom":2,"paddingTop":2}},"children":null}],"linkMap":[]},{"x":520,"y":380,"rotation":0,"id":21,"uid":"com.gliffy.shape.basic.basic_v1.default.line","width":100,"height":100,"lockAspectRatio":false,"lockShape":false,"order":13,"graphic":{"type":"Line","Line":{"strokeWidth":2,"strokeColor":"#000000","fillColor":"none","dashStyle":null,"startArrow":0,"endArrow":2,"startArrowRotation":"auto","endArrowRotation":"auto","ortho":true,"interpolationType":"linear","cornerRadius":10,"controlPath":[[0,1.75],[13.33352952052519,1.75],[26.66705904105038,1.75],[40.00058856157557,1.75]],"lockSegments":{}}},"children":null,"constraints":{"constraints":[],"startConstraint":{"type":"StartPositionConstraint","StartPositionConstraint":{"nodeId":18,"px":1,"py":0.5}},"endConstraint":{"type":"EndPositionConstraint","EndPositionConstraint":{"nodeId":6,"px":1.1102230246251563e-16,"py":0.2928932188134525}}},"linkMap":[]},{"x":310,"y":328.5,"rotation":0,"id":18,"uid":"com.gliffy.shape.uml.uml_v1.default.note","width":210,"height":106.5,"lockAspectRatio":false,"lockShape":false,"order":11,"graphic":{"type":"Shape","Shape":{"tid":"com.gliffy.stencil.note.uml_v1","strokeWidth":1,"strokeColor":"#000000","fillColor":"#ffe599","gradient":false,"dropShadow":false,"state":0,"shadowX":0,"shadowY":0,"opacity":1}},"children":[{"x":4.199999999999998,"y":0,"rotation":0,"id":20,"uid":null,"width":201.59999999999994,"height":84,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Text","Text":{"tid":null,"valign":"middle","overflow":"none","vposition":"none","hposition":"none","html":"1. gb_tree存储数据\n
2. 预定义Sql模板,\"?\"表示可以替换的变量\n
2.1 保存模板\n
2.2 传入Sql参数\n
2.3 执行
","paddingLeft":2,"paddingRight":2,"paddingBottom":2,"paddingTop":2}},"children":null}],"linkMap":[]},{"x":792,"y":274,"rotation":0,"id":15,"uid":"com.gliffy.shape.basic.basic_v1.default.line","width":100,"height":100,"lockAspectRatio":false,"lockShape":false,"order":10,"graphic":{"type":"Line","Line":{"strokeWidth":2,"strokeColor":"#000000","fillColor":"none","dashStyle":null,"startArrow":0,"endArrow":2,"startArrowRotation":"auto","endArrowRotation":"auto","ortho":true,"interpolationType":"linear","cornerRadius":10,"controlPath":[[-1.289321881345245,1],[-1.289321881345245,43.5],[153,43.5],[153,86]],"lockSegments":{}}},"children":null,"constraints":{"constraints":[],"startConstraint":{"type":"StartPositionConstraint","StartPositionConstraint":{"nodeId":3,"px":0.7071067811865476,"py":1}},"endConstraint":{"type":"EndPositionConstraint","EndPositionConstraint":{"nodeId":9,"px":0.5,"py":0}}},"linkMap":[]},{"x":747,"y":274,"rotation":0,"id":14,"uid":"com.gliffy.shape.basic.basic_v1.default.line","width":100,"height":100,"lockAspectRatio":false,"lockShape":false,"order":9,"graphic":{"type":"Line","Line":{"strokeWidth":2,"strokeColor":"#000000","fillColor":"none","dashStyle":null,"startArrow":0,"endArrow":2,"startArrowRotation":"auto","endArrowRotation":"auto","ortho":true,"interpolationType":"linear","cornerRadius":10,"controlPath":[[2.289321881345245,1],[2.289321881345245,43.5],[-137,43.5],[-137,86]],"lockSegments":{}}},"children":null,"constraints":{"constraints":[],"startConstraint":{"type":"StartPositionConstraint","StartPositionConstraint":{"nodeId":3,"px":0.29289321881345254,"py":0.9999999999999998}},"endConstraint":{"type":"EndPositionConstraint","EndPositionConstraint":{"nodeId":6,"px":0.5,"py":0}}},"linkMap":[]},{"x":772,"y":141,"rotation":0,"id":12,"uid":"com.gliffy.shape.basic.basic_v1.default.line","width":100,"height":100,"lockAspectRatio":false,"lockShape":false,"order":8,"graphic":{"type":"Line","Line":{"strokeWidth":2,"strokeColor":"#000000","fillColor":"none","dashStyle":null,"startArrow":0,"endArrow":2,"startArrowRotation":"auto","endArrowRotation":"auto","ortho":true,"interpolationType":"linear","cornerRadius":10,"controlPath":[[-2,-1],[-2,19],[-2,39],[-2,59]],"lockSegments":{}}},"children":null,"constraints":{"constraints":[],"startConstraint":{"type":"StartPositionConstraint","StartPositionConstraint":{"nodeId":0,"px":0.5,"py":1}},"endConstraint":{"type":"EndPositionConstraint","EndPositionConstraint":{"nodeId":3,"px":0.5,"py":0}}},"linkMap":[]},{"x":880,"y":360,"rotation":0,"id":9,"uid":"com.gliffy.shape.flowchart.flowchart_v1.default.process","width":130,"height":75,"lockAspectRatio":false,"lockShape":false,"order":6,"graphic":{"type":"Shape","Shape":{"tid":"com.gliffy.stencil.rectangle.basic_v1","strokeWidth":2,"strokeColor":"#333333","fillColor":"#FFFFFF","gradient":false,"dropShadow":false,"state":0,"shadowX":0,"shadowY":0,"opacity":1}},"children":[{"x":2.5999999999999996,"y":0,"rotation":0,"id":11,"uid":null,"width":124.8,"height":14,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Text","Text":{"tid":null,"valign":"middle","overflow":"none","vposition":"none","hposition":"none","html":"emysql_conn_mgr
","paddingLeft":2,"paddingRight":2,"paddingBottom":2,"paddingTop":2}},"children":null}],"linkMap":[]},{"x":560,"y":360,"rotation":0,"id":6,"uid":"com.gliffy.shape.flowchart.flowchart_v1.default.process","width":100,"height":75,"lockAspectRatio":false,"lockShape":false,"order":4,"graphic":{"type":"Shape","Shape":{"tid":"com.gliffy.stencil.rectangle.basic_v1","strokeWidth":2,"strokeColor":"#333333","fillColor":"#FFFFFF","gradient":false,"dropShadow":false,"state":0,"shadowX":0,"shadowY":0,"opacity":1}},"children":[{"x":2,"y":0,"rotation":0,"id":8,"uid":null,"width":96,"height":28,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Text","Text":{"tid":null,"valign":"middle","overflow":"none","vposition":"none","hposition":"none","html":"emysql_statements
","paddingLeft":2,"paddingRight":2,"paddingBottom":2,"paddingTop":2}},"children":null}],"linkMap":[]},{"x":720,"y":200,"rotation":0,"id":3,"uid":"com.gliffy.shape.flowchart.flowchart_v1.default.subroutine","width":100,"height":75,"lockAspectRatio":false,"lockShape":false,"order":2,"graphic":{"type":"Shape","Shape":{"tid":"com.gliffy.stencil.subroutine.flowchart_v1","strokeWidth":2,"strokeColor":"#333333","fillColor":"#FFFFFF","gradient":false,"dropShadow":false,"state":0,"shadowX":0,"shadowY":0,"opacity":1}},"children":[{"x":2,"y":0,"rotation":0,"id":5,"uid":null,"width":96,"height":14,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Text","Text":{"tid":null,"valign":"middle","overflow":"none","vposition":"none","hposition":"none","html":"emysql_sup
","paddingLeft":2,"paddingRight":2,"paddingBottom":2,"paddingTop":2}},"children":null}],"linkMap":[]},{"x":720,"y":90,"rotation":0,"id":0,"uid":"com.gliffy.shape.flowchart.flowchart_v1.default.start_end","width":100,"height":50,"lockAspectRatio":false,"lockShape":false,"order":0,"graphic":{"type":"Shape","Shape":{"tid":"com.gliffy.stencil.start_end.flowchart_v1","strokeWidth":2,"strokeColor":"#333333","fillColor":"#FFFFFF","gradient":false,"dropShadow":false,"state":0,"shadowX":0,"shadowY":0,"opacity":1}},"children":[{"x":2,"y":0,"rotation":0,"id":2,"uid":null,"width":96,"height":14,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Text","Text":{"tid":null,"valign":"middle","overflow":"none","vposition":"none","hposition":"none","html":"emysql_app
","paddingLeft":2,"paddingRight":2,"paddingBottom":2,"paddingTop":2}},"children":null}],"linkMap":[]},{"x":1780,"y":1050,"rotation":0,"id":55,"uid":"com.gliffy.shape.flowchart.flowchart_v1.default.process","width":100,"height":40,"lockAspectRatio":false,"lockShape":false,"order":33,"graphic":{"type":"Shape","Shape":{"tid":"com.gliffy.stencil.rectangle.basic_v1","strokeWidth":2,"strokeColor":"#333333","fillColor":"#FFFFFF","gradient":false,"dropShadow":false,"state":0,"shadowX":0,"shadowY":0,"opacity":1}},"children":[{"x":2,"y":0,"rotation":0,"id":56,"uid":null,"width":96,"height":14,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Text","Text":{"tid":null,"valign":"middle","overflow":"none","vposition":"none","hposition":"none","html":"handle_info
","paddingLeft":2,"paddingRight":2,"paddingBottom":2,"paddingTop":2}},"children":null}],"linkMap":[]},{"x":1970,"y":480,"rotation":0,"id":63,"uid":"com.gliffy.shape.flowchart.flowchart_v1.default.process","width":100,"height":37.5,"lockAspectRatio":false,"lockShape":false,"order":39,"graphic":{"type":"Shape","Shape":{"tid":"com.gliffy.stencil.rectangle.basic_v1","strokeWidth":2,"strokeColor":"#333333","fillColor":"#FFFFFF","gradient":false,"dropShadow":false,"state":0,"shadowX":0,"shadowY":0,"opacity":1}},"children":[{"x":2,"y":0,"rotation":0,"id":64,"uid":null,"width":96,"height":28,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Text","Text":{"tid":null,"valign":"middle","overflow":"none","vposition":"none","hposition":"none","html":"add_pool\n
添加连接池
","paddingLeft":2,"paddingRight":2,"paddingBottom":2,"paddingTop":2}},"children":null}],"linkMap":[]},{"x":1970,"y":550,"rotation":0,"id":65,"uid":"com.gliffy.shape.flowchart.flowchart_v1.default.process","width":100,"height":40,"lockAspectRatio":false,"lockShape":false,"order":41,"graphic":{"type":"Shape","Shape":{"tid":"com.gliffy.stencil.rectangle.basic_v1","strokeWidth":2,"strokeColor":"#333333","fillColor":"#FFFFFF","gradient":false,"dropShadow":false,"state":0,"shadowX":0,"shadowY":0,"opacity":1}},"children":[{"x":2,"y":0,"rotation":0,"id":66,"uid":null,"width":96,"height":28,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Text","Text":{"tid":null,"valign":"middle","overflow":"none","vposition":"none","hposition":"none","html":"remove_pool\n
删除连接池
","paddingLeft":2,"paddingRight":2,"paddingBottom":2,"paddingTop":2}},"children":null}],"linkMap":[]},{"x":1970,"y":620,"rotation":0,"id":67,"uid":"com.gliffy.shape.flowchart.flowchart_v1.default.process","width":130,"height":40,"lockAspectRatio":false,"lockShape":false,"order":43,"graphic":{"type":"Shape","Shape":{"tid":"com.gliffy.stencil.rectangle.basic_v1","strokeWidth":2,"strokeColor":"#333333","fillColor":"#FFFFFF","gradient":false,"dropShadow":false,"state":0,"shadowX":0,"shadowY":0,"opacity":1}},"children":[{"x":2.6,"y":0,"rotation":0,"id":68,"uid":null,"width":124.80000000000001,"height":28,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Text","Text":{"tid":null,"valign":"middle","overflow":"none","vposition":"none","hposition":"none","html":"add_connections\n
增加连接到连接池
","paddingLeft":2,"paddingRight":2,"paddingBottom":2,"paddingTop":2}},"children":null}],"linkMap":[]},{"x":1970,"y":690,"rotation":0,"id":69,"uid":"com.gliffy.shape.flowchart.flowchart_v1.default.process","width":130,"height":40,"lockAspectRatio":false,"lockShape":false,"order":45,"graphic":{"type":"Shape","Shape":{"tid":"com.gliffy.stencil.rectangle.basic_v1","strokeWidth":2,"strokeColor":"#333333","fillColor":"#FFFFFF","gradient":false,"dropShadow":false,"state":0,"shadowX":0,"shadowY":0,"opacity":1}},"children":[{"x":2.6,"y":0,"rotation":0,"id":70,"uid":null,"width":124.80000000000001,"height":28,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Text","Text":{"tid":null,"valign":"middle","overflow":"none","vposition":"none","hposition":"none","html":"remove_connections\n
删除一定数量的连接
","paddingLeft":2,"paddingRight":2,"paddingBottom":2,"paddingTop":2}},"children":null}],"linkMap":[]},{"x":1970,"y":765,"rotation":0,"id":71,"uid":"com.gliffy.shape.flowchart.flowchart_v1.default.process","width":130,"height":60,"lockAspectRatio":false,"lockShape":false,"order":47,"graphic":{"type":"Shape","Shape":{"tid":"com.gliffy.stencil.rectangle.basic_v1","strokeWidth":2,"strokeColor":"#333333","fillColor":"#FFFFFF","gradient":false,"dropShadow":false,"state":0,"shadowX":0,"shadowY":0,"opacity":1}},"children":[{"x":2.6,"y":0,"rotation":0,"id":72,"uid":null,"width":124.80000000000001,"height":42,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Text","Text":{"tid":null,"valign":"middle","overflow":"none","vposition":"none","hposition":"none","html":"lock_connection\n
锁定某连接池的一个连接,加入到等待队列
","paddingLeft":2,"paddingRight":2,"paddingBottom":2,"paddingTop":2}},"children":null}],"linkMap":[]},{"x":1970,"y":860,"rotation":0,"id":73,"uid":"com.gliffy.shape.flowchart.flowchart_v1.default.process","width":130,"height":40,"lockAspectRatio":false,"lockShape":false,"order":49,"graphic":{"type":"Shape","Shape":{"tid":"com.gliffy.stencil.rectangle.basic_v1","strokeWidth":2,"strokeColor":"#333333","fillColor":"#FFFFFF","gradient":false,"dropShadow":false,"state":0,"shadowX":0,"shadowY":0,"opacity":1}},"children":[{"x":2.6,"y":0,"rotation":0,"id":74,"uid":null,"width":124.80000000000001,"height":28,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Text","Text":{"tid":null,"valign":"middle","overflow":"none","vposition":"none","hposition":"none","html":"abort_wait\n
从等待队列删除
","paddingLeft":2,"paddingRight":2,"paddingBottom":2,"paddingTop":2}},"children":null}],"linkMap":[]},{"x":1970,"y":930,"rotation":0,"id":75,"uid":"com.gliffy.shape.flowchart.flowchart_v1.default.process","width":150,"height":50,"lockAspectRatio":false,"lockShape":false,"order":52,"graphic":{"type":"Shape","Shape":{"tid":"com.gliffy.stencil.rectangle.basic_v1","strokeWidth":2,"strokeColor":"#333333","fillColor":"#FFFFFF","gradient":false,"dropShadow":false,"state":0,"shadowX":0,"shadowY":0,"opacity":1}},"children":[{"x":3,"y":0,"rotation":0,"id":76,"uid":null,"width":144,"height":28,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Text","Text":{"tid":null,"valign":"middle","overflow":"none","vposition":"none","hposition":"none","html":"replace_connection\n
删除旧连接,使用新连接
","paddingLeft":2,"paddingRight":2,"paddingBottom":2,"paddingTop":2}},"children":null}],"linkMap":[]}],"background":"#FFFFFF","width":2120,"height":1090,"maxWidth":5000,"maxHeight":5000,"nodeIndex":96,"autoFit":true,"exportBorder":false,"gridOn":true,"snapToGrid":true,"drawingGuidesOn":true,"pageBreaksOn":false,"printGridOn":false,"printPaper":"LETTER","printShrinkToFit":false,"printPortrait":true,"shapeStyles":{"com.gliffy.shape.flowchart.flowchart_v1.default":{"fill":"#FFFFFF","stroke":"#333333","strokeWidth":2}},"lineStyles":{"global":{"endArrow":2}},"textStyles":{},"themeData":null}}
\ No newline at end of file
diff --git a/include/emysql.hrl b/include/emysql.hrl
index 1320289f..bd59966f 100644
--- a/include/emysql.hrl
+++ b/include/emysql.hrl
@@ -3,16 +3,16 @@
%% Jacob Vorreuter ,
%% Henning Diedrich ,
%% Eonblast Corporation
-%%
+%%
%% Permission is hereby granted, free of charge, to any person
%% obtaining a copy of this software and associated documentation
%% files (the "Software"),to deal in the Software without restric-
-%% tion, including without limitation the rights to use, copy,
+%% tion, including without limitation the rights to use, copy,
%% modify, merge, publish, distribute, sublicense, and/or sell
%% copies of the Software, and to permit persons to whom the
-%% Software is furnished to do so, subject to the following
+%% Software is furnished to do so, subject to the following
%% conditions:
-%%
+%%
%% The above copyright notice and this permission notice shall be
%% included in all copies or substantial portions of the Software.
%%
@@ -26,31 +26,16 @@
%% OTHER DEALINGS IN THE SOFTWARE.
--record(pool, {pool_id :: atom(),
- size :: number(),
- user :: string(),
- password :: string(),
- host :: string(),
- port :: number(),
- database :: string(),
- encoding :: utf8 | latin1 | {utf8, utf8_unicode_ci} | {utf8, utf8_general_ci},
- available=queue:new() :: queue(),
- locked=gb_trees:empty() :: gb_tree(),
- waiting=queue:new() :: queue(),
- start_cmds=[] :: string(),
- conn_test_period=0 :: number(),
- connect_timeout=infinity :: number() | infinity,
- warnings=false :: boolean()}).
-
-record(emysql_connection, {id :: string(),
pool_id :: atom(),
encoding :: atom(), % maybe could be latin1 | utf8 ?
+ max_allowed_packet :: non_neg_integer(), % max_allowed_packet on bytes.
socket :: inet:socket(),
version :: number(),
thread_id :: number(),
caps :: number(),
- language :: number,
- prepared=gb_trees:empty(),
+ language :: number(),
+ prepared=gb_trees:empty(),
locked_at :: number(),
alive=true :: boolean(),
test_period=0 :: number(),
@@ -58,6 +43,23 @@
monitor_ref :: reference(),
warnings=false :: boolean()}).
+-record(pool, {pool_id :: atom(),
+ size :: number(),
+ user :: string(),
+ password :: string(),
+ host :: string(),
+ port :: number(),
+ database :: string(),
+ encoding :: utf8 | latin1 | {utf8, utf8_unicode_ci} | {utf8, utf8_general_ci},
+ max_allowed_packet :: non_neg_integer(), % max_allowed_packet on bytes.
+ available=queue:new() :: emysql:t_queue(),
+ locked=gb_trees:empty() :: emysql:t_gb_tree(),
+ waiting=queue:new() :: emysql:t_queue(),
+ start_cmds=[] :: string(),
+ conn_test_period=0 :: number(),
+ connect_timeout=infinity :: number() | infinity,
+ warnings=false :: boolean()}).
+
-record(greeting, {protocol_version :: number(),
server_version :: binary(),
thread_id :: number(),
@@ -109,7 +111,7 @@
-record(result_packet, {seq_num :: number(),
field_list :: list(),
- rows, extra}).
+ rows :: any(), extra :: any()}).
-define(TIMEOUT, 8000).
-define(LOCK_TIMEOUT, 5000).
@@ -180,3 +182,12 @@
% number of result set columns.
-define(SERVER_STATUS_METADATA_CHANGED, 1024).
+% https://dev.mysql.com/doc/dev/mysql-server/latest/page_protocol_basic_packets.html
+% Sending More Than 16Mb
+%
+% If the payload is larger than or equal to 224-1 bytes the length is set to 224-1 (ff ff ff) and a additional packets are sent with the rest of the payload until the payload of a packet is less than 224-1 bytes.
+% Sending a payload of 16 777 215 (224-1) bytes looks like:
+%
+% ff ff ff 00 ...
+% 00 00 00 01
+-define(MAX_LENGTH_PAYLOAD, 16#ffffff).
diff --git a/rebar.config b/rebar.config
index e61983a8..72cdf619 100644
--- a/rebar.config
+++ b/rebar.config
@@ -1,9 +1,11 @@
% -*- Erlang -*-
% vim: ts=4 sw=4 et ft=erlang
{erl_opts, [
+ {platform_define, "^([1-9][0-9][0-9].*?)|([2-9][0-9].*?)|(1[8-9])", namespaced_types},
nowarn_deprecated_type
]}.
{pre_hooks,[
+
{"linux|bsd|darwin|solaris", compile, "escript ./support/crypto_compat.escript"},
{"win32", compile, "escript.exe support/crypto_compat.escript"}
]}.
diff --git a/rebar.config.script b/rebar.config.script
new file mode 100644
index 00000000..0917d911
--- /dev/null
+++ b/rebar.config.script
@@ -0,0 +1,14 @@
+{exports, ExportList} = lists:keyfind(exports,1,erlang:module_info()),
+Check = lists:member({timestamp,0},ExportList),
+case Check of
+ true ->
+ case lists:keyfind(erl_opts, 1, CONFIG) of
+ false ->
+ CONFIG ++ [{erl_opts,[{d,timestamp_support}]}];
+ {erl_opts, Opts} ->
+ NewOpts = {erl_opts, Opts ++ [{d,timestamp_support}]},
+ lists:keyreplace(erl_opts, 1, CONFIG, NewOpts)
+ end;
+ false ->
+ CONFIG
+end.
diff --git a/src/emysql.app.src b/src/emysql.app.src
index 1eca61a5..a0d73a6d 100644
--- a/src/emysql.app.src
+++ b/src/emysql.app.src
@@ -4,7 +4,7 @@
{application, emysql, [
{description, "Emysql - Erlang MySQL driver"},
- {vsn, "0.4.1"},
+ {vsn, "0.4.5"},
{modules, []},
{mod, {emysql_app, ["%MAKETIME%"]}},
{registered, [emysql_conn_mgr, emysql_sup]},
diff --git a/src/emysql.erl b/src/emysql.erl
index a373de9a..ace8e355 100644
--- a/src/emysql.erl
+++ b/src/emysql.erl
@@ -105,12 +105,13 @@
add_pool/9,
add_pool/8, remove_pool/1, increment_pool_size/2, decrement_pool_size/2
]).
-
+
%% Interaction API
-%% Used to interact with the database.
+%% Used to interact with the database.
-export([
prepare/2,
execute/2, execute/3, execute/4, execute/5,
+ transaction/2, transaction/3,
default_timeout/0
]).
@@ -136,6 +137,23 @@
% for record and constant defines
-include("emysql.hrl").
+-export_type([
+ t_gb_tree/0,
+ t_queue/0,
+ t_dict/0
+]).
+
+-ifdef(namespaced_types).
+-type t_gb_tree() :: gb_trees:tree().
+-type t_queue() :: queue:queue().
+-type t_dict() :: dict:dict().
+-else.
+-type t_gb_tree() :: gb_tree().
+-type t_queue() :: queue().
+-type t_dict() :: dict().
+-endif.
+
+
%% @spec start() -> ok
%% @doc Start the Emysql application.
%%
@@ -246,8 +264,8 @@ config_ok(#pool{pool_id=PoolId,size=Size,user=User,password=Password,host=Host,p
config_ok(_BadOptions) ->
erlang:error(badarg).
-encoding_ok(Enc) when is_atom(Enc) -> ok;
-encoding_ok({Enc, Coll}) when is_atom(Enc), is_atom(Coll) -> ok;
+encoding_ok(Enc) when is_atom(Enc) -> ok;
+encoding_ok({Enc, Coll}) when is_atom(Enc), is_atom(Coll) -> ok;
encoding_ok(_) -> erlang:error(badarg).
%% Creates a pool record, opens n=Size connections and calls
@@ -267,7 +285,7 @@ add_pool(PoolId, Options) when is_list(Options) ->
Warnings = proplists:get_value(warnings, Options, false),
add_pool(#pool{pool_id=PoolId,size=Size, user=User, password=Password,
host=Host, port=Port, database=Database,
- encoding=Encoding, start_cmds=StartCmds,
+ encoding=Encoding, start_cmds=StartCmds,
connect_timeout=ConnectTimeout, warnings=Warnings}).
add_pool(#pool{pool_id=PoolId,size=Size,user=User,password=Password,host=Host,port=Port,
@@ -275,7 +293,7 @@ add_pool(#pool{pool_id=PoolId,size=Size,user=User,password=Password,host=Host,po
connect_timeout=ConnectTimeout,warnings=Warnings}=PoolSettings)->
config_ok(PoolSettings),
case emysql_conn_mgr:has_pool(PoolId) of
- true ->
+ true ->
{error,pool_already_exists};
false ->
Pool = #pool{
@@ -295,7 +313,13 @@ add_pool(#pool{pool_id=PoolId,size=Size,user=User,password=Password,host=Host,po
{ok, Pool1} -> Pool1;
{error, Reason} -> throw(Reason)
end,
- emysql_conn_mgr:add_pool(Pool2)
+ try
+ emysql_conn_mgr:add_pool(Pool2)
+ catch
+ exit:pool_already_exists ->
+ emysql_conn:close_connections(Pool2),
+ {error, pool_already_exists}
+ end
end.
%% @spec add_pool(PoolId, Size, User, Password, Host, Port, Database, Encoding) -> Result
@@ -328,8 +352,8 @@ add_pool(PoolId, Size, User, Password, Host, Port, Database, Encoding) ->
add_pool(PoolId, Size, User, Password, Host, Port, Database, Encoding, StartCmds) ->
add_pool(PoolId, Size, User, Password, Host, Port, Database, Encoding, StartCmds, infinity).
-add_pool(PoolId, Size, User, Password, Host, Port, Database,
- Encoding, StartCmds, ConnectTimeout)->
+add_pool(PoolId, Size, User, Password, Host, Port, Database,
+ Encoding, StartCmds, ConnectTimeout)->
add_pool(PoolId,[{size,Size},{user,User},{password,Password},
{host,Host},{port,Port},{database,Database},
{encoding,Encoding},{start_cmds,StartCmds},
@@ -631,6 +655,28 @@ execute(PoolId, StmtName, Args, Timeout, nonblocking) when is_atom(StmtName), is
unavailable
end.
+%%@doc transaction
+-spec transaction(PoolId, Fun) -> Result when
+ PoolId :: pid(),
+ Fun :: function(),
+ Result :: {atomic, any()} | {aborted, any()}.
+transaction(PoolId, Fun) when is_function(Fun, 1) ->
+ transaction(PoolId, Fun, default_timeout()).
+
+-spec transaction(PoolId, Fun, Timeout) -> Result when
+ PoolId :: pid(),
+ Fun :: function(),
+ Timeout:: non_neg_integer(),
+ Result :: {atomic, any()} | {aborted, any()}.
+transaction(PoolId, Fun, Timeout) when is_function(Fun, 1) ->
+ case emysql_conn_mgr:lock_connection(PoolId) of
+ Connection when is_record(Connection, emysql_connection) ->
+ monitor_work(Connection, Timeout, {emysql_conn, transaction, [Connection, Fun]});
+ Other ->
+ Other
+ end.
+
+
%% @doc Return the field names of a result packet
%% @end
-spec field_names(Result) -> [Name]
@@ -669,7 +715,7 @@ result_type(#eof_packet{}) -> eof.
-spec as_dict(Result) -> Dict
when
Result :: #result_packet{},
- Dict :: dict().
+ Dict :: t_dict().
as_dict(Res) -> emysql_conv:as_dict(Res).
diff --git a/src/emysql_conn.erl b/src/emysql_conn.erl
index 01a5c74b..fd13f952 100644
--- a/src/emysql_conn.erl
+++ b/src/emysql_conn.erl
@@ -27,7 +27,7 @@
%% @private
-module(emysql_conn).
-export([set_database/2, set_encoding/2,
- execute/3, prepare/3, unprepare/2,
+ execute/3, transaction/2, prepare/3, unprepare/2,
open_connections/1, open_connection/1,
reset_connection/3, close_connection/1,
open_n_connections/2, hstate/1,
@@ -75,7 +75,7 @@ set_database(Connection, Database) ->
set_encoding(_, undefined) -> ok;
set_encoding(Connection, {Encoding, Collation}) ->
- Packet = <>,
emysql_tcp:send_and_recv_packet(Connection#emysql_connection.socket, Packet, 0);
set_encoding(Connection, Encoding) ->
@@ -122,6 +122,52 @@ execute(Connection, StmtName, Args) when is_atom(StmtName), is_list(Args) ->
Error
end.
+
+%%@doc transaction
+-spec transaction(Connection, Fun) -> Result when
+ Connection :: #emysql_connection{},
+ Fun :: function(),
+ Result :: any().
+transaction(Connection, Fun) when is_function(Fun, 1) ->
+ case begin_transaction(Connection) of
+ #ok_packet{} ->
+ try Fun(Connection) of
+ Val ->
+ case commit_transaction(Connection) of
+ #ok_packet{} ->
+ {atomic, Val};
+ #error_packet{} = ErrorPacket ->
+ {aborted, {commit_error, ErrorPacket}}
+ end
+ catch
+ _What:Exception ->
+ rollback_transaction(Connection),
+ case Exception of
+ {aborted, Reason} ->
+ {aborted, Reason};
+ _ ->
+ exit(Exception)
+ end
+ end;
+ #error_packet{} = ErrorPacket ->
+ {aborted, {begin_error, ErrorPacket}}
+ end.
+
+%% 事务处理的三个部分
+begin_transaction(Connection) ->
+ Packet = <>,
+ emysql_tcp:send_and_recv_packet(Connection#emysql_connection.socket, Packet, 0).
+
+rollback_transaction(Connection) ->
+ Packet = <>,
+ emysql_tcp:send_and_recv_packet(Connection#emysql_connection.socket, Packet, 0).
+
+commit_transaction(Connection) ->
+ Packet = <>,
+ emysql_tcp:send_and_recv_packet(Connection#emysql_connection.socket, Packet, 0).
+
+
+
prepare(Connection, Name, Statement) when is_atom(Name) ->
prepare(Connection, atom_to_list(Name), Statement);
prepare(Connection, Name, Statement) ->
@@ -260,7 +306,7 @@ run_startcmds_or_die(#emysql_connection{socket=Socket}, StartCmds) ->
end,
StartCmds
).
-
+
set_encoding_or_die(#emysql_connection { socket = Socket } = Connection, Encoding) ->
case set_encoding(Connection, Encoding) of
ok -> ok;
@@ -269,7 +315,7 @@ set_encoding_or_die(#emysql_connection { socket = Socket } = Connection, Encodin
gen_tcp:close(Socket),
exit({failed_to_set_encoding, Err2#error_packet.msg})
end.
-
+
reset_connection(Pools, Conn, StayLocked) ->
%% if a process dies or times out while doing work
%% the socket must be closed and the connection reset
@@ -320,7 +366,7 @@ test_connection(Conn, StayLocked) ->
exit({connection_down, {and_conn_reset_failed, FailedReset}})
end;
_ ->
- NewConn = Conn#emysql_connection{last_test_time = now_seconds()},
+ NewConn = Conn#emysql_connection{last_test_time = now_seconds() },
case StayLocked of
pass -> emysql_conn_mgr:replace_connection_as_available(Conn, NewConn);
keep -> emysql_conn_mgr:replace_connection_as_locked(Conn, NewConn)
@@ -333,9 +379,13 @@ need_test_connection(Conn) ->
(Conn#emysql_connection.last_test_time =:= 0) orelse
(Conn#emysql_connection.last_test_time + Conn#emysql_connection.test_period < now_seconds()).
+-ifdef(timestamp_support).
+now_seconds() -> os:system_time(1).
+-else.
now_seconds() ->
- {M, S, _} = erlang:now(),
+ {M, S, _} = os:timestamp(),
M * 1000000 + S.
+-endif.
%%--------------------------------------------------------------------
%%% Internal functions
@@ -365,7 +415,7 @@ set_params_packet(NumStart, Values) ->
BinValues = [encode(Val, binary) || Val <- Values],
BinNums = [encode(Num, binary) || Num <- lists:seq(NumStart, NumStart + length(Values) - 1)],
BinPairs = lists:zip(BinNums, BinValues),
- Parts = [<<"@", NumBin/binary, "=", ValBin/binary>> || {NumBin, ValBin} <- BinPairs],
+ Parts = [<<"@", NumBin/binary, "=", ValBin/binary>> || {NumBin, ValBin} <- BinPairs],
Sets = list_to_binary(join(Parts, <<",">>)),
<>.
@@ -449,7 +499,7 @@ encode({_Time1, _Time2, _Time3}=Val, binary) ->
list_to_binary(encode(Val, list));
encode(Val, _) ->
{error, {unrecognized_value, Val}}.
-
+
%% @private
two_digits(Nums) when is_list(Nums) ->
[two_digits(Num) || Num <- Nums];
diff --git a/src/emysql_conn_mgr.erl b/src/emysql_conn_mgr.erl
index b14a08d6..75fc1ce4 100644
--- a/src/emysql_conn_mgr.erl
+++ b/src/emysql_conn_mgr.erl
@@ -40,7 +40,7 @@
-include("emysql.hrl").
--record(state, {pools, lockers = dict:new() :: dict()}).
+-record(state, {pools, lockers = dict:new() :: dict:dict(reference(), term())}).
%%====================================================================
%% API
@@ -419,8 +419,8 @@ lock_next_connection(Available ,Locked, Who) ->
end.
connection_locked_at(Conn, MonitorRef) ->
- Conn#emysql_connection{locked_at=lists:nth(2, tuple_to_list(now())),
- monitor_ref = MonitorRef}.
+ {_,LockedAt,_} = emysql_util:timestamp(),
+ Conn#emysql_connection{locked_at=LockedAt, monitor_ref = MonitorRef}.
serve_waiting_pids(Pool) ->
{Waiting, Available, Locked, NewRefs} = serve_waiting_pids(Pool#pool.waiting, Pool#pool.available, Pool#pool.locked, []),
diff --git a/src/emysql_tcp.erl b/src/emysql_tcp.erl
index d19b49b9..009bf62e 100644
--- a/src/emysql_tcp.erl
+++ b/src/emysql_tcp.erl
@@ -35,14 +35,18 @@
-spec send_and_recv_packet(port(), iodata(), integer()) -> packet_result() | [packet_result()].
send_and_recv_packet(Sock, Packet, SeqNum) ->
- case gen_tcp:send(Sock, [<<(size(Packet)):24/little, SeqNum:8>>, Packet]) of
- ok -> ok;
- {error, closed} ->
- %% If we can't communicate on the socket since it has been closed, we exit the process
- %% at this point. The exit reason is caught by `emysql:monitor_work/3` and since it is
- %% with the atom `conn_tcp_closed` we special-case that and rehandle it properly
- exit(tcp_connection_closed)
- end,
+ Packets = packet_for_send(size(Packet), SeqNum, Packet),
+ lists:foldl(
+ fun(PacketT, _) ->
+ case gen_tcp:send(Sock, PacketT) of
+ ok -> ok;
+ {error, closed} ->
+ %% If we can't communicate on the socket since it has been closed, we exit the process
+ %% at this point. The exit reason is caught by `emysql:monitor_work/3` and since it is
+ %% with the atom `conn_tcp_closed` we special-case that and rehandle it properly
+ exit(tcp_connection_closed)
+ end
+ end, ok, Packets),
DefaultTimeout = emysql_app:default_timeout(),
case response_list(Sock, DefaultTimeout, ?SERVER_MORE_RESULTS_EXIST) of
% This is a bit murky. It's compatible with former Emysql versions
@@ -52,6 +56,37 @@ send_and_recv_packet(Sock, Packet, SeqNum) ->
List -> List
end.
+packet_for_send(Size, SeqNum, Packet) ->
+ Packets = packet_for_send(Size, SeqNum, Packet, []),
+ lists:reverse(Packets).
+
+%% smaller than 16m, just one package.
+packet_for_send(Size, SeqNum, Packet, []) when Size < ?MAX_LENGTH_PAYLOAD ->
+ [[<<(size(Packet)):24/little, SeqNum:8>>, Packet]];
+%% greater than 16m, more than one package.
+% last package.
+packet_for_send(Size, _SeqNum, Packet, Packets) when Size < ?MAX_LENGTH_PAYLOAD ->
+ [[Packet] | Packets];
+% first package.
+packet_for_send(Size, SeqNum, Packet, []) when Size >= ?MAX_LENGTH_PAYLOAD ->
+ <> = Packet,
+ {NextSize, NextSeqNum, AdditionalPackets} = additional_packets(Size, SeqNum),
+ Package = [<>, PacketNow, AdditionalPackets],
+ packet_for_send(NextSize, NextSeqNum, PackageRest, [Package]);
+
+packet_for_send(Size, SeqNum, Packet, Packets) when Size >= ?MAX_LENGTH_PAYLOAD ->
+ <> = Packet,
+ {NextSize, NextSeqNum, AdditionalPackets} = additional_packets(Size, SeqNum),
+ Package = [PacketNow, AdditionalPackets],
+ packet_for_send(NextSize, NextSeqNum, PackageRest, [Package | Packets]).
+
+additional_packets(Size, SeqNum) when Size < ?MAX_LENGTH_PAYLOAD ->
+ {0, SeqNum, <<>>};
+additional_packets(Size, SeqNum) when Size >= ?MAX_LENGTH_PAYLOAD ->
+ Size1 = Size - ?MAX_LENGTH_PAYLOAD,
+ Size2 = Size1 band ?MAX_LENGTH_PAYLOAD,
+ {Size1, SeqNum + 1, <>}.
+
response_list(Sock, DefaultTimeout, ServerStatus) ->
response_list(Sock, DefaultTimeout, ServerStatus, <<>>).
diff --git a/src/emysql_util.erl b/src/emysql_util.erl
index 71848cd9..738be0ed 100644
--- a/src/emysql_util.erl
+++ b/src/emysql_util.erl
@@ -44,6 +44,11 @@
as_record/4
]).
+%% Erlang version-specific functions
+-export([
+ timestamp/0
+]).
+
affected_rows(P) -> emysql:affected_rows(P).
field_names(R) -> emysql:field_names(R).
insert_id(P) -> emysql:insert_id(P).
@@ -55,3 +60,8 @@ as_proplist(Res) -> emysql:as_proplist(Res).
as_record(Res, RecName, Fields) -> emysql:as_record(Res, RecName, Fields).
as_record(Res, RecName, Fields, Fun) -> emysql:as_record(Res, RecName, Fields, Fun).
+-ifdef(timestamp_support).
+timestamp() -> os:timestamp().
+-else.
+timestamp() -> erlang:now().
+-endif.
diff --git a/support/include.mk b/support/include.mk
index eb826c5a..b6bab0a0 100644
--- a/support/include.mk
+++ b/support/include.mk
@@ -15,6 +15,19 @@ ifdef debug
ERLC_FLAGS += -Ddebug
endif
+## Check if we are on erlang version that has namespaced types
+ERL_NT := $(shell escript ../support/ntype_check.escript)
+## Check if we are on erlang version that has erlang:timestamp/0
+ERL_TS := $(shell escript ../support/timestamp_check.escript)
+
+ifeq ($(ERL_NT),true)
+ ERLC_FLAGS += -Dnamespaced_types
+endif
+
+ifeq ($(ERL_TS),true)
+ ERLC_FLAGS += -Dtimestamp_support
+endif
+
EBIN_DIR := ../ebin
DOC_DIR := ../doc
EMULATOR := beam
@@ -30,10 +43,9 @@ EBIN_FILES = $(ERL_OBJECTS) $(APP_FILES:%.app=../ebin/%.app) $(ERL_TEMPLATES)
$(EBIN_DIR)/%.$(EMULATOR): %.erl $(ERL_HEADERS)
$(ERLC) $(ERLC_FLAGS) -o $(EBIN_DIR) $<
-./%.$(EMULATOR): %.erl
+./%.$(EMULATOR): %.erl
$(ERLC) $(ERLC_FLAGS) -o . $<
$(DOC_DIR)/%.html: %.erl
$(ERL) -noshell -run edoc file $< -run init stop
mv *.html $(DOC_DIR)
-
diff --git a/support/ntype_check.escript b/support/ntype_check.escript
new file mode 100644
index 00000000..eda46d96
--- /dev/null
+++ b/support/ntype_check.escript
@@ -0,0 +1,14 @@
+#!/usr/bin/env escript
+%% vim: ts=4 sw=4 et ft=erlang
+
+%% The purpose of this script is to check if we need namespaced types for
+%% successful compilation.
+
+main([]) ->
+ Check = case erlang:system_info(otp_release) of
+ [X|_] when X >= 48 andalso X =< 57 ->
+ true;
+ _ ->
+ false
+ end,
+ io:format("~s",[Check]).
diff --git a/support/timestamp_check.escript b/support/timestamp_check.escript
new file mode 100644
index 00000000..5c24454a
--- /dev/null
+++ b/support/timestamp_check.escript
@@ -0,0 +1,10 @@
+#!/usr/bin/env escript
+%% vim: ts=4 sw=4 et ft=erlang
+
+%% The purpose of this script is to check if we need namespaced types for
+%% successful compilation.
+
+main([]) ->
+ {exports, ExportList} = lists:keyfind(exports,1,erlang:module_info()),
+ Check = lists:member({timestamp,0},ExportList),
+ io:format("~s",[Check]).