├── .gitignore ├── .npmignore ├── .travis.yml ├── AUTHORS ├── CHANGELOG.markdown ├── DEVELOPMENT.markdown ├── LICENSE ├── Makefile ├── README.markdown ├── binding.gyp ├── doc ├── api │ └── index.html ├── changelog.html ├── examples │ ├── examples.js │ └── url_shortener │ │ ├── index.html │ │ └── index.js └── index.html ├── gh_pages.sh ├── lib └── mysql-libmysqlclient.js ├── nodelint.conf ├── package.json ├── src ├── mysql_bindings.cc ├── mysql_bindings.h ├── mysql_bindings_connection.cc ├── mysql_bindings_connection.h ├── mysql_bindings_result.cc ├── mysql_bindings_result.h ├── mysql_bindings_statement.cc └── mysql_bindings_statement.h ├── tests ├── complex │ ├── setup-complex.js │ ├── test-binary-buffers.js │ ├── test-call-stored-procedure.js │ ├── test-datatypes-cast.js │ └── test-fetch-options.js ├── config.js ├── high-level │ ├── test-class-mysqlconnectionhighlevel.js │ ├── test-class-mysqlconnectionqueued.js │ ├── test-createconnection-highlevel.js │ └── test-createconnection-queued.js ├── ignored │ └── place_ignored_tests.here ├── issues │ ├── test-issue-102.js │ ├── test-issue-106.js │ ├── test-issue-110.js │ ├── test-issue-157.js │ └── test-issue-83.js ├── load-data-infile │ ├── complex-load-infile.js │ └── simle-load-infile.js ├── low-level-async │ ├── setup-low-level-async.js │ ├── test-class-mysqlconnection-async.js │ ├── test-class-mysqlresult-async.js │ └── test-createconnection-async.js ├── low-level-sync │ ├── setup-low-level-sync.js │ ├── test-class-mysqlconnection-sync.js │ ├── test-class-mysqlresult-sync.js │ ├── test-class-mysqlstatement-sync.js │ ├── test-connect-different-args.js │ └── test-createconnection-sync.js ├── slow │ ├── test-connect.js │ ├── test-fetchAll.js │ ├── test-query.js │ └── test-querySend.js └── ssl-fixtures │ ├── ca-cert.pem │ ├── ca-key.pem │ ├── client-cert.pem │ ├── client-key.pem │ ├── server-cert.pem │ └── server-key.pem └── tools ├── check-all-classes-methods-tests-exists.js ├── inspect-exported-classes-and-functions.js ├── memory-helper.js ├── memory-leaks-finder-repl.js ├── memory-usage-profile.gle └── memory-usage-profile.js /.gitignore: -------------------------------------------------------------------------------- 1 | # Needed for npm :-( 2 | .idea 3 | npm-debug.log 4 | 5 | *~ 6 | build 7 | mysql_bindings.node 8 | node_modules 9 | 10 | npm-install-stamp 11 | devdependencies-stamp 12 | webkit-devtools-agent-stamp 13 | 14 | *.gcda 15 | *.gcno 16 | *.gcov 17 | 18 | valgrind.log 19 | *.dat 20 | *.png 21 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | tests 2 | doc 3 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - 0.8 # previous stable release 4 | - 0.10 # latest stable release 5 | - 0.11 # latest development release 6 | 7 | # This causes `Job is already running: mysql` 8 | #services: 9 | # - mysql # start MySQL on startup 10 | 11 | before_script: 12 | - "mysql -uroot -e \"DELETE FROM mysql.db WHERE Db = 'test\\_%';\"" 13 | - "mysql -uroot -e \"DELETE FROM mysql.user WHERE Host = 'localhost' AND User = '';\"" 14 | - "mysql -uroot -e \"FLUSH PRIVILEGES;\"" 15 | - "mysql -uroot -e \"CREATE DATABASE IF NOT EXISTS test_allowed DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci;\"" 16 | - "mysql -uroot -e \"GRANT ALL PRIVILEGES ON test_allowed.* TO 'test_user'@'localhost' IDENTIFIED BY '1234';\"" 17 | - "mysql -uroot -e \"CREATE DATABASE IF NOT EXISTS test_denied DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci;\"" 18 | # Some extras for Travis-CI only 19 | - "mysql -uroot -e \"DELETE FROM mysql.user WHERE User = 'travis';\"" 20 | - "mysql -uroot -e \"FLUSH PRIVILEGES;\"" 21 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | # Authors ordered by first contribution. 2 | 3 | Oleg Efimov 4 | Surendra Singhi 5 | Akzhan Abdulin 6 | Pavel Ponomarenko 7 | Robin Duckett 8 | Roman Shtylman 9 | Dan Beam 10 | Maurits Lamers 11 | Benjmain Reesman 12 | Krists Krīgers 13 | Sergey Novgorodsky 14 | Ștefan Rusu 15 | Zhiqiang Zhao 16 | Zhao Cheng 17 | Zhao Lei 18 | Alexander Makarenko 19 | Fionn Kelleher 20 | Farrin Reid 21 | -------------------------------------------------------------------------------- /DEVELOPMENT.markdown: -------------------------------------------------------------------------------- 1 | Node-mysql-libmysqlclient development 2 | ===================================== 3 | 4 | 5 | Build and use 6 | ------------- 7 | 8 | To get source code: 9 | 10 | $> git clone git://github.com/Sannis/node-mysql-libmysqlclient.git 11 | $> cd node-mysql-libmysqlclient 12 | 13 | If you want to build specific version of node-mysql-libmysqlclient, checkout it: 14 | 15 | $> git checkout v1.3.0 16 | 17 | To build the binding using `node-waf` you should run: 18 | 19 | $> make waf 20 | 21 | To build the binding using `node-gyp` you should run: 22 | 23 | $> make gyp 24 | 25 | To cleanup: 26 | 27 | $> make clean 28 | 29 | To run tests: 30 | 31 | $> make test 32 | 33 | To lint code: 34 | 35 | $> # install cpplint.py 36 | $> make lint 37 | 38 | The two files required to use these bindings are ./mysql-libmysqlclient.js and 39 | ./mysql\_bindings.node (build/default/mysql\_bindings.node). 40 | Put module directory in your NODE_PATH or copy those two files where you need them. 41 | 42 | 43 | Testing 44 | ------- 45 | 46 | All functions and possible use cases should have tests, places in one of `tests` sub-folders. 47 | Also `tests/issues` contains tests for some reportes issues and used for regression testing. 48 | `node-mysql-libmysqlclient` uses `nodeunit` as testing tool. If you contributing something, 49 | you should check that your changes do not breakes tests. 50 | 51 | If you chnage small part of code you can test it using: 52 | 53 | $> make test 54 | 55 | But after all you should run all tests for `node-mysql-libmysqlclient` code by executing: 56 | 57 | $> make test-all 58 | 59 | All branches build status: ![Build status](https://secure.travis-ci.org/Sannis/node-mysql-libmysqlclient.png). 60 | `Master` branch build status: ![Build status](https://secure.travis-ci.org/Sannis/node-mysql-libmysqlclient.png?branch=master). 61 | [Go to Travis CI site to view tests results](http://travis-ci.org/Sannis/node-mysql-libmysqlclient). 62 | 63 | 64 | Coding style 65 | ------------ 66 | 67 | Code style based on [Node.js code styles](http://github.com/ry/node/wiki/contributing). 68 | 69 | 1. Discuss large changes before coding (this is good idea in collaborative development) 70 | 2. Javascript code should follow [Douglas Crockford code conventions for the javascript programming language](http://javascript.crockford.com/code.html) and be run through [Nodelint](http://github.com/tav/nodelint). And: 71 | * Code should has two space indention 72 | * Multi-line if statements must have braces 73 | 3. C++ code should follow [Google's C++ style guide](http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml) and be run through [cpplint.py](http://google-styleguide.googlecode.com/svn/trunk/cpplint/cpplint.py). And: 74 | * Max line length is 120 symbols 75 | 4. All code must be MIT licensed 76 | 77 | If you have `cpplint.py` in `$PATH`, you can lint `node-mysql-libmysqlclient` code by executing: 78 | 79 | $> make lint 80 | 81 | 82 | Contributing 83 | ------------ 84 | 85 | I will be happy to hear tips from the more experienced programmers. 86 | If you are interested in wide MySQL usage in Node.JS applications, 87 | leave your comments to the code. 88 | I'll be glad to see your forks and commits in them :) 89 | 90 | You can [email patches to me](mailto:efimovov@gmail.com) 91 | or simply fork this repository using GitHub and send 92 | a pull request to [me](https://github.com/Sannis). 93 | 94 | Thanks! 95 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | ----------- 3 | 4 | Copyright (C) 2010 Oleg "Sannis" Efimov 5 | and other node-mysql-libmysqlclient contributors. 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in 15 | all copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | THE SOFTWARE. 24 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | CURR_HEAD_SHA := $(firstword $(shell git show-ref --hash HEAD | cut -b -6) master) 4 | GITHUB_PROJECT_NAME := Sannis/node-mysql-libmysqlclient 5 | GITHUB_PROJECT_URL := https://github.com/${GITHUB_PROJECT_NAME} 6 | API_SRC_URL_FMT := https://github.com/${GITHUB_PROJECT_NAME}/blob/${CURR_HEAD_SHA}/{file}\#L{line} 7 | API_DEST_DIR := ./doc/api 8 | 9 | MLF=./tools/run-memoryleaks-finder.js 10 | NI=./node_modules/.bin/node-inspector 11 | NI_DEBUG_PORT=5858 12 | NI_WEB_PORT=8888 13 | WEB_BROWSER=google-chrome 14 | 15 | all: npm-install 16 | 17 | npm-install: npm-install-stamp 18 | 19 | npm-install-stamp: ./binding.gyp ./src/* 20 | npm install 21 | touch npm-install-stamp 22 | 23 | clean: 24 | rm -rf ./build 25 | rm -f ./mysql_bindings.node 26 | rm -f npm-install-stamp 27 | rm -f webkit-devtools-agent-stamp 28 | 29 | clean-all: clean 30 | rm -rf ./node_modules 31 | 32 | test: npm-install 33 | ./node_modules/.bin/nodeunit --reporter=minimal tests/low-level-sync tests/low-level-async \ 34 | tests/high-level tests/complex tests/issues \ 35 | tests/load-data-infile 36 | 37 | test-slow: npm-install 38 | ./node_modules/.bin/nodeunit --reporter=minimal tests/slow 39 | 40 | test-all: npm-install 41 | ./node_modules/.bin/nodeunit --reporter=minimal tests/low-level-sync tests/low-level-async \ 42 | tests/high-level tests/complex tests/issues \ 43 | tests/slow tests/load-data-infile 44 | 45 | test-profile: npm-install 46 | rm -f v8.log 47 | /usr/bin/env node --prof ./node_modules/.bin/nodeunit tests/low-level-sync tests/low-level-async \ 48 | tests/high-level tests/complex tests/issues 49 | /usr/bin/env linux-tick-processor v8.log > v8.processed.log 50 | 51 | lint: npm-install 52 | cpplint ./src/*.h ./src/*.cc 53 | ./node_modules/.bin/nodelint --config ./nodelint.conf ./package.json ./lib ./tools/*.js 54 | ./node_modules/.bin/nodelint --config ./nodelint.conf ./tests 55 | 56 | webkit-devtools-agent: webkit-devtools-agent-stamp 57 | 58 | webkit-devtools-agent-stamp: 59 | npm install webkit-devtools-agent@0.0.4 60 | touch webkit-devtools-agent-stamp 61 | 62 | mlf: npm-install webkit-devtools-agent 63 | ./tools/memory-leaks-finder-repl.js 64 | 65 | valgrind: npm-install webkit-devtools-agent $(shell time) 66 | valgrind \ 67 | --leak-check=full --error-limit=no \ 68 | --track-origins=yes -v \ 69 | --log-file=valgrind.log -- \ 70 | node --expose-gc ./tools/memory-usage-show.js 71 | 72 | doc: ./lib/* ./src/* 73 | rm -rf ${API_DEST_DIR} 74 | ./node_modules/.bin/ndoc \ 75 | --gh-ribbon ${GITHUB_PROJECT_URL} \ 76 | --link-format ${API_SRC_URL_FMT} \ 77 | --output ${API_DEST_DIR} \ 78 | --alias cc:js \ 79 | --alias h:js \ 80 | ./lib/*.js ./src/*.cc ./src/*.h 81 | 82 | gh-pages: 83 | ./gh_pages.sh 84 | 85 | .PHONY: all npm-install clean clean-all test test-slow test-all test-profile lint mlf doc 86 | -------------------------------------------------------------------------------- /README.markdown: -------------------------------------------------------------------------------- 1 | Node-mysql-libmysqlclient [![Build status][Build status image]][Build status URL] 2 | ================================================================================= 3 | 4 | **Asynchronous MySQL binding for [Node.js] using libmysqlclient.** 5 | 6 | **This module has been tested with Node.js versions 0.8.26, v0.10.25 and 0.11.10** 7 | 8 | [Node.js]: http://nodejs.org/ 9 | [Build status image]: https://secure.travis-ci.org/Sannis/node-mysql-libmysqlclient.png?branch=master 10 | [Build status URL]: http://travis-ci.org/Sannis/node-mysql-libmysqlclient 11 | 12 | 13 | Overview 14 | -------- 15 | 16 | These bindings provides all general connection/querying functions from the MySQL C API, 17 | and partial support for prepared statements. `Connect`, `query` and `fetchAll` are asynchronous. 18 | This module also includes support for asynchronous `querySend` from internals of `libmysqlclient`. 19 | 20 | I started this project in 2010 when Node.js was growing. Ryan had plans to write this binding as part of [GSoC]. 21 | It is now used by many projects and has more than 10 contributors, 22 | who are listed in the [AUTHORS](https://github.com/Sannis/node-mysql-libmysqlclient/blob/master/AUTHORS) file. 23 | I also maintain the [Node.js MySQL bindings benchmark] which shows how mysql-libmysqlclient performs. 24 | 25 | Node-mysql-libmysqlclient's source code is available in the [Github repo] and you can report issues at the project tracker. 26 | Visit the [module site] for API docs and examples. You can also read some extra information in [wiki]. 27 | 28 | [GSoC]: http://code.google.com/soc/ 29 | [Node.js MySQL bindings benchmark]: https://github.com/Sannis/node-mysql-benchmarks 30 | [GitHub repo]: https://github.com/Sannis/node-mysql-libmysqlclient 31 | [module site]: http://sannis.github.com/node-mysql-libmysqlclient 32 | [wiki]: https://github.com/Sannis/node-mysql-libmysqlclient/wiki 33 | 34 | 35 | Dependencies 36 | ------------ 37 | 38 | To build this module you must install the libmysqlclient library and the development files for it. 39 | `mysql_config` is used to determine the paths to the library and header files. 40 | To install these dependencies, execute the commands below for the OS you're running. 41 | 42 | For CentOS: 43 | 44 | #> yum install mysql-devel 45 | 46 | For openSUSE: 47 | 48 | #> zypper install libmysqlclient-devel 49 | 50 | For Debian-based systems/Ubuntu: 51 | 52 | #> apt-get install libmysqlclient-dev 53 | 54 | Alternatively, you can use `aptitude` for Debian-based systems. 55 | 56 | Please refer to your system's documentation for more information and feel free to send me a patch for this readme. 57 | 58 | 59 | Installation 60 | ------------ 61 | 62 | You can install this module via NPM: 63 | 64 | $> npm install mysql-libmysqlclient 65 | 66 | You can also build latest source code from repository. 67 | Please refer to the developers documentation for more information. 68 | 69 | 70 | Contributing 71 | ------------ 72 | 73 | This module is written in collaboration with many peoples listed on [GitHub contributors page]. 74 | List of [authors ordered by first contribution] also available. 75 | 76 | If you are interested in wide MySQL usage in Node.JS applications, 77 | leave your comments to the code. 78 | To contribute any patches, simply fork this repository using GitHub 79 | and send a pull request to [me](https://github.com/Sannis). Thanks! 80 | 81 | All information about development use and contribution is placed in the [DEVELOPMENT] file. 82 | 83 | [GitHub contributors page]: https://github.com/Sannis/node-mysql-libmysqlclient/graphs/contributors 84 | [authors ordered by first contribution]: https://github.com/Sannis/node-mysql-libmysqlclient/blob/master/AUTHORS 85 | [DEVELOPMENT]: https://github.com/Sannis/node-mysql-libmysqlclient/blob/master/DEVELOPMENT.markdown 86 | 87 | 88 | Users and related projects 89 | -------------------------- 90 | 91 | This module is used by [Taobao](http://taobao.com) guys 92 | for their distributed MySQL proxy [Myfox-query](https://github.com/vincent-zhao/Myfox-query-module) module. 93 | There is long time developed Node.js ORM library called [noblerecord](https://github.com/noblesamurai/noblerecord). 94 | It is inspired by Rails and widely used by Noblesamurai. 95 | If you are looking for lightweight Node.js ORM on top of this module, 96 | try [mapper](https://github.com/mgutz/mapper) by Mario Gutierrez. 97 | 98 | 99 | License 100 | ------- 101 | 102 | Node-mysql-libmysqlclient itself is published under MIT license. 103 | See license text in [LICENSE](https://github.com/Sannis/node-mysql-libmysqlclient/blob/master/LICENSE) file. 104 | -------------------------------------------------------------------------------- /binding.gyp: -------------------------------------------------------------------------------- 1 | { 2 | 'targets': [ 3 | { 4 | # have to specify 'liblib' here since gyp will remove the first one :\ 5 | 'target_name': 'mysql_bindings', 6 | 'sources': [ 7 | 'src/mysql_bindings.cc', 8 | 'src/mysql_bindings_connection.cc', 9 | 'src/mysql_bindings_result.cc', 10 | 'src/mysql_bindings_statement.cc', 11 | ], 12 | "include_dirs" : [ 13 | ' 2 | 3 | 4 | 5 | Node.js + node-mysql-libmysqlclient URL shortener 6 | 7 | 42 | 43 | 44 |
45 | 46 | 47 |
48 |
49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /doc/examples/url_shortener/index.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Copyright by Oleg Efimov and node-mysql-libmysqlclient contributors 3 | * See contributors list in README 4 | * 5 | * See license text in LICENSE file 6 | */ 7 | 8 | /** 9 | * Database schema 10 | * 11 | * CREATE TABLE `shortLinks` ( 12 | * `id` int(11) NOT NULL AUTO_INCREMENT, 13 | * `url` varchar(512) NOT NULL, 14 | * PRIMARY KEY (`id`) 15 | * ) DEFAULT CHARSET=utf8; 16 | */ 17 | 18 | /*jslint onevar: false */ 19 | 20 | /** 21 | * Require Node modules 22 | */ 23 | var http = require('http'); 24 | var url = require('url'); 25 | var fs = require('fs'); 26 | 27 | /** 28 | * Create connection 29 | */ 30 | var conn = require('../../../mysql-libmysqlclient').createConnectionSync(); 31 | conn.connectSync('localhost', 'test', '', 'test'); 32 | 33 | /** 34 | * Define class for shortened links 35 | */ 36 | function Link(obj) { 37 | this.setId = function (id) { 38 | this.id = (isNaN(id) || id <= 0) ? null : parseInt(id, 10); 39 | return this; 40 | }; 41 | 42 | this.getId = function () { 43 | return this.id; 44 | }; 45 | 46 | this.setUrl = function (url) { 47 | this.url = url || null; 48 | return this; 49 | }; 50 | 51 | this.getUrl = function () { 52 | return this.url; 53 | }; 54 | 55 | this.setCode = function (code) { 56 | this.id = code ? parseInt(code, 36) : null; 57 | return this; 58 | }; 59 | 60 | this.getCode = function () { 61 | return this.id ? this.id.toString(36) : null; 62 | }; 63 | 64 | this.setId(obj.id).id || this.setCode(obj.code); 65 | this.setUrl(obj.url); 66 | } 67 | 68 | /** 69 | * Define model for operate with links 70 | */ 71 | function Model(conn) { 72 | this.create = function (args) { 73 | return new Link(args); 74 | }; 75 | 76 | /** 77 | * Get link info from database 78 | */ 79 | this.get = function (link, fn) { 80 | if (!link.getId()) { 81 | throw 'EmptyId'; 82 | } 83 | 84 | var q = 'SELECT * FROM shortLinks WHERE id = ' + link.getId(); 85 | 86 | this.conn.query(q, function (err, res) { 87 | if (err) { 88 | throw err; 89 | } 90 | 91 | res.fetchAll(function (err, rows) { 92 | if (err) { 93 | throw err; 94 | } 95 | 96 | res.freeSync(); 97 | 98 | fn(rows.length ? link.setUrl(rows[0].url) : null); 99 | }); 100 | }); 101 | }; 102 | 103 | /** 104 | * Put link info to database 105 | */ 106 | this.put = function (link, fn) { 107 | var q = 'INSERT INTO shortLinks (id, url) ' + 108 | 'VALUES (NULL, "' + this.conn.escapeSync(link.getUrl()) + '");'; 109 | 110 | this.conn.query(q, function (err, res) { 111 | if (err) { 112 | throw err; 113 | } 114 | 115 | fn(link.setId( 116 | this.conn.lastInsertIdSync() 117 | )); 118 | }.bind(this)); 119 | }; 120 | 121 | this.conn = conn; 122 | } 123 | 124 | /** 125 | * Create model instance and define renderer 126 | */ 127 | var linkModel = new Model(conn); 128 | 129 | var Renderer = {}; 130 | 131 | /** 132 | * Function for handle incoming HTTP requests 133 | */ 134 | Renderer.run = function (req, res) { 135 | var path = url.parse(req.url, true); 136 | if (path.query && ('add' in path.query)) { 137 | var addUrl = path.query.add; 138 | if (!url.parse(addUrl).protocol) { 139 | addUrl = 'http://' + addUrl; 140 | } 141 | this.add(res, addUrl); 142 | } else if (path.pathname.search(/^\/![0-9a-z]+$/) !== -1) { 143 | this.send(res, path.pathname.substr(2)); 144 | } else { 145 | this.index(res); 146 | } 147 | }; 148 | 149 | /** 150 | * 'Add' controller 151 | */ 152 | Renderer.add = function (res, url) { 153 | res.header(200); 154 | this.link.put( 155 | this.link.create({url: url}), 156 | function (link) { 157 | res.end(link.getCode()); 158 | } 159 | ); 160 | }; 161 | 162 | /** 163 | * 'Send' controller 164 | */ 165 | Renderer.send = function (res, code) { 166 | this.link.get( 167 | this.link.create({code: code}), 168 | function (link) { 169 | if (link) { 170 | res.redirect(link.getUrl()); 171 | } else { 172 | res.header(404, true); 173 | res.end('There is not such URL'); 174 | } 175 | } 176 | ); 177 | }; 178 | 179 | /** 180 | * 'Index' controller 181 | */ 182 | Renderer.index = function (res) { 183 | fs.readFile(__dirname + '/index.html', function (err, data) { 184 | if (err) { 185 | throw err; 186 | } 187 | 188 | res.header(200); 189 | res.end(data); 190 | }); 191 | }; 192 | 193 | /** 194 | * @ignore 195 | */ 196 | Renderer.link = linkModel; 197 | 198 | /** 199 | * Expand some node classes 200 | */ 201 | http.ServerResponse.prototype.header = function (code, plain) { 202 | this.writeHead(code, { 203 | 'Content-Type': plain ? 'text/plain' : 'text/html' 204 | }); 205 | }; 206 | 207 | http.ServerResponse.prototype.redirect = function (url, status) { 208 | this.writeHead(status || 302, { 209 | 'Content-Type' : 'text/plain', 210 | 'Location' : url 211 | }); 212 | this.write('Redirecting to ' + url); 213 | this.end(); 214 | }; 215 | 216 | /** 217 | * Run server 218 | */ 219 | http.createServer(function (req, res) { 220 | Renderer.run(req, res); 221 | }).listen(12700, "localhost"); 222 | console.log('Server running at http://localhost:12700/'); 223 | 224 | -------------------------------------------------------------------------------- /gh_pages.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | BRANCH=`git branch 2> /dev/null | grep "*" | sed 's#*\ \(.*\)#\1#'` 4 | if [ "$BRANCH" != "master" ] 5 | then 6 | exit 1 7 | fi 8 | 9 | DESC=`git describe --tags` 10 | 11 | # Update gh-pages branch 12 | TMP=`mktemp -d ${TMPDIR}temp.XXXXXXXXXX` 13 | cp -r ./doc/* $TMP 14 | rm -f $TMP/*~ 15 | git checkout gh-pages 16 | git reset --hard 17 | git clean -df 18 | cp -r $TMP/* ./ 19 | git add . 20 | git ci -m "Update docs to $DESC" 21 | git checkout master 22 | rm -rf $TMP 23 | -------------------------------------------------------------------------------- /nodelint.conf: -------------------------------------------------------------------------------- 1 | var options = { 2 | maxlen: 120 3 | }; 4 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name" : "mysql-libmysqlclient", 3 | "version" : "1.6.0", 4 | "description" : "Binary MySQL bindings for Node.JS", 5 | "keywords" : ["mysql", "libmysqlclient", "sql", "database", "addon"], 6 | "homepage" : "http://sannis.github.com/node-mysql-libmysqlclient", 7 | 8 | "author" : { "name": "Oleg Efimov", "email": "efimovov@gmail.com" }, 9 | "contributors" : 10 | [ { "name": "Oleg Efimov", "email": "efimovov@gmail.com" } 11 | , { "name": "Surendra Singhi", "email": "ssinghi@kreeti.com" } 12 | , { "name": "Akzhan Abdulin", "email": "akzhan.abdulin@gmail.com" } 13 | , { "name": "Robin Duckett", "email": "robin.duckett@gmail.com" } 14 | , { "name": "Dan Beam", "email": "dan@danbeam.org" } 15 | , { "name": "Maurits Lamers", "email": "maurits@weidestraat.nl" } 16 | , { "name": "Benjmain Reesman", "email": "ben.reesman@gmail.com" } 17 | , { "name": "Pavel Ponomarenko", "email": "shocksilien@gmail.com" } 18 | , { "name": "Krists Krīgers", "email": "kristsk@cdi.lv" } 19 | , { "name": "Roman Shtylman", "email": "shtylman@gmail.com" } 20 | , { "name": "Sergey Novgorodsky", "email": "svnovgorodsky@hotmail.com" } 21 | , { "name": "Ștefan Rusu", "email": "saltwaterc@gmail.com" } 22 | , { "name": "Zhiqiang Zhaoy", "email": "zzqvincent@gmail.com" } 23 | , { "name": "Zhao Cheng", "email": "zcbenz@gmail.com" } 24 | , { "name": "Zhao Lei", "email": "iseeyou1987@sina.com" } 25 | ], 26 | 27 | "bugs" : { "url" : "https://github.com/Sannis/node-mysql-libmysqlclient/issues" }, 28 | "license" : { "type" : "MIT", "url": "https://github.com/Sannis/node-mysql-libmysqlclient/blob/master/LICENSE" }, 29 | "repository" : { "type" : "git", "url" : "https://github.com/Sannis/node-mysql-libmysqlclient.git"}, 30 | 31 | "main" : "./lib/mysql-libmysqlclient.js", 32 | 33 | "scripts" : { "test" : "make test", "doc" : "make doc" }, 34 | 35 | "dependencies" : { "nan" : "~1.4.1" }, 36 | 37 | "devDependencies" : 38 | { "nodeunit" : "~0.8.4" 39 | , "difflet" : "~0.2.6" 40 | , "nodelint" : "~0.6.2" 41 | , "async" : "~0.2.10" 42 | , "ndoc" : "~3.1.0" 43 | }, 44 | "engines" : { "node" : ">=0.8.0" } 45 | } 46 | -------------------------------------------------------------------------------- /src/mysql_bindings.cc: -------------------------------------------------------------------------------- 1 | /*! 2 | * Copyright by Oleg Efimov and node-mysql-libmysqlclient contributors 3 | * See contributors list in README 4 | * 5 | * See license text in LICENSE file 6 | */ 7 | 8 | #ifndef BUILDING_NODE_EXTENSION 9 | #define BUILDING_NODE_EXTENSION 1 10 | #endif // BUILDING_NODE_EXTENSION 11 | 12 | #include 13 | 14 | /*! 15 | * Include headers 16 | */ 17 | #include "./mysql_bindings_connection.h" 18 | #include "./mysql_bindings_result.h" 19 | #include "./mysql_bindings_statement.h" 20 | 21 | /*! 22 | * Init V8 structures 23 | * 24 | * Classes to populate in JavaScript: 25 | * 26 | * * MysqlConnection 27 | * * MysqlResult 28 | * * MysqlStatement 29 | */ 30 | void InitMysqlLibmysqlclient(Handle target) { 31 | NanScope(); 32 | 33 | //// Populate classes constructors 34 | MysqlConnection::Init(target); 35 | MysqlResult::Init(target); 36 | MysqlStatement::Init(target); 37 | 38 | //// Populate constants 39 | // Constants for connect flags 40 | NODE_DEFINE_CONSTANT(target, CLIENT_COMPRESS); 41 | NODE_DEFINE_CONSTANT(target, CLIENT_FOUND_ROWS); 42 | NODE_DEFINE_CONSTANT(target, CLIENT_IGNORE_SIGPIPE); 43 | NODE_DEFINE_CONSTANT(target, CLIENT_IGNORE_SPACE); 44 | NODE_DEFINE_CONSTANT(target, CLIENT_INTERACTIVE); 45 | // Not yet implemented 46 | // NODE_DEFINE_CONSTANT(target, CLIENT_LOCAL_FILES); 47 | NODE_DEFINE_CONSTANT(target, CLIENT_MULTI_RESULTS); 48 | NODE_DEFINE_CONSTANT(target, CLIENT_MULTI_STATEMENTS); 49 | NODE_DEFINE_CONSTANT(target, CLIENT_NO_SCHEMA); 50 | // Unused by MySQL 51 | // NODE_DEFINE_CONSTANT(target, CLIENT_ODBC); 52 | // This option should not be set by application programs; 53 | // it is set internally in the client library. Instead, 54 | // use setSslSync() before calling connect() or connectSync(). 55 | // NODE_DEFINE_CONSTANT(target, CLIENT_SSL); 56 | // Known issue: mysql.CLIENT_REMEMBER_OPTIONS === -2147483648 57 | NODE_DEFINE_CONSTANT(target, CLIENT_REMEMBER_OPTIONS); 58 | 59 | // Constants for setOption 60 | NODE_DEFINE_CONSTANT(target, MYSQL_INIT_COMMAND); 61 | NODE_DEFINE_CONSTANT(target, MYSQL_OPT_COMPRESS); 62 | NODE_DEFINE_CONSTANT(target, MYSQL_OPT_CONNECT_TIMEOUT); 63 | // Unused, embedded 64 | // NODE_DEFINE_CONSTANT(MYSQL_OPT_GUESS_CONNECTION); 65 | NODE_DEFINE_CONSTANT(target, MYSQL_OPT_LOCAL_INFILE); 66 | // Unused, windows 67 | // NODE_DEFINE_CONSTANT(target, MYSQL_OPT_NAMED_PIPE); 68 | NODE_DEFINE_CONSTANT(target, MYSQL_OPT_PROTOCOL); 69 | NODE_DEFINE_CONSTANT(target, MYSQL_OPT_READ_TIMEOUT); 70 | NODE_DEFINE_CONSTANT(target, MYSQL_OPT_RECONNECT); 71 | // Unused, embedded 72 | // NODE_DEFINE_CONSTANT(MYSQL_SET_CLIENT_IP); 73 | NODE_DEFINE_CONSTANT(target, MYSQL_OPT_SSL_VERIFY_SERVER_CERT); 74 | // Unused, embedded 75 | // NODE_DEFINE_CONSTANT(MYSQL_OPT_USE_EMBEDDED_CONNECTION); 76 | // Unused, embedded 77 | // NODE_DEFINE_CONSTANT(MYSQL_OPT_USE_REMOTE_CONNECTION); 78 | // Unused by MySQL 79 | // NODE_DEFINE_CONSTANT(MYSQL_OPT_USE_RESULT); 80 | NODE_DEFINE_CONSTANT(target, MYSQL_OPT_WRITE_TIMEOUT); 81 | NODE_DEFINE_CONSTANT(target, MYSQL_READ_DEFAULT_FILE); 82 | NODE_DEFINE_CONSTANT(target, MYSQL_READ_DEFAULT_GROUP); 83 | NODE_DEFINE_CONSTANT(target, MYSQL_REPORT_DATA_TRUNCATION); 84 | NODE_DEFINE_CONSTANT(target, MYSQL_SECURE_AUTH); 85 | NODE_DEFINE_CONSTANT(target, MYSQL_SET_CHARSET_DIR); 86 | NODE_DEFINE_CONSTANT(target, MYSQL_SET_CHARSET_NAME); 87 | // Unused, windows 88 | // NODE_DEFINE_CONSTANT(target, MYSQL_SHARED_MEMORY_BASE_NAME); 89 | 90 | // Statements constants 91 | NODE_DEFINE_CONSTANT(target, STMT_ATTR_UPDATE_MAX_LENGTH); 92 | NODE_DEFINE_CONSTANT(target, STMT_ATTR_CURSOR_TYPE); 93 | NODE_DEFINE_CONSTANT(target, STMT_ATTR_PREFETCH_ROWS); 94 | } 95 | 96 | NODE_MODULE(mysql_bindings, InitMysqlLibmysqlclient) 97 | -------------------------------------------------------------------------------- /src/mysql_bindings.h: -------------------------------------------------------------------------------- 1 | /*! 2 | * Copyright by Oleg Efimov and node-mysql-libmysqlclient contributors 3 | * See contributors list in README 4 | * 5 | * See license text in LICENSE file 6 | */ 7 | 8 | #ifndef SRC_MYSQL_BINDINGS_H_ 9 | #define SRC_MYSQL_BINDINGS_H_ 10 | 11 | #include 12 | #include 13 | 14 | #include "nan.h" 15 | 16 | using namespace v8; // NOLINT 17 | 18 | /*! 19 | * Useful macroses for utility operations 20 | * such as argument checking and C=+ <-> V8 type conversions 21 | */ 22 | 23 | // Only for fixing some cpplint.py errors: 24 | // Lines should be <= 80 characters long 25 | // [whitespace/line_length] [2] 26 | // Lines should very rarely be longer than 100 characters 27 | // [whitespace/line_length] [4] 28 | #define V8EXC(str) Exception::Error(NanNew(str)) 29 | #define OBJUNWRAP ObjectWrap::Unwrap 30 | #define MALLOC_ARRAY(name, type, size) type* name = (type*) malloc(sizeof(type) * size); 31 | 32 | #define REQ_INT_ARG(I, VAR) \ 33 | if (args.Length() <= (I) || !args[I]->IsInt32()) \ 34 | return NanThrowTypeError("Argument " #I " must be an integer"); \ 35 | int32_t VAR = args[I]->Int32Value(); 36 | 37 | #define REQ_UINT_ARG(I, VAR) \ 38 | if (args.Length() <= (I) || !args[I]->IsUint32()) \ 39 | return NanThrowTypeError("Argument " #I " must be an integer"); \ 40 | uint32_t VAR = args[I]->Uint32Value(); 41 | 42 | #define REQ_NUMBER_ARG(I, VAR) \ 43 | if (args.Length() <= (I) || !args[I]->IsNumber()) \ 44 | return NanThrowTypeError("Argument " #I " must be a number"); \ 45 | double VAR = args[I]->NumberValue(); 46 | 47 | #define REQ_STR_ARG(I, VAR) \ 48 | if (args.Length() <= (I) || !args[I]->IsString()) \ 49 | return NanThrowTypeError("Argument " #I " must be a string"); \ 50 | String::Utf8Value VAR(args[I]->ToString()); 51 | 52 | #define OPTIONAL_STR_ARG(I, VAR) \ 53 | String::Utf8Value Utf8Value_##VAR(args[I]->ToString()); \ 54 | char *VAR; \ 55 | if (args[I]->IsString()) { \ 56 | VAR = *(Utf8Value_##VAR); \ 57 | } else { \ 58 | VAR = NULL; \ 59 | } 60 | 61 | #define REQ_BOOL_ARG(I, VAR) \ 62 | if (args.Length() <= (I) || !args[I]->IsBoolean()) \ 63 | return NanThrowTypeError("Argument " #I " must be a boolean"); \ 64 | bool VAR = args[I]->BooleanValue(); 65 | 66 | #define REQ_ARRAY_ARG(I, VAR) \ 67 | if (args.Length() <= (I) || !args[I]->IsArray()) \ 68 | return NanThrowTypeError("Argument " #I " must be an array"); \ 69 | Local VAR = Local::Cast(args[I]); 70 | 71 | #define REQ_EXT_ARG(I, VAR) \ 72 | if (args.Length() <= (I) || !args[I]->IsExternal()) \ 73 | return NanThrowTypeError("Argument " #I " must be an external"); \ 74 | Local VAR = Local::Cast(args[I]); 75 | 76 | #define REQ_FUN_ARG(I, VAR) \ 77 | if (args.Length() <= (I) || !args[I]->IsFunction()) \ 78 | return NanThrowTypeError("Argument " #I " must be a function"); \ 79 | Local VAR = Local::Cast(args[I]); 80 | 81 | #define OPTIONAL_FUN_ARG(I, VAR) \ 82 | Handle VAR; \ 83 | if (args.Length() > (I) && args[I]->IsFunction()) {\ 84 | VAR = args[I]; \ 85 | } else { \ 86 | VAR = NanNull(); \ 87 | } 88 | 89 | #define OPTIONAL_BUFFER_ARG(I, VAR) \ 90 | Handle VAR; \ 91 | if (args.Length() > (I) \ 92 | && args[I]->IsObject() \ 93 | && node::Buffer::HasInstance(args[I]) \ 94 | ) { \ 95 | VAR = args[I]->ToObject(); \ 96 | } else { \ 97 | VAR = NanNull(); \ 98 | } 99 | 100 | #ifdef DEBUG 101 | #define DEBUG_PRINTF(...) printf("\nDEBUG_PRINTF: "); printf(__VA_ARGS__); printf("\n") 102 | #define DEBUG_ARGS() for (int i = 0; i < args.Length(); i++) { \ 103 | printf( \ 104 | "DEBUG_ARGS[%d]: is_null(%d) is_bool(%d) is_number(%d) is_string(%d) is_object(%d) is_function(%d) is_external(%d)\n", \ 105 | i, \ 106 | args[i]->IsNull() ? 1 : 0, \ 107 | args[i]->IsBoolean() ? 1 : 0, \ 108 | args[i]->IsNumber() ? 1 : 0, \ 109 | args[i]->IsString() ? 1 : 0, \ 110 | args[i]->IsObject() ? 1 : 0, \ 111 | args[i]->IsFunction() ? 1 : 0, \ 112 | args[i]->IsExternal() ? 1 : 0 \ 113 | ); \ 114 | } \ 115 | printf("DEBUG_ARGS END\n\n"); 116 | #else 117 | #define DEBUG_PRINTF(...) (void)0 118 | #define DEBUG_ARGS() (void)0 119 | #endif 120 | 121 | #endif // SRC_MYSQL_BINDINGS_H_ 122 | 123 | -------------------------------------------------------------------------------- /src/mysql_bindings_connection.h: -------------------------------------------------------------------------------- 1 | /*! 2 | * Copyright by Oleg Efimov and node-mysql-libmysqlclient contributors 3 | * See contributors list in README 4 | * 5 | * See license text in LICENSE file 6 | */ 7 | 8 | #ifndef SRC_MYSQL_BINDINGS_CONNECTION_H_ 9 | #define SRC_MYSQL_BINDINGS_CONNECTION_H_ 10 | 11 | #include 12 | 13 | #include 14 | #include 15 | 16 | #include 17 | #include 18 | 19 | #include 20 | #include 21 | 22 | #include "./mysql_bindings.h" 23 | 24 | #define MYSQLCONN_DISABLE_MQ \ 25 | if (conn->multi_query) { \ 26 | mysql_set_server_option(conn->_conn, MYSQL_OPTION_MULTI_STATEMENTS_OFF); \ 27 | conn->multi_query = false; \ 28 | } 29 | 30 | #define MYSQLCONN_ENABLE_MQ \ 31 | if (!conn->multi_query) { \ 32 | mysql_set_server_option(conn->_conn, MYSQL_OPTION_MULTI_STATEMENTS_ON); \ 33 | conn->multi_query = true; \ 34 | } 35 | 36 | #define MYSQLCONN_MUSTBE_CONNECTED \ 37 | if (!conn->_conn || !conn->connected) { \ 38 | return NanThrowError("Not connected"); \ 39 | } 40 | 41 | #define MYSQLCONN_MUSTBE_INITIALIZED \ 42 | if (!conn->_conn) { \ 43 | return NanThrowError("Not initialized"); \ 44 | } 45 | 46 | /** section: Classes 47 | * class MysqlConnection 48 | * 49 | * MySQL connection class, base version 50 | **/ 51 | class MysqlConnection : public node::ObjectWrap { 52 | public: 53 | static Persistent constructor_template; 54 | 55 | static void Init(Handle target); 56 | 57 | bool Connect(const char* hostname, 58 | const char* user, 59 | const char* password, 60 | const char* dbname, 61 | uint32_t port, 62 | const char* socket, 63 | uint64_t flags); 64 | 65 | bool RealConnect(const char* hostname, 66 | const char* user, 67 | const char* password, 68 | const char* dbname, 69 | uint32_t port, 70 | const char* socket, 71 | uint64_t flags); 72 | 73 | void Close(); 74 | 75 | private: 76 | MYSQL *_conn; 77 | bool connected; 78 | 79 | pthread_mutex_t query_lock; 80 | 81 | bool multi_query; 82 | my_bool opt_reconnect; 83 | 84 | unsigned int connect_errno; 85 | const char *connect_error; 86 | 87 | MysqlConnection(); 88 | 89 | ~MysqlConnection(); 90 | 91 | // Constructor 92 | 93 | static NAN_METHOD(New); 94 | 95 | // Properties 96 | 97 | static NAN_GETTER(ConnectErrnoGetter); 98 | 99 | static NAN_GETTER(ConnectErrorGetter); 100 | 101 | // Methods 102 | 103 | static NAN_METHOD(AffectedRowsSync); 104 | 105 | static NAN_METHOD(AutoCommitSync); 106 | 107 | static NAN_METHOD(ChangeUserSync); 108 | 109 | static NAN_METHOD(CommitSync); 110 | 111 | struct connect_request { 112 | bool ok; 113 | 114 | NanCallback *nan_callback; 115 | MysqlConnection *conn; 116 | 117 | String::Utf8Value *hostname; 118 | String::Utf8Value *user; 119 | String::Utf8Value *password; 120 | String::Utf8Value *dbname; 121 | uint32_t port; 122 | String::Utf8Value *socket; 123 | uint64_t flags; 124 | }; 125 | static void EIO_After_Connect(uv_work_t *req); 126 | static void EIO_Connect(uv_work_t *req); 127 | static NAN_METHOD(Connect); 128 | 129 | static NAN_METHOD(ConnectSync); 130 | 131 | static NAN_METHOD(ConnectedSync); 132 | 133 | static NAN_METHOD(CloseSync); 134 | 135 | static NAN_METHOD(DebugSync); 136 | 137 | static NAN_METHOD(DumpDebugInfoSync); 138 | 139 | static NAN_METHOD(ErrnoSync); 140 | 141 | static NAN_METHOD(ErrorSync); 142 | 143 | static NAN_METHOD(EscapeSync); 144 | 145 | static NAN_METHOD(FieldCountSync); 146 | 147 | static NAN_METHOD(GetCharsetSync); 148 | 149 | static NAN_METHOD(GetCharsetNameSync); 150 | 151 | static NAN_METHOD(GetClientInfoSync); 152 | 153 | static NAN_METHOD(GetInfoSync); 154 | 155 | static NAN_METHOD(GetInfoStringSync); 156 | 157 | static NAN_METHOD(GetWarningsSync); 158 | 159 | static NAN_METHOD(InitSync); 160 | 161 | static NAN_METHOD(InitStatementSync); 162 | 163 | static NAN_METHOD(LastInsertIdSync); 164 | 165 | static NAN_METHOD(MultiMoreResultsSync); 166 | 167 | static NAN_METHOD(MultiNextResultSync); 168 | 169 | static NAN_METHOD(MultiRealQuerySync); 170 | 171 | static NAN_METHOD(PingSync); 172 | struct local_infile_data { 173 | char * buffer; 174 | size_t length; 175 | size_t position; 176 | }; 177 | 178 | struct query_request { 179 | bool ok; 180 | bool connection_closed; 181 | bool have_result_set; 182 | 183 | NanCallback *nan_callback; 184 | MysqlConnection *conn; 185 | 186 | char *query; 187 | unsigned int query_len; 188 | 189 | MYSQL_RES *my_result; 190 | uint32_t field_count; 191 | my_ulonglong affected_rows; 192 | my_ulonglong insert_id; 193 | 194 | unsigned int my_errno; 195 | const char *my_error; 196 | 197 | local_infile_data * infile_data; 198 | }; 199 | static int CustomLocalInfileInit(void ** ptr, 200 | const char * filename, 201 | void * userdata); 202 | static int CustomLocalInfileRead(void * ptr, 203 | char * buf, 204 | unsigned int buf_len); 205 | static void CustomLocalInfileEnd(void * ptr); 206 | static int CustomLocalInfileError(void * ptr, 207 | char * error_msg, 208 | unsigned int error_msg_len); 209 | static void SetCorrectLocalInfileHandlers(local_infile_data * infile_data, 210 | MYSQL * conn); 211 | static void RestoreLocalInfileHandlers(local_infile_data * infile_data, 212 | MYSQL * conn); 213 | static local_infile_data * PrepareLocalInfileData(Handle buffer); 214 | static void EIO_After_Query(uv_work_t *req); 215 | static void EIO_Query(uv_work_t *req); 216 | static NAN_METHOD(Query); 217 | 218 | static void EV_After_QuerySend(uv_poll_t* handle, int status, int events); 219 | static void EV_After_QuerySend_OnWatchHandleClose(uv_handle_t* handle); 220 | static NAN_METHOD(QuerySend); 221 | 222 | static NAN_METHOD(QuerySync); 223 | 224 | static NAN_METHOD(RealConnectSync); 225 | 226 | static NAN_METHOD(RealQuerySync); 227 | 228 | static NAN_METHOD(RollbackSync); 229 | 230 | static NAN_METHOD(SelectDbSync); 231 | 232 | static NAN_METHOD(SetCharsetSync); 233 | 234 | static NAN_METHOD(SetOptionSync); 235 | 236 | static NAN_METHOD(SetSslSync); 237 | 238 | static NAN_METHOD(SqlStateSync); 239 | 240 | static NAN_METHOD(StatSync); 241 | 242 | static NAN_METHOD(StoreResultSync); 243 | 244 | static NAN_METHOD(ThreadIdSync); 245 | 246 | static NAN_METHOD(ThreadSafeSync); 247 | 248 | static NAN_METHOD(UseResultSync); 249 | 250 | static NAN_METHOD(WarningCountSync); 251 | }; 252 | 253 | #endif // SRC_MYSQL_BINDINGS_CONNECTION_H_ 254 | 255 | -------------------------------------------------------------------------------- /src/mysql_bindings_result.h: -------------------------------------------------------------------------------- 1 | /*! 2 | * Copyright by Oleg Efimov and node-mysql-libmysqlclient contributors 3 | * See contributors list in README 4 | * 5 | * See license text in LICENSE file 6 | */ 7 | 8 | #ifndef SRC_MYSQL_BINDINGS_RESULT_H_ 9 | #define SRC_MYSQL_BINDINGS_RESULT_H_ 10 | 11 | #include 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #include 19 | 20 | #include "./mysql_bindings.h" 21 | 22 | #define mysql_result_is_unbuffered(r) \ 23 | ((r)->handle && (r)->handle->status == MYSQL_STATUS_USE_RESULT) 24 | 25 | #define MYSQLRES_MUSTBE_VALID \ 26 | if (!res->_res) { \ 27 | return NanThrowError("Result has been freed."); \ 28 | } 29 | 30 | /** section: Classes 31 | * class MysqlResult 32 | * 33 | * MySQL results class 34 | **/ 35 | class MysqlResult : public node::ObjectWrap { 36 | public: 37 | static Persistent constructor_template; 38 | 39 | static void Init(Handle target); 40 | 41 | static Local NewInstance(MYSQL *my_conn, MYSQL_RES *my_result, uint32_t field_count); 42 | 43 | static void AddFieldProperties(Local &js_field_obj, MYSQL_FIELD *field); 44 | 45 | static Local GetFieldValue(MYSQL_FIELD field, char* field_value, unsigned long field_length); 46 | 47 | struct fetch_options { 48 | bool results_as_array; 49 | bool results_nest_tables; 50 | }; 51 | static fetch_options GetFetchOptions(Local options); 52 | 53 | void Free(); 54 | 55 | private: 56 | MYSQL *_conn; 57 | MYSQL_RES *_res; 58 | 59 | uint32_t field_count; 60 | 61 | MysqlResult(); 62 | 63 | explicit MysqlResult(MYSQL *my_connection, MYSQL_RES *my_result, uint32_t my_field_count): 64 | ObjectWrap(), 65 | _conn(my_connection), 66 | _res(my_result), 67 | field_count(my_field_count) {} 68 | 69 | ~MysqlResult(); 70 | 71 | // Constructor 72 | 73 | static NAN_METHOD(New); 74 | 75 | // Properties 76 | 77 | static NAN_GETTER(FieldCountGetter); 78 | 79 | // Methods 80 | 81 | static NAN_METHOD(DataSeekSync); 82 | 83 | struct fetchAll_request { 84 | bool ok; 85 | 86 | NanCallback *nan_callback; 87 | MysqlResult *res; 88 | 89 | MYSQL_FIELD *fields; 90 | uint32_t num_fields; 91 | 92 | fetch_options fo; 93 | }; 94 | static void EIO_After_FetchAll(uv_work_t *req); 95 | static void EIO_FetchAll(uv_work_t *req); 96 | static NAN_METHOD(FetchAll); 97 | 98 | static NAN_METHOD(FetchAllSync); 99 | 100 | static NAN_METHOD(FetchFieldSync); 101 | 102 | static NAN_METHOD(FetchFieldDirectSync); 103 | 104 | static NAN_METHOD(FetchFieldsSync); 105 | 106 | static NAN_METHOD(FetchLengthsSync); 107 | 108 | static NAN_METHOD(FetchRowSync); 109 | 110 | static NAN_METHOD(FieldSeekSync); 111 | 112 | static NAN_METHOD(FieldTellSync); 113 | 114 | static NAN_METHOD(FreeSync); 115 | 116 | static NAN_METHOD(NumRowsSync); 117 | }; 118 | 119 | #endif // SRC_MYSQL_BINDINGS_RESULT_H_ 120 | 121 | -------------------------------------------------------------------------------- /src/mysql_bindings_statement.h: -------------------------------------------------------------------------------- 1 | /*! 2 | * Copyright by Oleg Efimov and node-mysql-libmysqlclient contributors 3 | * See contributors list in README 4 | * 5 | * See license text in LICENSE file 6 | */ 7 | 8 | #ifndef SRC_MYSQL_BINDINGS_STATEMENT_H_ 9 | #define SRC_MYSQL_BINDINGS_STATEMENT_H_ 10 | 11 | #include 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | #include "./mysql_bindings.h" 18 | 19 | #define MYSQLSTMT_MUSTBE_INITIALIZED \ 20 | if (stmt->state < STMT_INITIALIZED) { \ 21 | return NanThrowError("Statement not initialized"); \ 22 | } 23 | 24 | #define MYSQLSTMT_MUSTBE_PREPARED \ 25 | if (stmt->state < STMT_PREPARED) { \ 26 | return NanThrowError("Statement not prepared"); \ 27 | } 28 | 29 | #define MYSQLSTMT_MUSTBE_EXECUTED \ 30 | if (stmt->state < STMT_EXECUTED) { \ 31 | return NanThrowError("Statement not executed"); \ 32 | } 33 | 34 | #define MYSQLSTMT_MUSTBE_STORED \ 35 | if (stmt->state < STMT_STORED_RESULT) { \ 36 | return NanThrowError("Statement result not stored"); \ 37 | } 38 | 39 | /** section: Classes 40 | * class MysqlStatement 41 | * 42 | * MySQL prepared statement class 43 | **/ 44 | class MysqlStatement : public node::ObjectWrap { 45 | public: 46 | static Persistent constructor_template; 47 | 48 | static void Init(Handle target); 49 | 50 | static Local NewInstance(MYSQL_STMT *my_statement); 51 | 52 | private: 53 | MYSQL_STMT *_stmt; 54 | 55 | MYSQL_BIND *binds; 56 | MYSQL_BIND *result_binds; 57 | unsigned long param_count; 58 | 59 | enum MysqlStatementState { 60 | STMT_CLOSED, 61 | STMT_INITIALIZED, 62 | STMT_PREPARED, 63 | STMT_BINDED_PARAMS, 64 | STMT_EXECUTED, 65 | STMT_BINDED_RESULT, 66 | STMT_STORED_RESULT, 67 | }; 68 | MysqlStatementState state; 69 | 70 | MysqlStatement(MYSQL_STMT *my_stmt); 71 | 72 | ~MysqlStatement(); 73 | 74 | // Constructor 75 | 76 | static NAN_METHOD(New); 77 | 78 | // Properties 79 | 80 | static NAN_GETTER(ParamCountGetter); 81 | 82 | // Methods 83 | 84 | static NAN_METHOD(AffectedRowsSync); 85 | 86 | static NAN_METHOD(AttrGetSync); 87 | 88 | static NAN_METHOD(AttrSetSync); 89 | 90 | static NAN_METHOD(BindParamsSync); 91 | 92 | static NAN_METHOD(BindResultSync); 93 | 94 | static NAN_METHOD(CloseSync); 95 | 96 | static NAN_METHOD(DataSeekSync); 97 | 98 | static NAN_METHOD(ErrnoSync); 99 | 100 | static NAN_METHOD(ErrorSync); 101 | 102 | struct execute_request { 103 | bool ok; 104 | 105 | NanCallback *nan_callback; 106 | MysqlStatement* stmt; 107 | }; 108 | 109 | static void EIO_After_Execute(uv_work_t* req); 110 | 111 | static void EIO_Execute(uv_work_t* req); 112 | 113 | static NAN_METHOD(Execute); 114 | 115 | static NAN_METHOD(ExecuteSync); 116 | 117 | struct fetch_request { 118 | bool ok; 119 | bool empty_resultset; 120 | 121 | NanCallback *nan_callback; 122 | MysqlStatement* stmt; 123 | 124 | MYSQL_RES* meta; 125 | unsigned long field_count; 126 | }; 127 | static void EIO_After_FetchAll(uv_work_t* req); 128 | static void EIO_FetchAll(uv_work_t* req); 129 | static NAN_METHOD(FetchAll); 130 | 131 | static NAN_METHOD(FetchAllSync); 132 | 133 | static void EIO_After_Fetch(uv_work_t* req); 134 | static void EIO_Fetch(uv_work_t* req); 135 | static NAN_METHOD(Fetch); 136 | 137 | static NAN_METHOD(FetchSync); 138 | 139 | static NAN_METHOD(FieldCountSync); 140 | 141 | static NAN_METHOD(FreeResultSync); 142 | 143 | static void FreeMysqlBinds(MYSQL_BIND *binds, unsigned long size, bool params); 144 | 145 | static Local GetFieldValue(void* ptr, unsigned long& field_length, MYSQL_FIELD& field); 146 | 147 | static NAN_METHOD(LastInsertIdSync); 148 | 149 | static NAN_METHOD(NextResultSync); 150 | 151 | static NAN_METHOD(NumRowsSync); 152 | 153 | static NAN_METHOD(PrepareSync); 154 | 155 | static NAN_METHOD(ResetSync); 156 | 157 | static NAN_METHOD(ResultMetadataSync); 158 | 159 | static NAN_METHOD(SendLongDataSync); 160 | 161 | static NAN_METHOD(StoreResultSync); 162 | 163 | struct store_result_request { 164 | bool ok; 165 | 166 | NanCallback *nan_callback; 167 | MysqlStatement* stmt; 168 | }; 169 | static void EIO_After_StoreResult(uv_work_t* req); 170 | static void EIO_StoreResult(uv_work_t* req); 171 | static NAN_METHOD(StoreResult); 172 | 173 | static NAN_METHOD(SqlStateSync); 174 | }; 175 | 176 | #endif // SRC_MYSQL_BINDINGS_STATEMENT_H_ 177 | 178 | -------------------------------------------------------------------------------- /tests/complex/setup-complex.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright by Oleg Efimov and node-mysql-libmysqlclient contributors 3 | See contributors list in README 4 | 5 | See license text in LICENSE file 6 | */ 7 | 8 | // Load configuration 9 | var cfg = require("../config"); 10 | 11 | exports.createTestTableComplex1 = function (test) { 12 | test.expect(3); 13 | 14 | var 15 | conn = cfg.mysql_libmysqlclient.createConnectionSync(cfg.host, cfg.user, cfg.password, cfg.database), 16 | res, 17 | tables; 18 | 19 | conn.querySync("DROP TABLE IF EXISTS " + cfg.test_table + ";"); 20 | conn.querySync("CREATE TABLE " + cfg.test_table + 21 | " (size ENUM('small', 'medium', 'large') NULL," + 22 | " colors SET('red', 'green', 'blue') NULL," + 23 | " num INT(8) NOT NULL DEFAULT 0) " + cfg.store_engine + ";"); 24 | res = conn.querySync("SHOW TABLES"); 25 | tables = res.fetchAllSync(); 26 | 27 | test.ok(res.fieldCount === 1, "SHOW TABLES result field count === 1"); 28 | test.ok(tables.some(function (r) { 29 | return r['Tables_in_' + cfg.database] === cfg.test_table; 30 | }), "Find the test_table in results"); 31 | 32 | res = conn.querySync("INSERT INTO " + cfg.test_table + 33 | " (size, colors) VALUES ('small', 'red');"); 34 | res = conn.querySync("INSERT INTO " + cfg.test_table + 35 | " (size, colors) VALUES ('medium', 'red,green,blue');") && res; 36 | res = conn.querySync("INSERT INTO " + cfg.test_table + 37 | " (size, colors) VALUES ('large', 'green');") && res; 38 | res = conn.querySync("INSERT INTO " + cfg.test_table + 39 | " (size, colors) VALUES ('large', 'red,blue');") && res; 40 | test.ok(res, "conn.querySync('INSERT INTO test_table ...')"); 41 | 42 | conn.closeSync(); 43 | test.done(); 44 | }; 45 | 46 | -------------------------------------------------------------------------------- /tests/complex/test-binary-buffers.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright by Oleg Efimov and node-mysql-libmysqlclient contributors 3 | See contributors list in README 4 | 5 | See license text in LICENSE file 6 | */ 7 | 8 | // Load configuration 9 | var cfg = require('../config'); 10 | 11 | exports.createTestTableComplex2BinaryBlobs = function (test) { 12 | test.expect(3); 13 | 14 | var 15 | conn = cfg.mysql_libmysqlclient.createConnectionSync(cfg.host, cfg.user, cfg.password, cfg.database), 16 | res, 17 | tables; 18 | 19 | conn.querySync("DROP TABLE IF EXISTS " + cfg.test_table2 + ";"); 20 | conn.querySync("CREATE TABLE " + cfg.test_table2 + 21 | " (id INT AUTO_INCREMENT, vc VARCHAR(8), vbi VARBINARY(8), bi BINARY(8), t TEXT, b BLOB, PRIMARY KEY (id)) " + cfg.store_engine + ";"); 22 | res = conn.querySync("SHOW TABLES"); 23 | tables = res.fetchAllSync(); 24 | 25 | test.ok(res.fieldCount === 1, "SHOW TABLES result field count === 1"); 26 | test.ok(tables.some(function (r) { 27 | return r['Tables_in_' + cfg.database] === cfg.test_table2; 28 | }), "Find the test_table2 in results"); 29 | 30 | res = conn.querySync("INSERT INTO " + cfg.test_table2 + 31 | " (vc, vbi, bi, t, b) VALUES ('qwerty', 'qwerty', 'qwerty', 'qwerty', 'qwerty');"); 32 | res = conn.querySync("INSERT INTO " + cfg.test_table2 + 33 | " (vc, vbi, bi, t, b) VALUES ('qwe\\0\\0', 'qwe\\0\\0', 'qwe\\0\\0', 'qwe\\0\\0', 'qwe\\0\\0');") && res; 34 | res = conn.querySync("INSERT INTO " + cfg.test_table2 + 35 | " (vc, vbi, bi, t) VALUES ('12\\0\\0', '12\\0\\0', '12\\0\\0', '12\\0\\0');") && res; 36 | res = conn.querySync("INSERT INTO " + cfg.test_table2 + 37 | " (vc, vbi, bi, b) VALUES ('34\\0\\0', '34\\0\\0', '34\\0\\0', '34\\0\\0');") && res; 38 | test.ok(res, "conn.querySync('INSERT INTO test_table2 ...')"); 39 | 40 | // Ensure all rows are inserted 41 | setTimeout(function () { 42 | conn.closeSync(); 43 | test.done(); 44 | }, 100); 45 | }; 46 | 47 | exports.FetchAllSyncWithBinaryFields = function (test) { 48 | test.expect(2); 49 | 50 | var 51 | conn = cfg.mysql_libmysqlclient.createConnectionSync(cfg.host, cfg.user, cfg.password, cfg.database), 52 | res, 53 | rows, 54 | rowsExpected; 55 | 56 | res = conn.querySync("SELECT vc, vbi, bi, t, b FROM " + cfg.test_table2 + " ORDER BY id;"); 57 | test.ok(res instanceof cfg.mysql_bindings.MysqlResult); 58 | 59 | rows = res.fetchAllSync({"asArray": true}); 60 | 61 | rowsExpected = [ [ 'qwerty', new Buffer('qwerty'), new Buffer('qwerty\0\0'), 'qwerty', new Buffer('qwerty') ], 62 | [ 'qwe\u0000\u0000', new Buffer('qwe\0\0'), new Buffer('qwe\0\0\0\0\0'), 'qwe\u0000\u0000', new Buffer('qwe\0\0') ], 63 | [ '12\u0000\u0000', new Buffer('12\0\0'), new Buffer('12\0\0\0\0\0\0'), '12\u0000\u0000', null ], 64 | [ '34\u0000\u0000', new Buffer('34\0\0'), new Buffer('34\0\0\0\0\0\0'), null, new Buffer('34\0\0') ] ]; 65 | 66 | var difflet = require('difflet')({indent: 2, comment: true}); 67 | test.same( 68 | cfg.util.inspect(rows), 69 | cfg.util.inspect(rowsExpected), 70 | "conn.querySync('SELECT ...').fetchAllSync(true) failed: " + difflet.compare(rowsExpected, rows) 71 | ); 72 | 73 | res.freeSync(); 74 | 75 | conn.closeSync(); 76 | 77 | test.done(); 78 | }; 79 | 80 | -------------------------------------------------------------------------------- /tests/complex/test-call-stored-procedure.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright by Oleg Efimov and node-mysql-libmysqlclient contributors 3 | See contributors list in README 4 | 5 | See license text in LICENSE file 6 | */ 7 | 8 | // Load configuration 9 | var cfg = require('../config'); 10 | 11 | /** 12 | * Reference: 13 | * http://dev.mysql.com/doc/refman/5.1/en/create-procedure.html 14 | * http://dev.mysql.com/doc/refman/5.1/en/call.html 15 | */ 16 | 17 | exports.CallStoredProcedureSelectSync = function (test) { 18 | test.expect(4); 19 | 20 | var 21 | conn = cfg.mysql_libmysqlclient.createConnectionSync(), 22 | res, 23 | num = 1234, 24 | numFromProcedure; 25 | 26 | conn.connectSync(cfg.host, cfg.user, cfg.password, cfg.database, null, null, cfg.mysql_libmysqlclient.CLIENT_MULTI_RESULTS); 27 | 28 | res = conn.querySync("DROP PROCEDURE IF EXISTS test_procedure;"); 29 | test.strictEqual(res, true); 30 | 31 | res = conn.querySync("CREATE PROCEDURE test_procedure() SELECT " + num + " AS num;"); 32 | test.strictEqual(res, true); 33 | 34 | res = conn.querySync("CALL test_procedure();"); 35 | test.ok(res instanceof cfg.mysql_bindings.MysqlResult, "CALL test_procedure();"); 36 | 37 | numFromProcedure = res.fetchAllSync()[0].num; 38 | res.freeSync(); 39 | 40 | test.equals(numFromProcedure, num, "numFromProcedure == num"); 41 | 42 | conn.closeSync(); 43 | test.done(); 44 | }; 45 | 46 | exports.CallStoredProcedureSelectTwiceSync = function (test) { 47 | test.expect(6); 48 | 49 | var 50 | conn = cfg.mysql_libmysqlclient.createConnectionSync(), 51 | res, 52 | num = 1234, 53 | numFromProcedure; 54 | 55 | conn.connectSync(cfg.host, cfg.user, cfg.password, cfg.database, null, null, cfg.mysql_libmysqlclient.CLIENT_MULTI_RESULTS); 56 | 57 | res = conn.querySync("DROP PROCEDURE IF EXISTS test_procedure;"); 58 | test.strictEqual(res, true); 59 | 60 | res = conn.querySync("CREATE PROCEDURE test_procedure() SELECT " + num + " AS num;"); 61 | test.strictEqual(res, true); 62 | 63 | res = conn.querySync("CALL test_procedure();"); 64 | test.ok(res instanceof cfg.mysql_bindings.MysqlResult, "CALL test_procedure();"); 65 | 66 | numFromProcedure = res.fetchAllSync()[0].num; 67 | res.freeSync(); 68 | 69 | test.equals(numFromProcedure, num, "numFromProcedure == num"); 70 | 71 | // We need to get second result from set, that contains execution status 72 | while (conn.multiMoreResultsSync()) { 73 | // Go to next result in set 74 | conn.multiNextResultSync(); 75 | // Store result 76 | res = conn.storeResultSync(); 77 | if (typeof res.freeSync === 'function') { 78 | // Free result if it is not simple true/false 79 | res.freeSync(); 80 | } 81 | } 82 | 83 | res = conn.querySync("CALL test_procedure();"); 84 | 85 | test.ok(res instanceof cfg.mysql_bindings.MysqlResult, "CALL test_procedure();"); 86 | 87 | numFromProcedure = res.fetchAllSync()[0].num; 88 | res.freeSync(); 89 | 90 | test.equals(numFromProcedure, num, "numFromProcedure == num"); 91 | 92 | // We need to get second result from set, that contains execution status 93 | while (conn.multiMoreResultsSync()) { 94 | // Go to next result in set 95 | conn.multiNextResultSync(); 96 | // Store result 97 | res = conn.storeResultSync(); 98 | if (typeof res.freeSync === 'function') { 99 | // Free result if it is not simple true/false 100 | res.freeSync(); 101 | } 102 | } 103 | 104 | conn.closeSync(); 105 | test.done(); 106 | }; 107 | 108 | exports.CallStoredProcedureSelectIntoSync = function (test) { 109 | test.expect(5); 110 | 111 | var 112 | conn = cfg.mysql_libmysqlclient.createConnectionSync(), 113 | res, 114 | num = 1234, 115 | numFromProcedure; 116 | 117 | conn.connectSync(cfg.host, cfg.user, cfg.password, cfg.database, null, null, cfg.mysql_libmysqlclient.CLIENT_MULTI_RESULTS); 118 | 119 | res = conn.querySync("DROP PROCEDURE IF EXISTS test_procedure;"); 120 | test.strictEqual(res, true); 121 | 122 | res = conn.querySync("CREATE PROCEDURE test_procedure(OUT num INT) SELECT " + num + " INTO num;"); 123 | test.strictEqual(res, true); 124 | 125 | res = conn.querySync("CALL test_procedure(@num);"); 126 | test.strictEqual(res, true); 127 | 128 | res = conn.querySync("SELECT @num AS num;"); 129 | test.ok(res instanceof cfg.mysql_bindings.MysqlResult, "SELECT @num AS num;"); 130 | 131 | numFromProcedure = res.fetchAllSync()[0].num; 132 | res.freeSync(); 133 | 134 | test.equals(numFromProcedure, num, "numFromProcedure == num"); 135 | 136 | conn.closeSync(); 137 | test.done(); 138 | }; 139 | 140 | exports.CallStoredProcedureSelectIntoTwiceSync = function (test) { 141 | test.expect(8); 142 | 143 | var 144 | conn = cfg.mysql_libmysqlclient.createConnectionSync(), 145 | res, 146 | num = 1234, 147 | numFromProcedure; 148 | 149 | conn.connectSync(cfg.host, cfg.user, cfg.password, cfg.database, null, null, cfg.mysql_libmysqlclient.CLIENT_MULTI_RESULTS); 150 | 151 | res = conn.querySync("DROP PROCEDURE IF EXISTS test_procedure;"); 152 | test.strictEqual(res, true); 153 | 154 | res = conn.querySync("CREATE PROCEDURE test_procedure(OUT num INT) SELECT " + num + " INTO num;"); 155 | test.strictEqual(res, true); 156 | 157 | res = conn.querySync("CALL test_procedure(@num);"); 158 | test.strictEqual(res, true); 159 | 160 | res = conn.querySync("SELECT @num AS num;"); 161 | test.ok(res instanceof cfg.mysql_bindings.MysqlResult, "SELECT @num AS num;"); 162 | 163 | numFromProcedure = res.fetchAllSync()[0].num; 164 | res.freeSync(); 165 | 166 | test.equals(numFromProcedure, num, "numFromProcedure == num"); 167 | 168 | // We need to get second result from set, that contains execution status 169 | while (conn.multiMoreResultsSync()) { 170 | // Go to next result in set 171 | conn.multiNextResultSync(); 172 | // Store result 173 | res = conn.storeResultSync(); 174 | if (typeof res.freeSync === 'function') { 175 | // Free result if it is not simple true/false 176 | res.freeSync(); 177 | } 178 | } 179 | 180 | res = conn.querySync("CALL test_procedure(@num);"); 181 | test.strictEqual(res, true); 182 | 183 | res = conn.querySync("SELECT @num AS num;"); 184 | test.ok(res instanceof cfg.mysql_bindings.MysqlResult, "SELECT @num AS num;"); 185 | 186 | numFromProcedure = res.fetchAllSync()[0].num; 187 | res.freeSync(); 188 | 189 | test.equals(numFromProcedure, num, "numFromProcedure == num"); 190 | 191 | // We need to get second result from set, that contains execution status 192 | while (conn.multiMoreResultsSync()) { 193 | // Go to next result in set 194 | conn.multiNextResultSync(); 195 | // Store result 196 | res = conn.storeResultSync(); 197 | if (typeof res.freeSync === 'function') { 198 | // Free result if it is not simple true/false 199 | res.freeSync(); 200 | } 201 | } 202 | 203 | conn.closeSync(); 204 | test.done(); 205 | }; 206 | 207 | exports.CallStoredFunctionSync = function (test) { 208 | test.expect(4); 209 | 210 | var 211 | conn = cfg.mysql_libmysqlclient.createConnectionSync(), 212 | res, 213 | error, 214 | num = 1234, 215 | numFromFunction; 216 | 217 | conn.connectSync(cfg.host, cfg.user, cfg.password, cfg.database, null, null, cfg.mysql_libmysqlclient.CLIENT_MULTI_RESULTS); 218 | 219 | res = conn.querySync("DROP FUNCTION IF EXISTS test_function;"); 220 | test.strictEqual(res, true); 221 | 222 | res = conn.querySync("CREATE FUNCTION test_function() RETURNS INT DETERMINISTIC RETURN " + num + ";"); 223 | test.strictEqual(res, true); 224 | 225 | if (!res) { 226 | error = conn.errorSync(); 227 | if (error.match(new RegExp("You do not have the SUPER privilege and binary logging is enabled"))) { 228 | console.log("Known MySQL bug: run `SET GLOBAL log_bin_trust_function_creators = 1;` " 229 | + "in MySQL console to fix this."); 230 | } 231 | } 232 | 233 | res = conn.querySync("SELECT test_function() AS num;"); 234 | test.ok(res instanceof cfg.mysql_bindings.MysqlResult, "SELECT test_function() AS num;"); 235 | 236 | numFromFunction = res.fetchAllSync()[0].num; 237 | res.freeSync(); 238 | 239 | test.equals(numFromFunction, num, "numFromFunction == num"); 240 | 241 | conn.closeSync(); 242 | test.done(); 243 | }; 244 | 245 | exports.CallStoredFunctionTwiceSync = function (test) { 246 | test.expect(6); 247 | 248 | var 249 | conn = cfg.mysql_libmysqlclient.createConnectionSync(), 250 | res, 251 | error, 252 | num = 1234, 253 | numFromFunction; 254 | 255 | conn.connectSync(cfg.host, cfg.user, cfg.password, cfg.database, null, null, cfg.mysql_libmysqlclient.CLIENT_MULTI_RESULTS); 256 | 257 | res = conn.querySync("DROP FUNCTION IF EXISTS test_function;"); 258 | test.strictEqual(res, true); 259 | 260 | res = conn.querySync("CREATE FUNCTION test_function() RETURNS INT DETERMINISTIC RETURN " + num + ";"); 261 | test.strictEqual(res, true); 262 | 263 | if (!res) { 264 | error = conn.errorSync(); 265 | if (error.match(new RegExp("You do not have the SUPER privilege and binary logging is enabled"))) { 266 | console.log("Known MySQL bug: run `SET GLOBAL log_bin_trust_function_creators = 1;` " 267 | + "in MySQL console to fix this."); 268 | } 269 | } 270 | 271 | res = conn.querySync("SELECT test_function() AS num;"); 272 | test.ok(res instanceof cfg.mysql_bindings.MysqlResult, "SELECT test_function() AS num;"); 273 | 274 | numFromFunction = res.fetchAllSync()[0].num; 275 | res.freeSync(); 276 | 277 | test.equals(numFromFunction, num, "numFromFunction == num"); 278 | 279 | res = conn.querySync("SELECT test_function() AS num;"); 280 | test.ok(res instanceof cfg.mysql_bindings.MysqlResult, "SELECT test_function() AS num;"); 281 | 282 | numFromFunction = res.fetchAllSync()[0].num; 283 | res.freeSync(); 284 | 285 | test.equals(numFromFunction, num, "numFromFunction == num"); 286 | 287 | conn.closeSync(); 288 | test.done(); 289 | }; 290 | 291 | exports.CallStoredProcedureSelectNested = function (test) { 292 | test.expect(8); 293 | 294 | var 295 | conn = cfg.mysql_libmysqlclient.createConnectionSync(), 296 | res, 297 | num = 1234, 298 | numFromProcedure; 299 | 300 | conn.connectSync(cfg.host, cfg.user, cfg.password, cfg.database, null, null, cfg.mysql_libmysqlclient.CLIENT_MULTI_RESULTS); 301 | 302 | res = conn.querySync("DROP PROCEDURE IF EXISTS test_procedure;"); 303 | test.strictEqual(res, true); 304 | 305 | res = conn.querySync("CREATE PROCEDURE test_procedure() SELECT " + num + " AS num;"); 306 | test.strictEqual(res, true); 307 | 308 | conn.query("CALL test_procedure();", function (err, res) { 309 | test.ok(err === null, "Error object is not present"); 310 | test.ok(res instanceof cfg.mysql_bindings.MysqlResult, "res instanceof MysqlResult"); 311 | 312 | numFromProcedure = res.fetchAllSync()[0].num; 313 | res.freeSync(); 314 | 315 | test.equals(numFromProcedure, num, "numFromProcedure == num"); 316 | 317 | // We need to get second result from set, that contains execution status 318 | while (conn.multiMoreResultsSync()) { 319 | // Go to next result in set 320 | conn.multiNextResultSync(); 321 | // Store result 322 | res = conn.storeResultSync(); 323 | if (typeof res.freeSync === 'function') { 324 | // Free result if it is not simple true/false 325 | res.freeSync(); 326 | } 327 | } 328 | 329 | conn.query("CALL test_procedure();", function (err, res) { 330 | test.ok(err === null, "Error object is not present"); 331 | test.ok(res instanceof cfg.mysql_bindings.MysqlResult, "res instanceof MysqlResult"); 332 | 333 | numFromProcedure = res.fetchAllSync()[0].num; 334 | res.freeSync(); 335 | 336 | test.equals(numFromProcedure, num, "numFromProcedure == num"); 337 | 338 | // We need to get second result from set, that contains execution status 339 | while (conn.multiMoreResultsSync()) { 340 | // Go to next result in set 341 | conn.multiNextResultSync(); 342 | // Store result 343 | res = conn.storeResultSync(); 344 | if (typeof res.freeSync === 'function') { 345 | // Free result if it is not simple true/false 346 | res.freeSync(); 347 | } 348 | } 349 | 350 | conn.closeSync(); 351 | test.done(); 352 | }); 353 | }); 354 | }; 355 | -------------------------------------------------------------------------------- /tests/complex/test-datatypes-cast.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright by Oleg Efimov and node-mysql-libmysqlclient contributors 3 | See contributors list in README 4 | 5 | See license text in LICENSE file 6 | */ 7 | 8 | // Load configuration 9 | var cfg = require('../config'); 10 | 11 | exports.fetchDateAndTimeValues = function (test) { 12 | test.expect(16); 13 | 14 | var 15 | conn = cfg.mysql_libmysqlclient.createConnectionSync(cfg.host, cfg.user, cfg.password, cfg.database), 16 | rows; 17 | 18 | rows = conn.querySync("SELECT CAST('2 2:50' AS TIME) as time;").fetchAllSync(); 19 | test.ok(rows[0].time instanceof Date, "SELECT CAST('2 2:50' AS TIME) is Date"); 20 | test.equals(rows[0].time.toUTCString(), "Sat, 03 Jan 1970 02:50:00 GMT", "SELECT CAST('2 2:50' AS TIME) is correct"); 21 | 22 | rows = conn.querySync("SELECT CAST('2000-01-01' AS DATE) as date;").fetchAllSync(); 23 | test.ok(rows[0].date instanceof Date, "SELECT CAST('2000-01-01' AS DATE) is Date"); 24 | test.equals(rows[0].date.toUTCString(), "Sat, 01 Jan 2000 00:00:00 GMT", "SELECT CAST('2000-01-01' AS DATE) is correct"); 25 | 26 | rows = conn.querySync("SELECT CAST('1988-10-25 06:34' AS DATETIME) as datetime;").fetchAllSync(); 27 | test.ok(rows[0].datetime instanceof Date, "SELECT CAST('1988-10-25 06:34' AS DATETIME) is Date"); 28 | test.equals(rows[0].datetime.toUTCString(), "Tue, 25 Oct 1988 06:34:00 GMT", "SELECT CAST('1988-10-25 06:34' AS DATETIME) is correct"); 29 | 30 | rows = conn.querySync("SELECT CAST('1988-10-25' AS DATETIME) as datetime;").fetchAllSync(); 31 | test.ok(rows[0].datetime instanceof Date, "SELECT CAST('1988-10-25' AS DATETIME) is Date"); 32 | test.equals(rows[0].datetime.toUTCString(), "Tue, 25 Oct 1988 00:00:00 GMT", "SELECT CAST('1988-10-25' AS DATETIME) is correct"); 33 | 34 | rows = conn.querySync("SELECT CAST('1988-10-25 2:50' AS DATETIME) as datetime;").fetchAllSync(); 35 | test.ok(rows[0].datetime instanceof Date, "SELECT CAST('1988-10-25 2:50' AS DATETIME) is Date"); 36 | test.equals(rows[0].datetime.toUTCString(), "Tue, 25 Oct 1988 02:50:00 GMT", "SELECT CAST('1988-10-25 2:50' AS TIME) is correct"); 37 | 38 | rows = conn.querySync("SELECT CAST('1988-10-25 3:50' AS DATETIME) as datetime;").fetchAllSync(); 39 | test.ok(rows[0].datetime instanceof Date, "SELECT CAST('1988-10-25 3:50' AS DATETIME) is Date"); 40 | test.equals(rows[0].datetime.toUTCString(), "Tue, 25 Oct 1988 03:50:00 GMT", "SELECT CAST('1988-10-25 3:50' AS TIME) is correct"); 41 | 42 | rows = conn.querySync("SELECT CAST('1988-10-25 23:50' AS DATETIME) as datetime;").fetchAllSync(); 43 | test.ok(rows[0].datetime instanceof Date, "SELECT CAST('1988-10-25 23:50' AS DATETIME) is Date"); 44 | test.equals(rows[0].datetime.toUTCString(), "Tue, 25 Oct 1988 23:50:00 GMT", "SELECT CAST('1988-10-25 23:50' AS TIME) is correct"); 45 | 46 | rows = conn.querySync("SELECT CAST('1988-10-25 18:50' AS DATETIME) as datetime;").fetchAllSync(); 47 | test.ok(rows[0].datetime instanceof Date, "SELECT CAST('1988-10-25 18:50' AS DATETIME) is Date"); 48 | test.equals(rows[0].datetime.toUTCString(), "Tue, 25 Oct 1988 18:50:00 GMT", "SELECT CAST('1988-10-25 18:50' AS TIME) is correct"); 49 | 50 | conn.closeSync(); 51 | 52 | test.done(); 53 | }; 54 | 55 | exports.fetchSetValues = function (test) { 56 | test.expect(4); 57 | 58 | var 59 | conn = cfg.mysql_libmysqlclient.createConnectionSync(cfg.host, cfg.user, cfg.password, cfg.database), 60 | rows; 61 | 62 | rows = conn.querySync("SELECT size, colors FROM " + cfg.test_table + " WHERE size='small';").fetchAllSync(); 63 | test.ok(rows[0].colors instanceof Array, "SET fetched result is Array"); 64 | test.same(rows[0].colors, ['red'], "SET fetched result is correct"); 65 | 66 | rows = conn.querySync("SELECT size, colors FROM " + cfg.test_table + " WHERE size='medium';").fetchAllSync(); 67 | test.ok(rows[0].colors instanceof Array, "SET fetched result is Array"); 68 | test.same(rows[0].colors, ['red', 'green', 'blue'], "SET fetched result is correct"); 69 | 70 | conn.closeSync(); 71 | 72 | test.done(); 73 | }; 74 | 75 | -------------------------------------------------------------------------------- /tests/complex/test-fetch-options.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright by Oleg Efimov and node-mysql-libmysqlclient contributors 3 | See contributors list in README 4 | 5 | See license text in LICENSE file 6 | */ 7 | 8 | // Load configuration 9 | var cfg = require('../config'); 10 | 11 | exports.createTestTableComplex2 = function (test) { 12 | test.expect(3); 13 | 14 | var 15 | conn = cfg.mysql_libmysqlclient.createConnectionSync(cfg.host, cfg.user, cfg.password, cfg.database), 16 | res, 17 | tables; 18 | 19 | conn.querySync("DROP TABLE IF EXISTS " + cfg.test_table2 + ";"); 20 | conn.querySync("CREATE TABLE " + cfg.test_table2 + 21 | " (size ENUM('small', 'medium', 'large')," + 22 | " colors VARCHAR(32)) " + cfg.store_engine + ";"); 23 | res = conn.querySync("SHOW TABLES"); 24 | tables = res.fetchAllSync(); 25 | 26 | test.ok(res.fieldCount === 1, "SHOW TABLES result field count === 1"); 27 | test.ok(tables.some(function (r) { 28 | return r['Tables_in_' + cfg.database] === cfg.test_table2; 29 | }), "Find the test_table2 in results"); 30 | 31 | res = conn.querySync("INSERT INTO " + cfg.test_table2 + 32 | " (size, colors) VALUES ('small', 'red');"); 33 | res = conn.querySync("INSERT INTO " + cfg.test_table2 + 34 | " (size, colors) VALUES ('small', 'orange');") && res; 35 | res = conn.querySync("INSERT INTO " + cfg.test_table2 + 36 | " (size, colors) VALUES ('medium', 'black');") && res; 37 | res = conn.querySync("INSERT INTO " + cfg.test_table2 + 38 | " (size, colors) VALUES ('large', 'deep purple');") && res; 39 | test.ok(res, "conn.querySync('INSERT INTO test_table2 ...')"); 40 | 41 | conn.closeSync(); 42 | test.done(); 43 | }; 44 | 45 | exports.FetchAllFailsWithBooleanOption = function (test) { 46 | test.expect(2); 47 | 48 | var 49 | conn = cfg.mysql_libmysqlclient.createConnectionSync(cfg.host, cfg.user, cfg.password, cfg.database), 50 | res; 51 | 52 | res = conn.querySync("SELECT size, colors FROM " + cfg.test_table + " WHERE size='small';"); 53 | 54 | res.fetchAll(false, function (err, rows) { 55 | test.ok(err instanceof Error, "Error object is presented"); 56 | test.ok(typeof rows === 'undefined'); 57 | 58 | conn.closeSync(); 59 | test.done(); 60 | }); 61 | }; 62 | 63 | exports.FetchAllSyncFailsWithBooleanOption = function (test) { 64 | test.expect(1); 65 | 66 | var 67 | conn = cfg.mysql_libmysqlclient.createConnectionSync(cfg.host, cfg.user, cfg.password, cfg.database), 68 | res, 69 | rows; 70 | 71 | res = conn.querySync("SELECT size, colors FROM " + cfg.test_table + " WHERE size='small';"); 72 | 73 | test.throws(function () { 74 | rows = res.fetchAllSync(false); 75 | }); 76 | res.freeSync(); 77 | 78 | conn.closeSync(); 79 | test.done(); 80 | }; 81 | 82 | exports.FetchAll_asArray = function (test) { 83 | test.expect(8); 84 | 85 | var 86 | conn = cfg.mysql_libmysqlclient.createConnectionSync(cfg.host, cfg.user, cfg.password, cfg.database), 87 | res; 88 | 89 | res = conn.querySync("SELECT size, colors FROM " + cfg.test_table + " WHERE size='small';"); 90 | test.ok(res instanceof cfg.mysql_bindings.MysqlResult); 91 | 92 | res.fetchAll({'asArray': false}, function (err, rows) { 93 | test.ok(err === null, "Error object is not present"); 94 | test.same(rows, [{size: 'small', colors: ['red']}], "conn.querySync('SELECT ...').fetchAllSync({'asArray': false})"); 95 | res.freeSync(); 96 | 97 | res = conn.querySync("SELECT size, colors FROM " + cfg.test_table + " WHERE size='small';"); 98 | test.ok(res instanceof cfg.mysql_bindings.MysqlResult, "res instanceof MysqlResult"); 99 | 100 | res.fetchAll({'asArray': true}, function (err, rows) { 101 | test.ok(err === null, "Error object is not present"); 102 | 103 | test.ok(Array.isArray(rows), "Result returns an array"); 104 | test.ok(Array.isArray(rows[0]), "Result returns an array of arrays"); 105 | 106 | test.same(rows, [['small', ['red']]], "conn.querySync('SELECT ...').fetchAll({'asArray': true})"); 107 | res.freeSync(); 108 | 109 | conn.closeSync(); 110 | test.done(); 111 | }); 112 | }); 113 | }; 114 | 115 | exports.FetchAllSync_asArray = function (test) { 116 | test.expect(6); 117 | 118 | var 119 | conn = cfg.mysql_libmysqlclient.createConnectionSync(cfg.host, cfg.user, cfg.password, cfg.database), 120 | res, 121 | rows; 122 | 123 | res = conn.querySync("SELECT size, colors FROM " + cfg.test_table + " WHERE size='small';"); 124 | test.ok(res instanceof cfg.mysql_bindings.MysqlResult); 125 | 126 | rows = res.fetchAllSync({'asArray': false}); 127 | test.same(rows, [{size: 'small', colors: ['red']}], "conn.querySync('SELECT ...').fetchAllSync({'asArray': false})"); 128 | res.freeSync(); 129 | 130 | res = conn.querySync("SELECT size, colors FROM " + cfg.test_table + " WHERE size='small';"); 131 | test.ok(res instanceof cfg.mysql_bindings.MysqlResult); 132 | 133 | rows = res.fetchAllSync({'asArray': true}); 134 | test.ok(Array.isArray(rows), "Result returns an array"); 135 | test.ok(Array.isArray(rows[0]), "Result returns an array of arrays"); 136 | test.same(rows, [['small', ['red']]], "conn.querySync('SELECT ...').fetchAllSync({'asArray': true})"); 137 | res.freeSync(); 138 | 139 | conn.closeSync(); 140 | test.done(); 141 | }; 142 | 143 | exports.FetchAll_nestTables = function (test) { 144 | test.expect(8); 145 | 146 | var 147 | conn = cfg.mysql_libmysqlclient.createConnectionSync(cfg.host, cfg.user, cfg.password, cfg.database), 148 | res; 149 | 150 | res = conn.querySync("SELECT t1.size, t1.colors, t2.size, t2.colors " + 151 | "FROM " + cfg.test_table + " t1, " + cfg.test_table2 + " t2 " + 152 | "WHERE t1.size = t2.size AND t1.size != 'medium';"); 153 | test.ok(res instanceof cfg.mysql_bindings.MysqlResult, "res instanceof MysqlResult"); 154 | 155 | res.fetchAll({'nestTables': false}, function (err, rows) { 156 | test.ok(err === null, "Error object is not present"); 157 | 158 | test.same(rows, 159 | [{size: 'small', colors: 'red'}, 160 | {size: 'small', colors: 'orange'}, 161 | {size: 'large', colors: 'deep purple'}, 162 | {size: 'large', colors: 'deep purple'} 163 | ], "conn.querySync('SELECT ...').fetchAllSync({'nestTables': false})"); 164 | res.freeSync(); 165 | 166 | res = conn.querySync("SELECT t1.size, t1.colors, t2.size, t2.colors " + 167 | "FROM " + cfg.test_table + " t1, " + cfg.test_table2 + " t2 " + 168 | "WHERE t1.size = t2.size AND t1.size != 'medium' AND t1.colors != 'green';"); 169 | test.ok(res instanceof cfg.mysql_bindings.MysqlResult, "res instanceof MysqlResult"); 170 | 171 | res.fetchAll({'nestTables': true}, function (err, rows) { 172 | test.ok(err === null, "Error object is not present"); 173 | 174 | test.ok(Array.isArray(rows), "Result returns an array"); 175 | test.ok(rows[0] instanceof Object, "Result returns an array of objects"); 176 | test.same(rows, 177 | [{t1: {size: 'small', colors: ['red']}, 178 | t2: {size: 'small', colors: 'red'} 179 | }, 180 | {t1: { size: 'small', colors: ['red']}, 181 | t2: { size: 'small', colors: 'orange'} 182 | }, 183 | {t1: { size: 'large', colors: ['red', 'blue'] }, 184 | t2: { size: 'large', colors: 'deep purple' } 185 | } 186 | ], "conn.querySync('SELECT ...').fetchAll({'nestTables': true})"); 187 | res.freeSync(); 188 | 189 | conn.closeSync(); 190 | test.done(); 191 | }); 192 | }); 193 | }; 194 | 195 | exports.FetchAllSync_nestTables = function (test) { 196 | test.expect(6); 197 | 198 | var 199 | conn = cfg.mysql_libmysqlclient.createConnectionSync(cfg.host, cfg.user, cfg.password, cfg.database), 200 | res, 201 | rows; 202 | 203 | res = conn.querySync("SELECT t1.size, t1.colors, t2.size, t2.colors " + 204 | "FROM " + cfg.test_table + " t1, " + cfg.test_table2 + " t2 " + 205 | "WHERE t1.size = t2.size AND t1.size != 'medium';"); 206 | test.ok(res instanceof cfg.mysql_bindings.MysqlResult); 207 | 208 | rows = res.fetchAllSync({'nestTables': false}); 209 | test.same(rows, 210 | [{size: 'small', colors: 'red'}, 211 | {size: 'small', colors: 'orange'}, 212 | {size: 'large', colors: 'deep purple'}, 213 | {size: 'large', colors: 'deep purple'} 214 | ], "conn.querySync('SELECT ...').fetchAllSync({'nestTables': false})"); 215 | res.freeSync(); 216 | 217 | res = conn.querySync("SELECT t1.size, t1.colors, t2.size, t2.colors " + 218 | "FROM " + cfg.test_table + " t1, " + cfg.test_table2 + " t2 " + 219 | "WHERE t1.size = t2.size AND t1.size != 'medium' AND t1.colors != 'green';"); 220 | test.ok(res instanceof cfg.mysql_bindings.MysqlResult); 221 | 222 | rows = res.fetchAllSync({'nestTables': true}); 223 | test.ok(Array.isArray(rows), "Result returns an array"); 224 | test.ok(rows[0] instanceof Object, "Result returns an array of objects"); 225 | test.same(rows, 226 | [{t1: { size: 'small', colors: ['red']}, 227 | t2: { size: 'small', colors: 'red'} 228 | }, 229 | {t1: { size: 'small', colors: ['red']}, 230 | t2: { size: 'small', colors: 'orange'} 231 | }, 232 | {t1: { size: 'large', colors: ['red', 'blue']}, 233 | t2: { size: 'large', colors: 'deep purple'} 234 | } 235 | ], "conn.querySync('SELECT ...').fetchAllSync({'nestTables': true})"); 236 | res.freeSync(); 237 | 238 | conn.closeSync(); 239 | test.done(); 240 | }; 241 | 242 | exports.FetchAllWithObjectOptionsConflicted = function (test) { 243 | test.expect(2); 244 | 245 | var 246 | conn = cfg.mysql_libmysqlclient.createConnectionSync(cfg.host, cfg.user, cfg.password, cfg.database), 247 | res; 248 | 249 | res = conn.querySync("SELECT t1.size, t1.colors, t2.size, t2.colors " + 250 | "FROM " + cfg.test_table + " t1, " + cfg.test_table2 + " t2 " + 251 | "WHERE t1.size = t2.size AND t1.size != 'medium';"); 252 | test.ok(res instanceof cfg.mysql_bindings.MysqlResult); 253 | 254 | test.throws(function () { 255 | res.fetchAll({'asArray': true, 'nestTables': true}, function (err, rows) {}); 256 | }, Error, "You can't mix 'asArray' and 'nestTables' parameters"); 257 | 258 | res.freeSync(); 259 | 260 | conn.closeSync(); 261 | test.done(); 262 | }; 263 | 264 | exports.FetchAllSyncWithObjectOptionsConflicted = function (test) { 265 | test.expect(2); 266 | 267 | var 268 | conn = cfg.mysql_libmysqlclient.createConnectionSync(cfg.host, cfg.user, cfg.password, cfg.database), 269 | res, 270 | rows; 271 | 272 | res = conn.querySync("SELECT t1.size, t1.colors, t2.size, t2.colors " + 273 | "FROM " + cfg.test_table + " t1, " + cfg.test_table2 + " t2 " + 274 | "WHERE t1.size = t2.size AND t1.size != 'medium';"); 275 | test.ok(res instanceof cfg.mysql_bindings.MysqlResult); 276 | 277 | test.throws(function () { 278 | rows = res.fetchAllSync({'asArray': true, 'nestTables': true}); 279 | }, Error, "You can't mix 'asArray' and 'nestTables' parameters"); 280 | 281 | res.freeSync(); 282 | 283 | conn.closeSync(); 284 | test.done(); 285 | }; 286 | 287 | exports.setOptionSyncQueryFetchAll = function (test) { 288 | test.expect(5); 289 | 290 | var conn = cfg.mysql_libmysqlclient.createConnectionSync(); 291 | 292 | conn.initSync(); 293 | conn.setOptionSync(cfg.mysql_libmysqlclient.MYSQL_OPT_RECONNECT, 1); 294 | conn.setOptionSync(cfg.mysql_libmysqlclient.MYSQL_SET_CHARSET_NAME, "utf8"); 295 | conn.realConnectSync(cfg.host, cfg.user, cfg.password, cfg.database); 296 | 297 | conn.query("SELECT size, colors FROM " + cfg.test_table + " WHERE size;", function (err, res) { 298 | test.ok(err === null, "Error object is not present"); 299 | test.ok(res instanceof cfg.mysql_bindings.MysqlResult, "res instanceof MysqlResult"); 300 | 301 | res.fetchAll(function (err, rows, fields) { 302 | test.ok(err === null, "Error object is not present"); 303 | 304 | test.same(rows, 305 | [{size: 'small', colors: ['red']}, 306 | {size: 'medium', colors: ['red', 'green', 'blue']}, 307 | {size: 'large', colors: ['green']}, 308 | {size: 'large', colors: ['red', 'blue']}], 309 | "conn.querySync('SELECT ...').fetchAll()"); 310 | test.same(fields, res.fetchFieldsSync(), "Callback fields argument == res.fetchFieldsSync()"); 311 | 312 | res.freeSync(); 313 | conn.closeSync(); 314 | 315 | test.done(); 316 | }); 317 | }); 318 | }; 319 | 320 | -------------------------------------------------------------------------------- /tests/config.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright by Oleg Efimov and node-mysql-libmysqlclient contributors 3 | See contributors list in README 4 | 5 | See license text in LICENSE file 6 | */ 7 | 8 | /* 9 | #See before_script commands in .travis.yml for actual version of this commends 10 | > mysql -u root 11 | DELETE FROM mysql.db WHERE Db = 'test\\_%'; 12 | DELETE FROM mysql.user WHERE Host = 'localhost' AND User = ''; 13 | FLUSH PRIVILEGES; 14 | CREATE DATABASE test_allowed DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci; 15 | GRANT ALL ON test_allowed.* TO test_user@localhost IDENTIFIED BY '1234'; 16 | CREATE DATABASE IF NOT EXISTS test_denied DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci; 17 | */ 18 | 19 | module.exports = { 20 | // Required modules 21 | mysql_libmysqlclient: require("../lib/mysql-libmysqlclient.js"), 22 | mysql_bindings: require("../lib/mysql-libmysqlclient.js").bindings, 23 | util: require("util"), 24 | 25 | // Database connection settings 26 | host: "localhost", 27 | port: 3306, 28 | user: "test_user", 29 | password: "1234", 30 | database: "test_allowed", 31 | database_denied: "test_denied", 32 | test_table: "test_table", 33 | test_table2: "test_table2", 34 | test_table_notexists: "test_table_notexists", 35 | charset: "utf8", 36 | store_engine: "ENGINE=MyISAM", 37 | 38 | // Operations count for continuous tests 39 | reconnect_count: 10000, 40 | insert_rows_count: 10000, 41 | 42 | // Operations count for slow tests 43 | slow_connects_nested: 10000, 44 | slow_connects_inloop: 100, 45 | slow_inserts_count: 10000, 46 | slow_fetches_nested: 10000, 47 | slow_fetches_inloop: 10000, 48 | 49 | // Pause before checks, to ensure MySQL inserts/update completed 50 | delay: 500 51 | }; 52 | -------------------------------------------------------------------------------- /tests/high-level/test-class-mysqlconnectionhighlevel.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright by Oleg Efimov and node-mysql-libmysqlclient contributors 3 | See contributors list in README 4 | 5 | See license text in LICENSE file 6 | */ 7 | 8 | // Load configuration 9 | var cfg = require('../config'); 10 | 11 | exports.Setup = function (test) { 12 | test.expect(0); 13 | 14 | var conn = cfg.mysql_libmysqlclient.createConnectionSync(cfg.host, cfg.user, cfg.password, cfg.database); 15 | 16 | conn.querySync("DROP TABLE IF EXISTS " + cfg.test_table + ";"); 17 | conn.querySync("CREATE TABLE " + cfg.test_table + " (number INT(8) NOT NULL) ENGINE=MEMORY;"); 18 | 19 | conn.closeSync(); 20 | 21 | test.done(); 22 | }; 23 | 24 | exports.New = function (test) { 25 | test.expect(1); 26 | 27 | test.doesNotThrow(function () { 28 | (new cfg.mysql_libmysqlclient.MysqlConnectionHighlevel()); 29 | }); 30 | 31 | test.done(); 32 | }; 33 | 34 | exports.ConnectWithCallback = function (test) { 35 | test.expect(2); 36 | 37 | var conn = cfg.mysql_libmysqlclient.createConnectionHighlevelSync(); 38 | 39 | conn.connect(cfg.host, cfg.user, cfg.password, cfg.database, function (err) { 40 | test.ok(err === null, "Error object is not present"); 41 | 42 | test.ok(arguments.length <= 1, "Only error arguments is possible."); 43 | 44 | test.done(); 45 | }); 46 | }; 47 | 48 | exports.ConnectWithQueryInCallback = function (test) { 49 | test.expect(1); 50 | 51 | var conn = cfg.mysql_libmysqlclient.createConnectionHighlevelSync(); 52 | 53 | conn.connect(cfg.host, cfg.user, cfg.password, cfg.database, function () { 54 | conn.query("SELECT 1;", function (err, res) { 55 | if (err) { 56 | throw err; 57 | } 58 | 59 | test.ok(res instanceof cfg.mysql_bindings.MysqlResult); 60 | 61 | test.done(); 62 | }); 63 | }); 64 | }; 65 | 66 | exports.ConnectWithoutCallbackAndThenQueryWithCallback = function (test) { 67 | test.expect(1); 68 | 69 | var conn = cfg.mysql_libmysqlclient.createConnectionHighlevelSync(); 70 | 71 | conn.connect(cfg.host, cfg.user, cfg.password, cfg.database); 72 | 73 | conn.query("SELECT 1;", function (err, res) { 74 | if (err) { 75 | throw err; 76 | } 77 | 78 | test.ok(res instanceof cfg.mysql_bindings.MysqlResult); 79 | 80 | test.done(); 81 | }); 82 | }; 83 | 84 | exports.ConnectWithoutCallbackAndThenTwoQueriesWithCallbacks = function (test) { 85 | test.expect(2); 86 | 87 | var conn = cfg.mysql_libmysqlclient.createConnectionHighlevelSync(); 88 | 89 | conn.connect(cfg.host, cfg.user, cfg.password, cfg.database); 90 | 91 | conn.query("SELECT 1;", function (err, res) { 92 | if (err) { 93 | throw err; 94 | } 95 | 96 | test.ok(res instanceof cfg.mysql_bindings.MysqlResult); 97 | }); 98 | 99 | conn.query("SELECT 2;", function (err, res) { 100 | if (err) { 101 | throw err; 102 | } 103 | 104 | test.ok(res instanceof cfg.mysql_bindings.MysqlResult); 105 | 106 | test.done(); 107 | }); 108 | }; 109 | 110 | exports.QueryParallel = function (test) { 111 | test.expect(4); 112 | 113 | var 114 | conn = cfg.mysql_libmysqlclient.createConnectionHighlevelSync(cfg.host, cfg.user, cfg.password, cfg.database), 115 | i = 0; 116 | 117 | conn.query("SELECT 1;", function (err, res) { 118 | if (err) { 119 | throw err; 120 | } 121 | 122 | test.ok(res instanceof cfg.mysql_bindings.MysqlResult); 123 | 124 | i++; 125 | 126 | if (i == 4) { 127 | test.done(); 128 | } 129 | }); 130 | 131 | conn.query("SELECT 2;", function (err, res) { 132 | if (err) { 133 | throw err; 134 | } 135 | 136 | test.ok(res instanceof cfg.mysql_bindings.MysqlResult); 137 | 138 | i++; 139 | 140 | if (i == 4) { 141 | test.done(); 142 | } 143 | }); 144 | 145 | conn.query("SELECT 3;", function (err, res) { 146 | if (err) { 147 | throw err; 148 | } 149 | 150 | test.ok(res instanceof cfg.mysql_bindings.MysqlResult); 151 | 152 | i++; 153 | 154 | if (i == 4) { 155 | test.done(); 156 | } 157 | }); 158 | 159 | conn.query("SELECT 4;", function (err, res) { 160 | if (err) { 161 | throw err; 162 | } 163 | 164 | test.ok(res instanceof cfg.mysql_bindings.MysqlResult); 165 | 166 | i++; 167 | 168 | if (i == 4) { 169 | test.done(); 170 | } 171 | }); 172 | }; 173 | 174 | exports.QueryParallelWithSetQueryType = function (test) { 175 | test.expect(6); 176 | 177 | var 178 | conn = cfg.mysql_libmysqlclient.createConnectionHighlevelSync(cfg.host, cfg.user, cfg.password, cfg.database), 179 | i = 0; 180 | 181 | conn.query("SELECT 1;", function (err, res) { 182 | if (err) { 183 | throw err; 184 | } 185 | 186 | test.ok(res instanceof cfg.mysql_bindings.MysqlResult); 187 | 188 | i++; 189 | 190 | if (i == 6) { 191 | test.done(); 192 | } 193 | }); 194 | 195 | conn.setQueryTypeSync('query'); 196 | 197 | conn.query("SELECT 2;", function (err, res) { 198 | if (err) { 199 | throw err; 200 | } 201 | 202 | test.ok(res instanceof cfg.mysql_bindings.MysqlResult); 203 | 204 | i++; 205 | 206 | if (i == 6) { 207 | test.done(); 208 | } 209 | }); 210 | 211 | conn.setQueryTypeSync('querySend'); 212 | 213 | conn.query("SELECT 3;", function (err, res) { 214 | if (err) { 215 | throw err; 216 | } 217 | 218 | test.ok(res instanceof cfg.mysql_bindings.MysqlResult); 219 | 220 | i++; 221 | 222 | if (i == 6) { 223 | test.done(); 224 | } 225 | }); 226 | 227 | conn.setQueryTypeSync('query'); 228 | 229 | conn.query("SELECT 4;", function (err, res) { 230 | if (err) { 231 | throw err; 232 | } 233 | 234 | test.ok(res instanceof cfg.mysql_bindings.MysqlResult); 235 | 236 | i++; 237 | 238 | if (i == 6) { 239 | test.done(); 240 | } 241 | }); 242 | 243 | conn.setQueryTypeSync('querySend'); 244 | 245 | conn.query("SELECT 5;", function (err, res) { 246 | if (err) { 247 | throw err; 248 | } 249 | 250 | test.ok(res instanceof cfg.mysql_bindings.MysqlResult); 251 | 252 | i++; 253 | 254 | if (i == 6) { 255 | test.done(); 256 | } 257 | }); 258 | 259 | conn.setQueryTypeSync('query'); 260 | 261 | conn.query("SELECT 6;", function (err, res) { 262 | if (err) { 263 | throw err; 264 | } 265 | 266 | test.ok(res instanceof cfg.mysql_bindings.MysqlResult); 267 | 268 | i++; 269 | 270 | if (i == 6) { 271 | test.done(); 272 | } 273 | }); 274 | }; 275 | -------------------------------------------------------------------------------- /tests/high-level/test-class-mysqlconnectionqueued.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright by Oleg Efimov and node-mysql-libmysqlclient contributors 3 | See contributors list in README 4 | 5 | See license text in LICENSE file 6 | */ 7 | 8 | // Load configuration 9 | var cfg = require('../config'); 10 | 11 | exports.Setup = function (test) { 12 | test.expect(0); 13 | 14 | var conn = cfg.mysql_libmysqlclient.createConnectionSync(cfg.host, cfg.user, cfg.password, cfg.database); 15 | 16 | conn.querySync("DROP TABLE IF EXISTS " + cfg.test_table + ";"); 17 | conn.querySync("CREATE TABLE " + cfg.test_table + " (number INT(8) NOT NULL) ENGINE=MEMORY;"); 18 | 19 | conn.closeSync(); 20 | 21 | test.done(); 22 | }; 23 | 24 | exports.New = function (test) { 25 | test.expect(1); 26 | 27 | test.doesNotThrow(function () { 28 | (new cfg.mysql_libmysqlclient.MysqlConnectionQueued()); 29 | }); 30 | 31 | test.done(); 32 | }; 33 | 34 | exports.ConnectWithCallback = function (test) { 35 | test.expect(2); 36 | 37 | var conn = cfg.mysql_libmysqlclient.createConnectionQueuedSync(); 38 | 39 | conn.connect(cfg.host, cfg.user, cfg.password, cfg.database, function (err) { 40 | test.ok(err === null, "Error object is not present"); 41 | 42 | test.ok(arguments.length <= 1, "Only error arguments is possible."); 43 | 44 | test.done(); 45 | }); 46 | }; 47 | 48 | exports.ConnectWithQueryInCallback = function (test) { 49 | test.expect(1); 50 | 51 | var conn = cfg.mysql_libmysqlclient.createConnectionQueuedSync(); 52 | 53 | conn.connect(cfg.host, cfg.user, cfg.password, cfg.database, function () { 54 | conn.query("SELECT 1;", function (err, res) { 55 | if (err) { 56 | throw err; 57 | } 58 | 59 | test.ok(res instanceof cfg.mysql_bindings.MysqlResult); 60 | 61 | test.done(); 62 | }); 63 | }); 64 | }; 65 | 66 | exports.ConnectWithoutCallbackAndThenQueryWithCallback = function (test) { 67 | test.expect(1); 68 | 69 | var conn = cfg.mysql_libmysqlclient.createConnectionQueuedSync(); 70 | 71 | conn.connect(cfg.host, cfg.user, cfg.password, cfg.database); 72 | 73 | conn.query("SELECT 1;", function (err, res) { 74 | if (err) { 75 | throw err; 76 | } 77 | 78 | test.ok(res instanceof cfg.mysql_bindings.MysqlResult); 79 | 80 | test.done(); 81 | }); 82 | }; 83 | 84 | exports.ConnectWithoutCallbackAndThenTwoQueriesWithCallbacks = function (test) { 85 | test.expect(2); 86 | 87 | var conn = cfg.mysql_libmysqlclient.createConnectionQueuedSync(); 88 | 89 | conn.connect(cfg.host, cfg.user, cfg.password, cfg.database); 90 | 91 | conn.query("SELECT 1;", function (err, res) { 92 | if (err) { 93 | throw err; 94 | } 95 | 96 | test.ok(res instanceof cfg.mysql_bindings.MysqlResult); 97 | }); 98 | 99 | conn.query("SELECT 2;", function (err, res) { 100 | if (err) { 101 | throw err; 102 | } 103 | 104 | test.ok(res instanceof cfg.mysql_bindings.MysqlResult); 105 | 106 | test.done(); 107 | }); 108 | }; 109 | 110 | exports.ConnectWithoutCallbackAndThenQueryWithoutCallbackAndThenQueryWithCallback = function (test) { 111 | test.expect(1); 112 | 113 | var conn = cfg.mysql_libmysqlclient.createConnectionQueuedSync(); 114 | 115 | conn.connect(cfg.host, cfg.user, cfg.password, cfg.database); 116 | 117 | conn.query("INSERT INTO " + cfg.test_table + " VALUES (NULL);"); 118 | 119 | conn.query("SELECT 2;", function (err, res) { 120 | if (err) { 121 | throw err; 122 | } 123 | 124 | test.ok(res instanceof cfg.mysql_bindings.MysqlResult); 125 | 126 | test.done(); 127 | }); 128 | }; 129 | 130 | exports.QueryParallel = function (test) { 131 | test.expect(2); 132 | 133 | var 134 | conn = cfg.mysql_libmysqlclient.createConnectionQueuedSync(cfg.host, cfg.user, cfg.password, cfg.database), 135 | i = 0; 136 | 137 | conn.query("SELECT 1;", function (err, res) { 138 | if (err) { 139 | throw err; 140 | } 141 | 142 | test.ok(res instanceof cfg.mysql_bindings.MysqlResult); 143 | 144 | i++; 145 | 146 | if (i == 2) { 147 | test.done(); 148 | } 149 | }); 150 | 151 | conn.query("SELECT 2;", function (err, res) { 152 | if (err) { 153 | throw err; 154 | } 155 | 156 | test.ok(res instanceof cfg.mysql_bindings.MysqlResult); 157 | 158 | i++; 159 | 160 | if (i == 2) { 161 | test.done(); 162 | } 163 | }); 164 | }; 165 | 166 | exports.QuerySendParallel = function (test) { 167 | test.expect(2); 168 | 169 | var 170 | conn = cfg.mysql_libmysqlclient.createConnectionQueuedSync(cfg.host, cfg.user, cfg.password, cfg.database), 171 | i = 0; 172 | 173 | conn.querySend("SELECT 1;", function (err, res) { 174 | if (err) { 175 | throw err; 176 | } 177 | 178 | test.ok(res instanceof cfg.mysql_bindings.MysqlResult); 179 | 180 | i++; 181 | 182 | if (i == 2) { 183 | test.done(); 184 | } 185 | }); 186 | 187 | conn.querySend("SELECT 2;", function (err, res) { 188 | if (err) { 189 | throw err; 190 | } 191 | 192 | test.ok(res instanceof cfg.mysql_bindings.MysqlResult); 193 | 194 | i++; 195 | 196 | if (i == 2) { 197 | test.done(); 198 | } 199 | }); 200 | }; 201 | 202 | exports.QueryAndQuerySendParallel = function (test) { 203 | test.expect(4); 204 | 205 | var 206 | conn = cfg.mysql_libmysqlclient.createConnectionQueuedSync(cfg.host, cfg.user, cfg.password, cfg.database), 207 | i = 0; 208 | 209 | conn.query("SELECT 1;", function (err, res) { 210 | if (err) { 211 | throw err; 212 | } 213 | 214 | test.ok(res instanceof cfg.mysql_bindings.MysqlResult); 215 | 216 | i++; 217 | 218 | if (i == 4) { 219 | test.done(); 220 | } 221 | }); 222 | 223 | conn.querySend("SELECT 2;", function (err, res) { 224 | if (err) { 225 | throw err; 226 | } 227 | 228 | test.ok(res instanceof cfg.mysql_bindings.MysqlResult); 229 | 230 | i++; 231 | 232 | if (i == 4) { 233 | test.done(); 234 | } 235 | }); 236 | 237 | conn.query("SELECT 3;", function (err, res) { 238 | if (err) { 239 | throw err; 240 | } 241 | 242 | test.ok(res instanceof cfg.mysql_bindings.MysqlResult); 243 | 244 | i++; 245 | 246 | if (i == 4) { 247 | test.done(); 248 | } 249 | }); 250 | 251 | conn.querySend("SELECT 4;", function (err, res) { 252 | if (err) { 253 | throw err; 254 | } 255 | 256 | test.ok(res instanceof cfg.mysql_bindings.MysqlResult); 257 | 258 | i++; 259 | 260 | if (i == 4) { 261 | test.done(); 262 | } 263 | }); 264 | }; 265 | 266 | -------------------------------------------------------------------------------- /tests/high-level/test-createconnection-highlevel.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright by Oleg Efimov and node-mysql-libmysqlclient contributors 3 | See contributors list in README 4 | 5 | See license text in LICENSE file 6 | */ 7 | 8 | // Load configuration 9 | var cfg = require('../config'); 10 | 11 | exports.mysql_libmysqlclient_createConnectionHighlevelSync_0 = function (test) { 12 | test.expect(3); 13 | 14 | var conn = cfg.mysql_libmysqlclient.createConnectionHighlevelSync(); 15 | test.ok(conn instanceof cfg.mysql_bindings.MysqlConnection, "conn instanceof MysqlConnection"); 16 | test.ok(conn instanceof cfg.mysql_libmysqlclient.MysqlConnectionQueued); 17 | test.ok(conn instanceof cfg.mysql_libmysqlclient.MysqlConnectionHighlevel); 18 | if (conn.connectedSync()) { 19 | conn.closeSync(); 20 | } 21 | test.done(); 22 | }; 23 | 24 | exports.mysql_libmysqlclient_createConnectionHighlevelSync_4 = function (test) { 25 | test.expect(4); 26 | 27 | var conn = cfg.mysql_libmysqlclient.createConnectionHighlevelSync(cfg.host, cfg.user, cfg.password, cfg.database); 28 | test.ok(conn instanceof cfg.mysql_bindings.MysqlConnection, "conn instanceof MysqlConnection"); 29 | test.ok(conn instanceof cfg.mysql_libmysqlclient.MysqlConnectionQueued); 30 | test.ok(conn instanceof cfg.mysql_libmysqlclient.MysqlConnectionHighlevel); 31 | 32 | isConnected = conn.connectedSync(); 33 | test.ok(isConnected, "cfg.mysql_libmysqlclient.createConnectionHighlevelSync(host, user, password, database) connects"); 34 | 35 | if (!isConnected) { 36 | // Extra debug output 37 | console.log("Error:" + conn.connectError); 38 | } else { 39 | conn.closeSync(); 40 | } 41 | 42 | test.done(); 43 | }; 44 | 45 | exports.mysql_libmysqlclient_createConnectionHighlevelSync_DSN = function (test) { 46 | test.expect(4); 47 | 48 | var 49 | dsn = require('util').format("mysql://%s:%s@%s:%s/%s/zxcvbn?qwerty=1234", cfg.user, cfg.password, cfg.host, cfg.port, cfg.database), 50 | conn = cfg.mysql_libmysqlclient.createConnectionHighlevelSync(dsn), 51 | isConnected; 52 | test.ok(conn instanceof cfg.mysql_bindings.MysqlConnection, "conn instanceof MysqlConnection"); 53 | test.ok(conn instanceof cfg.mysql_libmysqlclient.MysqlConnectionQueued); 54 | test.ok(conn instanceof cfg.mysql_libmysqlclient.MysqlConnectionHighlevel); 55 | 56 | isConnected = conn.connectedSync(); 57 | test.ok(isConnected, "cfg.mysql_libmysqlclient.createConnectionHighlevelSync(dsn(user, password, host, port, database)) connects"); 58 | 59 | if (!isConnected) { 60 | // Extra debug output 61 | console.log("Error:" + conn.connectError); 62 | } else { 63 | conn.closeSync(); 64 | } 65 | 66 | test.done(); 67 | }; 68 | 69 | exports.mysql_libmysqlclient_createConnectionHighlevel_0 = function (test) { 70 | test.expect(1); 71 | 72 | test.throws(function () { 73 | cfg.mysql_libmysqlclient.createConnectionHighlevel(); 74 | }, "require('mysql-libmysqlclient').createConnectionHighlevel() must get callback as last argument"); 75 | 76 | test.done(); 77 | }; 78 | 79 | exports.mysql_libmysqlclient_createConnectionHighlevel_1 = function (test) { 80 | test.expect(4); 81 | 82 | cfg.mysql_libmysqlclient.createConnectionHighlevel(function (err, conn) { 83 | test.ok(err == null, "Error object is not present"); 84 | test.ok(conn instanceof cfg.mysql_bindings.MysqlConnection, "conn instanceof MysqlConnection"); 85 | test.ok(conn instanceof cfg.mysql_libmysqlclient.MysqlConnectionQueued); 86 | test.ok(conn instanceof cfg.mysql_libmysqlclient.MysqlConnectionHighlevel); 87 | 88 | if (conn.connectedSync()) { 89 | conn.closeSync(); 90 | } 91 | 92 | test.done(); 93 | }); 94 | }; 95 | 96 | exports.mysql_libmysqlclient_createConnectionHighlevel_5 = function (test) { 97 | test.expect(5); 98 | 99 | cfg.mysql_libmysqlclient.createConnectionHighlevel(cfg.host, cfg.user, cfg.password, cfg.database, function (err, conn) { 100 | test.ok(err === null, "Error object is not present"); 101 | 102 | test.ok(conn instanceof cfg.mysql_bindings.MysqlConnection, "conn instanceof MysqlConnection"); 103 | test.ok(conn instanceof cfg.mysql_libmysqlclient.MysqlConnectionQueued); 104 | test.ok(conn instanceof cfg.mysql_libmysqlclient.MysqlConnectionHighlevel); 105 | 106 | isConnected = conn.connectedSync(); 107 | test.ok(isConnected, "cfg.mysql_libmysqlclient.createConnectionHighlevel(host, user, password, database, callback) connects"); 108 | 109 | if (!isConnected) { 110 | // Extra debug output 111 | console.log("Error:" + conn.connectError); 112 | } else { 113 | conn.closeSync(); 114 | } 115 | 116 | test.done(); 117 | }); 118 | }; 119 | 120 | exports.mysql_libmysqlclient_createConnectionHighlevel_DSN = function (test) { 121 | test.expect(5); 122 | 123 | var dsn = require('util').format("mysql://%s:%s@%s:%s/%s/zxcvbn?qwerty=1234", cfg.user, cfg.password, cfg.host, cfg.port, cfg.database); 124 | 125 | cfg.mysql_libmysqlclient.createConnectionHighlevel(dsn, function (err, conn) { 126 | test.ok(err === null, "Error object is not present"); 127 | 128 | test.ok(conn instanceof cfg.mysql_bindings.MysqlConnection, "conn instanceof MysqlConnection"); 129 | test.ok(conn instanceof cfg.mysql_libmysqlclient.MysqlConnectionQueued); 130 | test.ok(conn instanceof cfg.mysql_libmysqlclient.MysqlConnectionHighlevel); 131 | 132 | isConnected = conn.connectedSync(); 133 | test.ok(isConnected, "cfg.mysql_libmysqlclient.createConnectionHighlevel(dsn(user, password, host, port, database), callback) connects"); 134 | 135 | if (!isConnected) { 136 | // Extra debug output 137 | console.log("Error:" + conn.connectError); 138 | } else { 139 | conn.closeSync(); 140 | } 141 | 142 | test.done(); 143 | }); 144 | }; 145 | -------------------------------------------------------------------------------- /tests/high-level/test-createconnection-queued.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright by Oleg Efimov and node-mysql-libmysqlclient contributors 3 | See contributors list in README 4 | 5 | See license text in LICENSE file 6 | */ 7 | 8 | // Load configuration 9 | var cfg = require('../config'); 10 | 11 | exports.mysql_libmysqlclient_createConnectionQueuedSync_0 = function (test) { 12 | test.expect(2); 13 | 14 | var conn = cfg.mysql_libmysqlclient.createConnectionQueuedSync(); 15 | test.ok(conn instanceof cfg.mysql_bindings.MysqlConnection, "conn instanceof MysqlConnection"); 16 | test.ok(conn instanceof cfg.mysql_libmysqlclient.MysqlConnectionQueued); 17 | if (conn.connectedSync()) { 18 | conn.closeSync(); 19 | } 20 | test.done(); 21 | }; 22 | 23 | exports.mysql_libmysqlclient_createConnectionQueuedSync_4 = function (test) { 24 | test.expect(3); 25 | 26 | var conn = cfg.mysql_libmysqlclient.createConnectionQueuedSync(cfg.host, cfg.user, cfg.password, cfg.database); 27 | test.ok(conn instanceof cfg.mysql_bindings.MysqlConnection, "conn instanceof MysqlConnection"); 28 | test.ok(conn instanceof cfg.mysql_libmysqlclient.MysqlConnectionQueued); 29 | 30 | isConnected = conn.connectedSync(); 31 | test.ok(isConnected, "cfg.mysql_libmysqlclient.createConnectionQueuedSync(host, user, password, database) connects"); 32 | 33 | if (!isConnected) { 34 | // Extra debug output 35 | console.log("Error:" + conn.connectError); 36 | } else { 37 | conn.closeSync(); 38 | } 39 | 40 | test.done(); 41 | }; 42 | 43 | exports.mysql_libmysqlclient_createConnectionQueuedSync_DSN = function (test) { 44 | test.expect(2); 45 | 46 | var 47 | dsn = require('util').format("mysql://%s:%s@%s:%s/%s/zxcvbn?qwerty=1234", cfg.user, cfg.password, cfg.host, cfg.port, cfg.database), 48 | conn = cfg.mysql_libmysqlclient.createConnectionQueuedSync(dsn), 49 | isConnected; 50 | test.ok(conn instanceof cfg.mysql_libmysqlclient.MysqlConnectionQueued, "cfg.mysql_libmysqlclient.createConnectionQueuedSync(dsn(user, password, host, port, database))"); 51 | 52 | isConnected = conn.connectedSync(); 53 | test.ok(isConnected, "cfg.mysql_libmysqlclient.createConnectionQueuedSync(dsn(user, password, host, port, database)) connects"); 54 | 55 | if (!isConnected) { 56 | // Extra debug output 57 | console.log("Error:" + conn.connectError); 58 | } else { 59 | conn.closeSync(); 60 | } 61 | 62 | test.done(); 63 | }; 64 | 65 | exports.mysql_libmysqlclient_createConnectionQueued_0 = function (test) { 66 | test.expect(1); 67 | 68 | test.throws(function () { 69 | cfg.mysql_libmysqlclient.createConnectionQueued(); 70 | }, "require('mysql-libmysqlclient').createConnectionQueued() must get callback as last argument"); 71 | 72 | test.done(); 73 | }; 74 | 75 | exports.mysql_libmysqlclient_createConnectionQueued_1 = function (test) { 76 | test.expect(3); 77 | 78 | cfg.mysql_libmysqlclient.createConnectionQueued(function (err, conn) { 79 | test.ok(err == null, "Error object is not present"); 80 | test.ok(conn instanceof cfg.mysql_bindings.MysqlConnection, "conn instanceof MysqlConnection"); 81 | test.ok(conn instanceof cfg.mysql_libmysqlclient.MysqlConnectionQueued); 82 | 83 | if (conn.connectedSync()) { 84 | conn.closeSync(); 85 | } 86 | 87 | test.done(); 88 | }); 89 | }; 90 | 91 | exports.mysql_libmysqlclient_createConnectionQueued_5 = function (test) { 92 | test.expect(4); 93 | 94 | cfg.mysql_libmysqlclient.createConnectionQueued(cfg.host, cfg.user, cfg.password, cfg.database, function (err, conn) { 95 | test.ok(err === null, "Error object is not present"); 96 | 97 | test.ok(conn instanceof cfg.mysql_bindings.MysqlConnection, "conn instanceof MysqlConnection"); 98 | test.ok(conn instanceof cfg.mysql_libmysqlclient.MysqlConnectionQueued); 99 | 100 | isConnected = conn.connectedSync(); 101 | test.ok(isConnected, "cfg.mysql_libmysqlclient.createConnectionQueued(host, user, password, database, callback) connects"); 102 | 103 | if (!isConnected) { 104 | // Extra debug output 105 | console.log("Error:" + conn.connectError); 106 | } else { 107 | conn.closeSync(); 108 | } 109 | 110 | test.done(); 111 | }); 112 | }; 113 | 114 | exports.mysql_libmysqlclient_createConnectionQueued_DSN = function (test) { 115 | test.expect(4); 116 | 117 | var dsn = require('util').format("mysql://%s:%s@%s:%s/%s/zxcvbn?qwerty=1234", cfg.user, cfg.password, cfg.host, cfg.port, cfg.database); 118 | 119 | cfg.mysql_libmysqlclient.createConnectionQueued(dsn, function (err, conn) { 120 | test.ok(err === null, "Error object is not present"); 121 | test.ok(conn instanceof cfg.mysql_bindings.MysqlConnection, "conn instanceof MysqlConnection"); 122 | test.ok(conn instanceof cfg.mysql_libmysqlclient.MysqlConnectionQueued); 123 | 124 | isConnected = conn.connectedSync(); 125 | test.ok(isConnected, "cfg.mysql_libmysqlclient.createConnectionQueued(dsn(user, password, host, port, database), callback) connects"); 126 | 127 | if (!isConnected) { 128 | // Extra debug output 129 | console.log("Error:" + conn.connectError); 130 | } else { 131 | conn.closeSync(); 132 | } 133 | 134 | test.done(); 135 | }); 136 | }; 137 | -------------------------------------------------------------------------------- /tests/ignored/place_ignored_tests.here: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sannis/node-mysql-libmysqlclient/a337b41e997fee6abaef9ee36a3bc2d548f3fc23/tests/ignored/place_ignored_tests.here -------------------------------------------------------------------------------- /tests/issues/test-issue-102.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright by Oleg Efimov and node-mysql-libmysqlclient contributors 3 | See contributors list in README 4 | 5 | See license text in LICENSE file 6 | */ 7 | 8 | // Load configuration 9 | var cfg = require("../config"); 10 | 11 | exports.createTestTableForIssue102 = function (test) { 12 | test.expect(3); 13 | 14 | var 15 | conn = cfg.mysql_libmysqlclient.createConnectionSync(cfg.host, cfg.user, cfg.password, cfg.database), 16 | res, 17 | tables; 18 | 19 | conn.querySync("DROP TABLE IF EXISTS " + cfg.test_table + ";"); 20 | conn.querySync("CREATE TABLE " + cfg.test_table + 21 | "(`user_` int(11) NOT NULL," + 22 | " `karma` int(11) DEFAULT '0'," + 23 | " `energy` int(11) DEFAULT '0'," + 24 | " `zachet` int(11) DEFAULT '0'," + 25 | " `hvost` int(11) DEFAULT '0'," + 26 | " `digits` int(11) DEFAULT '0'," + 27 | " `level` int(11) DEFAULT '1'," + 28 | " PRIMARY KEY (`user_`)," + 29 | " KEY `level_karma` (`level`,`karma`)) " + cfg.store_engine + ";"); 30 | res = conn.querySync("SHOW TABLES"); 31 | tables = res.fetchAllSync(); 32 | 33 | test.ok(res.fieldCount === 1, "SHOW TABLES result field count === 1"); 34 | test.ok(tables.some(function (r) { 35 | return r['Tables_in_' + cfg.database] === cfg.test_table; 36 | }), "Find the test_table in results"); 37 | 38 | res = conn.querySync("INSERT INTO " + cfg.test_table + 39 | " (`user_`, `karma`, `energy`, `zachet`, `hvost`, `digits`, `level`)" + 40 | " VALUES (1057691, 0, 400, 5, 5, 0, 1);"); 41 | test.ok(res === true, "conn.querySync('INSERT INTO test_table ...')"); 42 | 43 | conn.closeSync(); 44 | 45 | test.done(); 46 | }; 47 | 48 | exports.issue102 = function (test) { 49 | test.expect(2); 50 | 51 | var 52 | conn = cfg.mysql_libmysqlclient.createConnectionSync(cfg.host, cfg.user, cfg.password, cfg.database), 53 | res, 54 | rows; 55 | 56 | res = conn.querySync("SELECT * FROM " + cfg.test_table + ";"); 57 | 58 | test.ok(res instanceof cfg.mysql_bindings.MysqlResult, "conn.querySync('SELECT * FROM test_table;')"); 59 | 60 | rows = res.fetchAllSync(); 61 | 62 | test.equals(rows.length, 1, "1 row selected"); 63 | 64 | conn.closeSync(); 65 | 66 | test.done(); 67 | }; 68 | -------------------------------------------------------------------------------- /tests/issues/test-issue-106.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright by Oleg Efimov and node-mysql-libmysqlclient contributors 3 | See contributors list in README 4 | 5 | See license text in LICENSE file 6 | */ 7 | 8 | // Load configuration 9 | var cfg = require("../config"); 10 | 11 | exports.createTestTableForIssue106 = function (test) { 12 | test.expect(3); 13 | 14 | var 15 | conn = cfg.mysql_libmysqlclient.createConnectionSync(cfg.host, cfg.user, cfg.password, cfg.database), 16 | res, 17 | tables; 18 | 19 | conn.querySync("DROP TABLE IF EXISTS " + cfg.test_table + ";"); 20 | conn.querySync("CREATE TABLE " + cfg.test_table + 21 | "(`id` int(11) NOT NULL," + 22 | " `value` varchar(128)) " + cfg.store_engine + ";"); 23 | res = conn.querySync("SHOW TABLES"); 24 | tables = res.fetchAllSync(); 25 | 26 | test.ok(res.fieldCount === 1, "SHOW TABLES result field count === 1"); 27 | test.ok(tables.some(function (r) { 28 | return r['Tables_in_' + cfg.database] === cfg.test_table; 29 | }), "Find the test_table in results"); 30 | 31 | res = conn.querySync("INSERT INTO " + cfg.test_table + 32 | " (`id`, `value`)" + 33 | " VALUES (1, 'one'), (2, 'two'), (3, 'three'), (4, 'four');"); 34 | test.ok(res === true, "conn.querySync('INSERT INTO test_table ...')"); 35 | 36 | conn.closeSync(); 37 | 38 | test.done(); 39 | }; 40 | 41 | exports.issue106 = function (test) { 42 | test.expect(10); 43 | 44 | var 45 | conn = cfg.mysql_libmysqlclient.createConnectionSync(cfg.host, cfg.user, cfg.password, cfg.database), 46 | queryTemplate = "SELECT * FROM " + cfg.test_table + " WHERE `value` = '%'", 47 | queries = []; 48 | 49 | queries.push(queryTemplate.replace('%', 'one')); 50 | queries.push(queryTemplate.replace('%', 'three')); 51 | 52 | conn.query(queries.join(' UNION ALL '), function (err, res) { 53 | test.ok(err === null, "Error object is not present"); 54 | test.ok(res instanceof cfg.mysql_bindings.MysqlResult, "res instanceof MysqlResult"); 55 | 56 | res.fetchAll(function (err, rows) { 57 | test.ok(err === null, "Error object is not present"); 58 | test.ok(res instanceof cfg.mysql_bindings.MysqlResult, "res instanceof MysqlResult"); 59 | 60 | test.deepEqual(rows, [ { id: 1, value: 'one' }, { id: 3, value: 'three' } ]); 61 | 62 | conn.query(queries.join(' UNION ALL '), function (err, res) { 63 | test.ok(err === null, "Error object is not present"); 64 | test.ok(res instanceof cfg.mysql_bindings.MysqlResult, "res instanceof MysqlResult"); 65 | 66 | res.fetchAll(function (err, rows) { 67 | test.ok(err === null, "Error object is not present"); 68 | test.ok(res instanceof cfg.mysql_bindings.MysqlResult, "res instanceof MysqlResult"); 69 | 70 | test.deepEqual(rows, [ { id: 1, value: 'one' }, { id: 3, value: 'three' } ]); 71 | 72 | conn.closeSync(); 73 | 74 | test.done(); 75 | }); 76 | }); 77 | }); 78 | }); 79 | }; 80 | -------------------------------------------------------------------------------- /tests/issues/test-issue-110.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright by Oleg Efimov and node-mysql-libmysqlclient contributors 3 | See contributors list in README 4 | 5 | See license text in LICENSE file 6 | */ 7 | 8 | // Load configuration 9 | var cfg = require("../config"); 10 | 11 | exports.createTestTableForIssue110 = function (test) { 12 | test.expect(3); 13 | 14 | var 15 | conn = cfg.mysql_libmysqlclient.createConnectionSync(cfg.host, cfg.user, cfg.password, cfg.database), 16 | res, 17 | tables; 18 | 19 | conn.querySync("DROP TABLE IF EXISTS " + cfg.test_table + ";"); 20 | conn.querySync("CREATE TABLE " + cfg.test_table + 21 | "(`int` int NOT NULL," + 22 | " `bigint` bigint, " + 23 | " `decimal` decimal(40)) " + cfg.store_engine + ";"); 24 | res = conn.querySync("SHOW TABLES"); 25 | tables = res.fetchAllSync(); 26 | 27 | test.ok(res.fieldCount === 1, "SHOW TABLES result field count === 1"); 28 | test.ok(tables.some(function (r) { 29 | return r['Tables_in_' + cfg.database] === cfg.test_table; 30 | }), "Find the test_table in results"); 31 | 32 | res = conn.querySync("INSERT INTO " + cfg.test_table + 33 | " (`int`, `bigint`, `decimal`)" + 34 | " VALUES (1, 1234, 1234567890), (2, 1234567890123456789, 12345678901234567890);"); 35 | test.ok(res === true, "conn.querySync('INSERT INTO test_table ...')"); 36 | 37 | conn.closeSync(); 38 | 39 | test.done(); 40 | }; 41 | 42 | exports.issue110 = function (test) { 43 | test.expect(3); 44 | 45 | var 46 | conn = cfg.mysql_libmysqlclient.createConnectionSync(cfg.host, cfg.user, cfg.password, cfg.database), 47 | res, 48 | rows; 49 | 50 | res = conn.querySync("SELECT * FROM " + cfg.test_table + ";"); 51 | 52 | test.ok(res instanceof cfg.mysql_bindings.MysqlResult, "conn.querySync('SELECT * FROM test_table;')"); 53 | 54 | rows = res.fetchAllSync(); 55 | 56 | test.ok(typeof rows[0]['bigint'] === 'string', "BIGINT returns as string"); 57 | 58 | test.ok(rows[1]['bigint'] === '1234567890123456789', "BIGINT returns as correct string"); 59 | 60 | conn.closeSync(); 61 | 62 | test.done(); 63 | }; 64 | -------------------------------------------------------------------------------- /tests/issues/test-issue-157.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright by Oleg Efimov and node-mysql-libmysqlclient contributors 3 | See contributors list in README 4 | 5 | See license text in LICENSE file 6 | */ 7 | 8 | // Load configuration 9 | var cfg = require("../config"); 10 | 11 | exports.issue157_query = function (test) { 12 | test.expect(3); 13 | 14 | var conn = cfg.mysql_libmysqlclient.createConnectionSync(cfg.host, cfg.user, cfg.password, cfg.database); 15 | 16 | conn.query('SELECT SLEEP(5);', function (err) { 17 | test.ok(err instanceof Error); 18 | test.ok(err.message.indexOf("Connection is closed by closeSync()") === 0); 19 | 20 | test.done(); 21 | }); 22 | 23 | conn.closeSync(); 24 | 25 | test.ok(true); 26 | }; 27 | 28 | exports.issue157_querySend = function (test) { 29 | test.expect(3); 30 | 31 | var conn = cfg.mysql_libmysqlclient.createConnectionSync(cfg.host, cfg.user, cfg.password, cfg.database); 32 | 33 | conn.querySend('SELECT SLEEP(5);', function (err) { 34 | test.ok(err instanceof Error); 35 | test.ok(err.message.indexOf("Connection is closed by closeSync()") === 0); 36 | 37 | test.done(); 38 | }); 39 | 40 | conn.closeSync(); 41 | 42 | test.ok(true); 43 | }; 44 | -------------------------------------------------------------------------------- /tests/issues/test-issue-83.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright by Oleg Efimov and node-mysql-libmysqlclient contributors 3 | See contributors list in README 4 | 5 | See license text in LICENSE file 6 | */ 7 | 8 | /* 9 | mysql_query() cannot be used for statements that contain binary data; you must use mysql_real_query() instead. 10 | (Binary data may contain the “\0” character, which mysql_query() interprets as the end of the statement string.) 11 | In addition, mysql_real_query() is faster than mysql_query() because it does not call strlen() on the statement string. 12 | */ 13 | 14 | // Load configuration 15 | var cfg = require("../config"); 16 | 17 | exports.Issue83Query = function (test) { 18 | test.expect(3); 19 | 20 | var conn = cfg.mysql_libmysqlclient.createConnectionSync(cfg.host, cfg.user, cfg.password, cfg.database); 21 | 22 | res = conn.query("SELECT '1\u00002345\0' AS a;", function (err, res) { 23 | test.ok(err === null, "Error object is not present"); 24 | test.ok(res instanceof cfg.mysql_bindings.MysqlResult, "res instanceof MysqlResult"); 25 | 26 | rows = res.fetchAllSync(); 27 | test.same(rows, [{a: "1\u00002345\0"}], "conn.querySync('SELECT ...').fetchAllSync()"); 28 | 29 | conn.closeSync(); 30 | 31 | test.done(); 32 | }); 33 | }; 34 | 35 | exports.Issue83QuerySync = function (test) { 36 | test.expect(2); 37 | 38 | var 39 | conn = cfg.mysql_libmysqlclient.createConnectionSync(cfg.host, cfg.user, cfg.password, cfg.database), 40 | res; 41 | 42 | res = conn.querySync("SELECT '1\u00002345\0' AS a;"); 43 | test.ok(res instanceof cfg.mysql_bindings.MysqlResult, "SELECT '1\u00002345\0' AS a;"); 44 | 45 | rows = res.fetchAllSync(); 46 | test.same(rows, [{a: "1\u00002345\0"}], "conn.querySync('SELECT ...').fetchAllSync()"); 47 | 48 | conn.closeSync(); 49 | 50 | test.done(); 51 | }; 52 | 53 | exports.Issue83RealQuerySync = function (test) { 54 | test.expect(2); 55 | 56 | var 57 | conn = cfg.mysql_libmysqlclient.createConnectionSync(cfg.host, cfg.user, cfg.password, cfg.database), 58 | res; 59 | 60 | conn.realQuerySync("SELECT '1\u00002345\0' AS a;"); 61 | res = conn.storeResultSync(); 62 | 63 | test.ok(res instanceof cfg.mysql_bindings.MysqlResult, "SELECT '1\u00002345\0' AS a;"); 64 | 65 | rows = res.fetchAllSync(); 66 | test.same(rows, [{a: "1\u00002345\0"}], "conn.querySync('SELECT ...').fetchAllSync()"); 67 | 68 | conn.closeSync(); 69 | 70 | test.done(); 71 | }; 72 | 73 | exports.Issue83MultyQuerySync = function (test) { 74 | test.expect(5); 75 | 76 | var 77 | conn = cfg.mysql_libmysqlclient.createConnectionSync(cfg.host, cfg.user, cfg.password, cfg.database), 78 | res; 79 | 80 | conn.multiRealQuerySync("SELECT '1\u00002345\0' AS a; SELECT 'q\u0000werty\0' AS b;"); 81 | res = conn.storeResultSync(); 82 | test.ok(res instanceof cfg.mysql_bindings.MysqlResult, "SELECT '1\u00002345\0' AS a;"); 83 | 84 | rows = res.fetchAllSync(); 85 | test.same(rows, [{a: "1\u00002345\0"}], "conn.querySync('SELECT ...').fetchAllSync()"); 86 | 87 | test.ok(conn.multiMoreResultsSync(), "conn.multiMoreResultsSync()"); 88 | 89 | conn.multiNextResultSync(); 90 | res = conn.storeResultSync(); 91 | test.ok(res instanceof cfg.mysql_bindings.MysqlResult, "SELECT 'q\u0000werty\0' AS b;"); 92 | 93 | rows = res.fetchAllSync(); 94 | test.same(rows, [{b: "q\u0000werty\0"}], "conn.querySync('SELECT ...').fetchAllSync()"); 95 | 96 | conn.closeSync(); 97 | 98 | test.done(); 99 | }; 100 | -------------------------------------------------------------------------------- /tests/load-data-infile/complex-load-infile.js: -------------------------------------------------------------------------------- 1 | var cfg = require('../config.js'); 2 | var fs = require('fs'); 3 | var createLoadInfileCapableConnection = function () { 4 | var conn = new cfg.mysql_libmysqlclient.bindings.MysqlConnection(); 5 | conn.initSync(); 6 | conn.setOptionSync(cfg.mysql_libmysqlclient.MYSQL_OPT_LOCAL_INFILE); 7 | conn.realConnectSync(cfg.host, cfg.user, cfg.password, cfg.database); 8 | if (conn.connectErrno) { 9 | console.log("Failed to connect as " + cfg.user + "@" + cfg.host + ": " + conn.connectError); 10 | } 11 | return conn; 12 | }; 13 | var prepareData = function () { 14 | var i, 15 | data = []; 16 | for (i = 0; i < 1000; i++) { 17 | data.push(i + ',zzzz' + i); 18 | } 19 | return data.join('\n'); 20 | }; 21 | module.exports = { 22 | setUp: function (callback) { 23 | this.conn = createLoadInfileCapableConnection(); 24 | this.conn.querySync("DROP TABLE IF EXISTS " + cfg.test_table); 25 | this.conn.querySync("CREATE TABLE " + cfg.test_table + " (field1 int, field2 text)"); 26 | this.exampleData = new Buffer(prepareData()); 27 | this.exampleQuery = 'LOAD DATA LOCAL INFILE \'/nothing\' INTO TABLE ' + cfg.test_table + 28 | " FIELDS TERMINATED BY ',' LINES TERMINATED BY '\n'"; 29 | callback(); 30 | }, 31 | tearDown: function (callback) { 32 | if (this.conn && this.conn.connectedSync()) { 33 | this.conn.closeSync(); 34 | } 35 | callback(); 36 | }, 37 | syncCloseSync: function (test) { 38 | test.expect(2); 39 | test.ok(this.conn.querySync(this.exampleQuery, this.exampleData), "load infile syncronous"); 40 | this.conn.closeSync(); 41 | test.throws( 42 | this.conn.query.bind( 43 | this.conn, 44 | this.exampleQuery, 45 | this.exampleData, 46 | function (result) { 47 | test.ok(false, "there has to be exception if calling query after close"); 48 | test.done(); 49 | }.bind(this) 50 | ), 51 | "there has to be exception in query after closeSync" 52 | ); 53 | test.done(); 54 | }, 55 | asyncCloseAsync: function (test) { 56 | test.expect(2); 57 | try { 58 | this.conn.query( 59 | this.exampleQuery, 60 | this.exampleData, 61 | function (error) { 62 | test.ok(error === null, "asyncronous load data infile breaks"); 63 | this.conn.closeSync(); 64 | test.throws( 65 | this.conn.query.bind( 66 | this.conn, 67 | this.exampleQuery, 68 | this.exampleData, 69 | function (error) { 70 | test.ok(false, "there has to be exception in query after closeSync"); 71 | test.done(); 72 | } 73 | ) 74 | ); 75 | test.done(); 76 | }.bind(this) 77 | ); 78 | } catch (e) { 79 | test.ok(false, "asyncronous query LOAD DATA INFILE from Buffer breaks"); 80 | test.done(); 81 | } 82 | }, 83 | syncAsyncSync: function (test) { 84 | test.expect(4); 85 | test.ok( 86 | this.conn.querySync( 87 | this.exampleQuery, 88 | this.exampleData 89 | ), 90 | 'synchronous load data infile query' 91 | ); 92 | try { 93 | this.conn.query( 94 | this.exampleQuery, 95 | this.exampleData, 96 | function (error) { 97 | var result; 98 | test.ok(error === null, "Asynchronous load data infile after syncronous"); 99 | result = this.conn.querySync("select count(*) as count from " + cfg.test_table); 100 | test.ok(result, "syncronous query after sync + async"); 101 | result = result && result.fetchAllSync(); 102 | result = result && result[0] && result[0].count; 103 | test.ok(result > 0, "Load infile fails, table is empty"); 104 | test.done(); 105 | }.bind(this) 106 | ); 107 | } catch (e) { 108 | test.ok(false, "Asynchronous load data infile after syncronous"); 109 | test.done(); 110 | } 111 | }, 112 | asyncSyncAsync: function (test) { 113 | test.expect(4); 114 | try { 115 | this.conn.query( 116 | this.exampleQuery, 117 | this.exampleData, 118 | function (error) { 119 | test.ok(error === null, "Asynchronous load data infile fails"); 120 | test.ok( 121 | this.conn.querySync( 122 | this.exampleQuery, 123 | this.exampleData 124 | ), 125 | "synchronous data load fails" 126 | ); 127 | try { 128 | this.conn.query( 129 | "SELECT count(*) as count from " + cfg.test_table, 130 | function (error, result) { 131 | test.ok(error === null, "Asyncronous query after synchronous fails"); 132 | result = result && result.fetchAllSync(); 133 | result = result && result[0] && result[0].count; 134 | test.ok(result > 0, "Load data infile asynchounous and syncronous fails"); 135 | test.done(); 136 | }.bind(this) 137 | ); 138 | } catch (e) { 139 | test.ok(false, "Asyncronous query after synchronous fails"); 140 | test.done(); 141 | } 142 | }.bind(this) 143 | ); 144 | } catch (e) { 145 | test.ok(false, "Asynchronous load data infile after syncronous"); 146 | test.done(); 147 | } 148 | } 149 | }; 150 | -------------------------------------------------------------------------------- /tests/load-data-infile/simle-load-infile.js: -------------------------------------------------------------------------------- 1 | var cfg = require('../config.js'); 2 | var fs = require('fs'); 3 | var createLoadInfileCapableConnection = function (clientClass) { 4 | var conn = new clientClass(); 5 | conn.initSync(); 6 | conn.setOptionSync(cfg.mysql_libmysqlclient.MYSQL_OPT_LOCAL_INFILE); 7 | conn.realConnectSync(cfg.host, cfg.user, cfg.password, cfg.database); 8 | if (conn.connectErrno) { 9 | console.log("Failed to connect as " + cfg.user + "@" + cfg.host + ": " + conn.connectError); 10 | } 11 | return conn; 12 | }; 13 | var formatData = function (data, fieldTerminator, rowTerminator) { 14 | return data.map(function (row) { 15 | return row.join(fieldTerminator); 16 | }).join(rowTerminator); 17 | }; 18 | var prepareData = function () { 19 | var i, 20 | data = []; 21 | for (i = 0; i < 1000; i++) { 22 | data.push([i, 'zzzz' + i]); 23 | } 24 | return data; 25 | }; 26 | var prepareDataFile = function (filePath, data, fieldTerminator, rowTerminator) { 27 | try { 28 | if (fs.statSync(filePath)) { 29 | fs.unlinkSync(filePath); 30 | } 31 | } catch (e) {} 32 | fs.writeFileSync(filePath, formatData(data, fieldTerminator, rowTerminator)); 33 | }; 34 | var testQueryResult = function (test, conn) { 35 | var result = conn.querySync("select sum(field1) as sum, count(*) as count from " + 36 | cfg.test_table); 37 | result = result && result.fetchAllSync(); 38 | result = result && result[0]; 39 | test.ok( 40 | result && 41 | Number(result.sum) === 1000 * 999 / 2 && //arithmetic progression 42 | Number(result.count) === 1000, 43 | "load infile" 44 | ); 45 | }; 46 | var createQuery = function (fileName, fieldTerminator, rowTerminator) { 47 | return 'LOAD DATA LOCAL INFILE \'' + fileName + '\' INTO TABLE ' + cfg.test_table + 48 | " FIELDS TERMINATED BY '" + fieldTerminator + "'" + 49 | " LINES TERMINATED BY '" + rowTerminator + "'"; 50 | }; 51 | var setUp = function (callback) { 52 | this.conn = createLoadInfileCapableConnection(this.clientClass); 53 | this.conn.querySync("DROP TABLE IF EXISTS " + cfg.test_table); 54 | this.conn.querySync("CREATE TABLE " + cfg.test_table + " (field1 int, field2 text)"); 55 | this.fileName = this.fileName || 'nothing'; 56 | this.exampleData = prepareData(); 57 | callback(); 58 | }; 59 | var tearDown = function (callback) { 60 | if (this.conn && this.conn.connectedSync()) { 61 | this.conn.closeSync(); 62 | } 63 | callback(); 64 | }; 65 | 66 | var syncTest = function (fieldTerminator, rowTerminator, test) { 67 | test.expect(2); 68 | if (!this.bufferMode) { 69 | prepareDataFile(this.fileName, this.exampleData, fieldTerminator, rowTerminator); 70 | } else { 71 | this.exampleData = new Buffer(formatData(this.exampleData, fieldTerminator, rowTerminator)); 72 | } 73 | test.ok(this.conn.querySync( 74 | createQuery(this.fileName, fieldTerminator, rowTerminator), 75 | this.bufferMode ? this.exampleData : undefined 76 | )); 77 | testQueryResult(test, this.conn); 78 | test.done(); 79 | }; 80 | var asyncTest = function (fieldTerminator, rowTerminator, test) { 81 | test.expect(2); 82 | var queryCallback = 83 | function (error) { 84 | test.ok(error === null, "Asynchronous load data infile fails"); 85 | testQueryResult(test, this.conn); 86 | test.done(); 87 | }.bind(this), 88 | callArgs = [createQuery(this.fileName, fieldTerminator, rowTerminator)]; 89 | if (!this.bufferMode) { 90 | prepareDataFile(this.fileName, this.exampleData, fieldTerminator, rowTerminator); 91 | callArgs.push(queryCallback); 92 | } else { 93 | this.exampleData = new Buffer(formatData(this.exampleData, fieldTerminator, rowTerminator)); 94 | callArgs.push(this.exampleData, queryCallback); 95 | } 96 | try { 97 | this.conn.query.apply(this.conn, callArgs); 98 | } catch (e) { 99 | test.ok(false, "Asynchronous load data infile fails"); 100 | test.done(); 101 | } 102 | }; 103 | /** 104 | * Table with tests build as 105 | * combination of format (CSV/TSV) and 106 | * syncronous/asyncronous modes of work 107 | */ 108 | var formatModeCombinationsList = { 109 | syncCSV: function (test) { 110 | syncTest.call(this, ',', '\n', test); 111 | }, 112 | syncTSV: function (test) { 113 | syncTest.call(this, '\t', '\n', test); 114 | }, 115 | asyncCSV: function (test) { 116 | asyncTest.call(this, ',', '\n', test); 117 | }, 118 | asyncTSV: function (test) { 119 | asyncTest.call(this, '\t', '\n', test); 120 | } 121 | }; 122 | //enshure mysql server has enabled local_infile option, 123 | //and test has sence at all 124 | module.exports.checkServerOptions = function (test) { 125 | test.expect(1); 126 | var conn = createLoadInfileCapableConnection(cfg.mysql_libmysqlclient.MysqlConnectionQueued); 127 | result = conn.querySync("SHOW VARIABLES LIKE 'local_infile'"); 128 | result = result && result.fetchAllSync(); 129 | result = result && result[0] && result[0].Value; 130 | test.ok( 131 | result && result.toLowerCase() === 'on', 132 | "LOAD INFILE OPERATION REQUIRES local_infile options set on the server\n" + 133 | "execute 'SET GLOBAL local_infile=ON' in mysql server console" 134 | ); 135 | test.done(); 136 | }; 137 | //tests for c++ part 138 | module.exports.bindings = { 139 | realFile: { 140 | setUp: function (callback) { 141 | this.clientClass = cfg.mysql_libmysqlclient.bindings.MysqlConnection; 142 | this.fileName = '/tmp/load-infile-test.csv'; 143 | this.bufferMode = false; 144 | setUp.call(this, callback); 145 | }, 146 | tearDown: tearDown, 147 | tests: formatModeCombinationsList 148 | }, 149 | buffer: { 150 | setUp: function (callback) { 151 | this.clientClass = cfg.mysql_libmysqlclient.bindings.MysqlConnection; 152 | this.bufferMode = true; 153 | setUp.call(this, callback); 154 | }, 155 | tearDown: tearDown, 156 | tests: formatModeCombinationsList 157 | } 158 | }; 159 | //tests for queued client 160 | module.exports.queuedClient = { 161 | realFile: { 162 | setUp: function (callback) { 163 | this.clientClass = cfg.mysql_libmysqlclient.MysqlConnectionQueued; 164 | this.bufferMode = false; 165 | this.fileName = '/tmp/load-infile-test.csv'; 166 | setUp.call(this, callback); 167 | }, 168 | tearDown: tearDown, 169 | tests: formatModeCombinationsList 170 | }, 171 | buffer: { 172 | setUp: function (callback) { 173 | this.clientClass = cfg.mysql_libmysqlclient.MysqlConnectionQueued; 174 | this.bufferMode = true; 175 | setUp.call(this, callback); 176 | }, 177 | tearDown: tearDown, 178 | tests: formatModeCombinationsList 179 | } 180 | }; 181 | //tests for high-level client 182 | module.exports.highLevel= { 183 | realFile: { 184 | setUp: function (callback) { 185 | this.clientClass = cfg.mysql_libmysqlclient.MysqlConnectionHighlevel; 186 | this.bufferMode = false; 187 | this.fileName = '/tmp/load-infile-test.csv'; 188 | setUp.call(this, callback); 189 | }, 190 | tearDown: tearDown, 191 | tests: formatModeCombinationsList 192 | }, 193 | buffer: { 194 | setUp: function (callback) { 195 | this.clientClass = cfg.mysql_libmysqlclient.MysqlConnectionHighlevel; 196 | this.bufferMode = true; 197 | setUp.call(this, callback); 198 | }, 199 | tearDown: tearDown, 200 | tests: formatModeCombinationsList 201 | } 202 | }; 203 | -------------------------------------------------------------------------------- /tests/low-level-async/setup-low-level-async.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright by Oleg Efimov and node-mysql-libmysqlclient contributors 3 | See contributors list in README 4 | 5 | See license text in LICENSE file 6 | */ 7 | 8 | // Load configuration 9 | var cfg = require('../config.js'); 10 | 11 | exports.createTestTableSimple = function (test) { 12 | test.expect(3); 13 | 14 | var 15 | conn = cfg.mysql_libmysqlclient.createConnectionSync(cfg.host, cfg.user, cfg.password, cfg.database), 16 | res, 17 | tables; 18 | 19 | if (conn.connectErrno) { 20 | console.log("Failed to connect as " + cfg.user + "@" + cfg.host + ": " + conn.connectError); 21 | } 22 | 23 | test.ok(conn, "mysql_libmysqlclient.createConnectionSync(host, user, password, database)"); 24 | 25 | conn.querySync("DROP TABLE IF EXISTS " + cfg.test_table + ";"); 26 | conn.querySync("CREATE TABLE " + cfg.test_table + 27 | " (id INT(8) NOT NULL AUTO_INCREMENT, " + 28 | "random_number INT(8) NOT NULL, " + 29 | "random_boolean BOOLEAN NOT NULL, " + 30 | "PRIMARY KEY(id)) " + cfg.store_engine + ";"); 31 | res = conn.querySync("SHOW TABLES"); 32 | test.ok(res.fieldCount === 1, "SHOW TABLES result field count === 1"); 33 | tables = res.fetchAllSync(); 34 | test.ok(tables.some(function (r) { 35 | return r['Tables_in_' + cfg.database] === cfg.test_table; 36 | }), "Find the test table in result"); 37 | 38 | conn.querySync("DROP TABLE IF EXISTS " + cfg.test_table_notexists + ";"); 39 | 40 | conn.closeSync(); 41 | 42 | test.done(); 43 | }; 44 | 45 | -------------------------------------------------------------------------------- /tests/low-level-async/test-class-mysqlconnection-async.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright by Oleg Efimov and node-mysql-libmysqlclient contributors 3 | See contributors list in README 4 | 5 | See license text in LICENSE file 6 | */ 7 | 8 | // Load configuration 9 | var cfg = require('../config.js'); 10 | 11 | exports.Connect = function (test) { 12 | test.expect(2); 13 | 14 | var conn = new cfg.mysql_bindings.MysqlConnection(); 15 | 16 | conn.connect(cfg.host, cfg.user, cfg.password, cfg.database, function (err) { 17 | test.ok(err === null, "conn.connect() for allowed database"); 18 | test.ok(arguments.length <= 1, "Only error arguments is possible."); 19 | 20 | conn.closeSync(); 21 | 22 | test.done(); 23 | }); 24 | }; 25 | 26 | exports.ConnectWithError = function (test) { 27 | test.expect(4); 28 | 29 | var conn = new cfg.mysql_bindings.MysqlConnection(); 30 | 31 | conn.connect(cfg.host, cfg.user, cfg.password, cfg.database_denied, function (err) { 32 | test.ok(err instanceof Error, "Error object is presented"); 33 | 34 | var 35 | connectErrno = conn.connectErrno, 36 | connectError = conn.connectError, 37 | isMatched = connectError.match(new RegExp("Access denied for user '(" + cfg.user + "|)'@'.*' to database '" + cfg.database_denied + "'")); 38 | 39 | test.equals(connectErrno, 1044, "conn.connectErrno"); 40 | 41 | if (!isMatched) { 42 | console.log("Connect error: " + connectError); 43 | } 44 | test.ok(isMatched, "conn.connectError"); 45 | 46 | test.equals(err.message, "Connection error #" + connectErrno + ": " + connectError, "Callback exception in conn.connect() to denied database"); 47 | 48 | test.done(); 49 | }); 50 | }; 51 | 52 | exports.Connect2Times = function (test) { 53 | test.expect(5); 54 | 55 | var conn = new cfg.mysql_bindings.MysqlConnection(); 56 | 57 | conn.connect(cfg.host, cfg.user, cfg.password, cfg.database, function (err) { 58 | test.ok(err === null, "conn.connect() for allowed database"); 59 | test.ok(arguments.length <= 1, "Only error arguments is possible."); 60 | 61 | conn.connect(cfg.host, cfg.user, cfg.password, cfg.database, function (err) { 62 | test.ok(err instanceof Error, "conn.connect() fails if already"); 63 | test.equal(err.message, "Already initialized. Use conn.realConnectSync() after conn.initSync()"); 64 | test.ok(arguments.length <= 1, "Only error arguments is possible."); 65 | 66 | conn.closeSync(); 67 | 68 | test.done(); 69 | }); 70 | }); 71 | }; 72 | 73 | exports.ConnectAfterConnectSync2 = function (test) { 74 | test.expect(4); 75 | 76 | var conn = new cfg.mysql_bindings.MysqlConnection(); 77 | 78 | test.ok(conn.connectSync(cfg.host, cfg.user, cfg.password, cfg.database)); 79 | 80 | conn.connect(cfg.host, cfg.user, cfg.password, cfg.database, function (err) { 81 | test.ok(err instanceof Error, "conn.connect() fails if already"); 82 | test.equal(err.message, "Already initialized. Use conn.realConnectSync() after conn.initSync()"); 83 | test.ok(arguments.length <= 1, "Only error arguments is possible."); 84 | 85 | conn.closeSync(); 86 | 87 | test.done(); 88 | }); 89 | }; 90 | 91 | exports.Query = function (test) { 92 | test.expect(3); 93 | 94 | var 95 | conn = cfg.mysql_libmysqlclient.createConnectionSync(cfg.host, cfg.user, cfg.password, cfg.database); 96 | 97 | conn.query("SHOW TABLES", function (err, res) { 98 | test.ok(res, "have result"); 99 | if (!res) { 100 | test.done(); 101 | return; 102 | } 103 | 104 | test.ok(res.fieldCount === 1, "show results field count === 1"); 105 | var rows = res.fetchAllSync(); 106 | res.freeSync(); 107 | test.ok(rows.some(function (r) { 108 | return r['Tables_in_' + cfg.database] === cfg.test_table; 109 | }), "find the test table in results"); 110 | conn.closeSync(); 111 | test.done(); 112 | }); 113 | }; 114 | 115 | exports.QueryWithLastInsertIdAndAffectedRows = function (test) { 116 | test.expect(8); 117 | 118 | var 119 | conn = cfg.mysql_libmysqlclient.createConnectionSync(cfg.host, cfg.user, cfg.password, cfg.database), 120 | res; 121 | 122 | res = conn.querySync("DELETE FROM " + cfg.test_table + ";"); 123 | test.strictEqual(res, true); 124 | 125 | res = conn.querySync("ALTER TABLE " + cfg.test_table + " AUTO_INCREMENT = 1;"); 126 | test.strictEqual(res, true); 127 | 128 | conn.query("INSERT INTO " + cfg.test_table + " (random_number, random_boolean) VALUES ('1', '0');", function (err, info) { 129 | test.equals(info.insertId, 1, "Last insert id"); 130 | 131 | conn.query("INSERT INTO " + cfg.test_table + " (random_number, random_boolean) VALUES ('2', '0'), ('3', '0');", function (err, info) { 132 | // For MySQL version >= 5.1.12 133 | test.equals(info.insertId, 2, "Last insert id"); 134 | 135 | conn.query("INSERT INTO " + cfg.test_table + " (random_number, random_boolean) VALUES ('4', '1'), ('5', '1');", function (err, info) { 136 | // For MySQL version >= 5.1.12 137 | test.equals(info.insertId, 4, "Last insert id"); 138 | 139 | var insertIdSync = conn.lastInsertIdSync(); 140 | test.equals(insertIdSync, 4, "Last insert id"); 141 | 142 | conn.query("UPDATE " + cfg.test_table + " SET random_number = '0' WHERE random_boolean='0';", function (err, info) { 143 | test.equals(info.affectedRows, 3, "Affected rows count"); 144 | 145 | conn.query("DELETE FROM " + cfg.test_table + " WHERE random_boolean='1';", function (err, info) { 146 | test.equals(info.affectedRows, 2, "Affected rows count"); 147 | 148 | conn.closeSync(); 149 | test.done(); 150 | }); 151 | }); 152 | }); 153 | }); 154 | }); 155 | }; 156 | 157 | exports.QueryWithError = function (test) { 158 | test.expect(5); 159 | 160 | var 161 | conn = cfg.mysql_libmysqlclient.createConnectionSync(cfg.host, cfg.user, cfg.password, cfg.database); 162 | 163 | conn.query("SHOW TABLESaagh", function (err, res) { 164 | test.ok(err, "Error object is present"); 165 | test.ok(!res, "Result is not defined"); 166 | 167 | var 168 | errno = conn.errnoSync(), 169 | error = conn.errorSync(); 170 | 171 | test.equals(errno, 1064, "conn.connectErrno"); 172 | test.ok(error.match(new RegExp("You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'TABLESaagh'")), "conn.connectError"); 173 | 174 | test.equals(err.message, "Query error #" + errno + ": " + error, "Callback exception in conn.query()"); 175 | 176 | conn.closeSync(); 177 | test.done(); 178 | }); 179 | }; 180 | 181 | exports.QueryWithoutCallback = function (test) { 182 | test.expect(5); 183 | 184 | var 185 | conn = cfg.mysql_libmysqlclient.createConnectionSync(cfg.host, cfg.user, cfg.password, cfg.database), 186 | res; 187 | 188 | res = conn.querySync("DELETE FROM " + cfg.test_table + ";"); 189 | test.strictEqual(res, true); 190 | 191 | test.doesNotThrow(function () { 192 | conn.query("INSERT INTO " + cfg.test_table + " (random_number, random_boolean) VALUES ('1', '0');"); 193 | }); 194 | 195 | conn.query("SELECT random_number, random_boolean FROM " + cfg.test_table + ";", function (err, res) { 196 | test.ok(err === null, "Error object is not present"); 197 | test.ok(res instanceof cfg.mysql_bindings.MysqlResult, "res instanceof MysqlResult"); 198 | 199 | var rows = res.fetchAllSync(); 200 | test.same(rows, [{random_number: 1, random_boolean: 0}], 201 | "Right result, one row, [{random_number: 1, random_boolean: 0}]]"); 202 | conn.closeSync(); 203 | test.done(); 204 | }); 205 | }; 206 | 207 | exports.QuerySend = function (test) { 208 | test.expect(2); 209 | 210 | var 211 | conn = cfg.mysql_libmysqlclient.createConnectionSync(cfg.host, cfg.user, cfg.password, cfg.database); 212 | 213 | conn.querySend("SHOW TABLES", function (err, res) { 214 | test.ok(res.fieldCount === 1, "show results field count === 1"); 215 | var rows = res.fetchAllSync(); 216 | res.freeSync(); 217 | test.ok(rows.some(function (r) { 218 | return r['Tables_in_' + cfg.database] === cfg.test_table; 219 | }), "find the test table in results"); 220 | conn.closeSync(); 221 | test.done(); 222 | }); 223 | }; 224 | 225 | exports.QuerySendWithLastInsertIdAndAffectedRows = function (test) { 226 | test.expect(8); 227 | 228 | var 229 | conn = cfg.mysql_libmysqlclient.createConnectionSync(cfg.host, cfg.user, cfg.password, cfg.database), 230 | res; 231 | 232 | res = conn.querySync("DELETE FROM " + cfg.test_table + ";"); 233 | test.strictEqual(res, true); 234 | 235 | res = conn.querySync("ALTER TABLE " + cfg.test_table + " AUTO_INCREMENT = 1;"); 236 | test.strictEqual(res, true); 237 | 238 | conn.querySend("INSERT INTO " + cfg.test_table + " (random_number, random_boolean) VALUES ('1', '0');", function (err, info) { 239 | test.equals(info.insertId, 1, "Last insert id"); 240 | 241 | conn.querySend("INSERT INTO " + cfg.test_table + " (random_number, random_boolean) VALUES ('2', '0'), ('3', '0');", function (err, info) { 242 | // For MySQL version >= 5.1.12 243 | test.equals(info.insertId, 2, "Last insert id"); 244 | 245 | conn.querySend("INSERT INTO " + cfg.test_table + " (random_number, random_boolean) VALUES ('4', '1'), ('5', '1');", function (err, info) { 246 | // For MySQL version >= 5.1.12 247 | test.equals(info.insertId, 4, "Last insert id"); 248 | 249 | var insertIdSync = conn.lastInsertIdSync(); 250 | test.equals(insertIdSync, 4, "Last insert id"); 251 | 252 | conn.querySend("UPDATE " + cfg.test_table + " SET random_number = '0' WHERE random_boolean='0';", function (err, info) { 253 | test.equals(info.affectedRows, 3, "Affected rows count"); 254 | 255 | conn.querySend("DELETE FROM " + cfg.test_table + " WHERE random_boolean='1';", function (err, info) { 256 | test.equals(info.affectedRows, 2, "Affected rows count"); 257 | 258 | conn.closeSync(); 259 | test.done(); 260 | }); 261 | }); 262 | }); 263 | }); 264 | }); 265 | }; 266 | 267 | exports.QuerySendWithError = function (test) { 268 | test.expect(5); 269 | 270 | var 271 | conn = cfg.mysql_libmysqlclient.createConnectionSync(cfg.host, cfg.user, cfg.password, cfg.database); 272 | 273 | conn.querySend("SHOW TABLESaagh", function (err, res) { 274 | test.ok(err, "Error object is present"); 275 | test.ok(!res, "Result is not defined"); 276 | 277 | var 278 | errno = conn.errnoSync(), 279 | error = conn.errorSync(); 280 | 281 | test.equals(errno, 1064, "conn.connectErrno"); 282 | test.ok(error.match(new RegExp("You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'TABLESaagh'")), "conn.connectError"); 283 | 284 | test.equals(err.message, "Query error #" + errno + ": " + error, "Callback exception in conn.query()"); 285 | 286 | conn.closeSync(); 287 | test.done(); 288 | }); 289 | }; 290 | -------------------------------------------------------------------------------- /tests/low-level-async/test-class-mysqlresult-async.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright by Oleg Efimov and node-mysql-libmysqlclient contributors 3 | See contributors list in README 4 | 5 | See license text in LICENSE file 6 | */ 7 | 8 | // Load configuration 9 | var cfg = require('../config.js'); 10 | 11 | exports.setupTestTable = function (test) { 12 | test.expect(1); 13 | 14 | var conn = cfg.mysql_libmysqlclient.createConnectionSync(cfg.host, cfg.user, cfg.password, cfg.database); 15 | 16 | res = conn.querySync("DELETE FROM " + cfg.test_table + ";"); 17 | res = conn.querySync("INSERT INTO " + cfg.test_table + 18 | " (random_number, random_boolean) VALUES ('1', '1');") && res; 19 | res = conn.querySync("INSERT INTO " + cfg.test_table + 20 | " (random_number, random_boolean) VALUES ('2', '1');") && res; 21 | res = conn.querySync("INSERT INTO " + cfg.test_table + 22 | " (random_number, random_boolean) VALUES ('3', '0');") && res; 23 | test.ok(res, "INSERT"); 24 | 25 | test.done(); 26 | }; 27 | 28 | exports.FetchAll = function (test) { 29 | test.expect(3); 30 | 31 | var 32 | conn = cfg.mysql_libmysqlclient.createConnectionSync(cfg.host, cfg.user, cfg.password, cfg.database), 33 | res; 34 | 35 | res = conn.querySync( 36 | "SELECT random_number FROM " + cfg.test_table + " WHERE random_boolean='1';" 37 | ); 38 | 39 | res.fetchAll(function (err, rows, fields) { 40 | test.ok(err === null, "res.fetchAll() err===null"); 41 | 42 | test.same(rows, [{random_number: 1}, {random_number: 2}], "conn.querySync('SELECT ...').fetchAll()"); 43 | test.same(fields, res.fetchFieldsSync(), "Callback fields argument == res.fetchFieldsSync()"); 44 | 45 | res.freeSync(); 46 | conn.closeSync(); 47 | 48 | test.done(); 49 | }); 50 | }; 51 | 52 | exports.ResultObjectManipulationsAfterFetchAll = function (test) { 53 | test.expect(4); 54 | 55 | var 56 | conn = cfg.mysql_libmysqlclient.createConnectionSync(cfg.host, cfg.user, cfg.password, cfg.database), 57 | res; 58 | 59 | res = conn.querySync( 60 | "SELECT random_number FROM " + cfg.test_table + " WHERE random_boolean='1';" 61 | ); 62 | 63 | res.fetchAll(function (err, rows, fields) { 64 | test.ok(err === null, "res.fetchAll() err===null"); 65 | 66 | test.same(rows, [{random_number: 1}, {random_number: 2}], "conn.querySync('SELECT ...').fetchAll()"); 67 | test.same(fields, res.fetchFieldsSync(), "Callback fields argument == res.fetchFieldsSync()"); 68 | 69 | test.doesNotThrow(function () { 70 | var numRows = res.numRowsSync(); 71 | }); 72 | 73 | res.freeSync(); 74 | conn.closeSync(); 75 | 76 | test.done(); 77 | }); 78 | }; 79 | -------------------------------------------------------------------------------- /tests/low-level-async/test-createconnection-async.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright by Oleg Efimov and node-mysql-libmysqlclient contributors 3 | See contributors list in README 4 | 5 | See license text in LICENSE file 6 | */ 7 | 8 | // Load configuration 9 | var cfg = require('../config.js'); 10 | 11 | exports.mysql_libmysqlclient_createConnection_0 = function (test) { 12 | test.expect(1); 13 | 14 | test.throws(function () { 15 | cfg.mysql_libmysqlclient.createConnection(); 16 | }, "require('mysql-libmysqlclient').createConnection() must get callback as last argument"); 17 | 18 | test.done(); 19 | }; 20 | 21 | exports.mysql_libmysqlclient_createConnection_1_NoFunction = function (test) { 22 | test.expect(1); 23 | 24 | test.throws(function () { 25 | cfg.mysql_libmysqlclient.createConnection(cfg.host); 26 | }, "require('mysql-libmysqlclient').createConnection() must get callback as last argument"); 27 | 28 | test.done(); 29 | }; 30 | 31 | exports.mysql_libmysqlclient_createConnection_1_Function = function (test) { 32 | test.expect(2); 33 | 34 | cfg.mysql_libmysqlclient.createConnection(function (err, conn) { 35 | test.ok(err === null, "Error object is not present"); 36 | test.ok(conn instanceof cfg.mysql_bindings.MysqlConnection, "conn instanceof MysqlConnection"); 37 | 38 | if (conn.connectedSync()) { 39 | conn.closeSync(); 40 | } 41 | 42 | test.done(); 43 | }); 44 | }; 45 | 46 | exports.mysql_libmysqlclient_createConnection_2 = function (test) { 47 | test.expect(3); 48 | 49 | cfg.mysql_libmysqlclient.createConnection(cfg.host, function (err, conn) { 50 | test.ok(err instanceof Error, "Error object is present"); 51 | test.ok(!conn, "Connection object is not defined"); 52 | 53 | test.ok(err.message.match(/Connection error.*Access denied for user/)); 54 | 55 | test.done(); 56 | }); 57 | }; 58 | 59 | exports.mysql_libmysqlclient_createConnection_3_Function = function (test) { 60 | test.expect(3); 61 | 62 | cfg.mysql_libmysqlclient.createConnection(cfg.host, cfg.user, function (err, conn) { 63 | test.ok(err instanceof Error, "Error object is present"); 64 | test.ok(!conn, "Connection object is not defined"); 65 | 66 | var error = "Access denied for user '" + cfg.user + "'@'" + cfg.host + "' (using password: NO)"; 67 | var errno = 1045; 68 | 69 | test.equals(err.message, "Connection error #" + errno + ": " + error, "Callback exception"); 70 | 71 | if (conn && conn.connectedSync()) { 72 | conn.closeSync(); 73 | } 74 | 75 | test.done(); 76 | }); 77 | }; 78 | 79 | exports.mysql_libmysqlclient_createConnection_3_NoFunction = function (test) { 80 | test.expect(1); 81 | 82 | test.throws(function () { 83 | cfg.mysql_libmysqlclient.createConnection(cfg.host, cfg.user, cfg.password); 84 | }, "require('mysql-libmysqlclient').createConnection() must get callback as last argument"); 85 | 86 | test.done(); 87 | }; 88 | 89 | exports.mysql_libmysqlclient_createConnection_4 = function (test) { 90 | test.expect(2); 91 | 92 | cfg.mysql_libmysqlclient.createConnection(cfg.host, cfg.user, cfg.password, function (err, conn) { 93 | test.ok(err === null, "Error object is not present"); 94 | test.ok(conn instanceof cfg.mysql_bindings.MysqlConnection, "conn instanceof MysqlConnection"); 95 | 96 | if (conn.connectedSync()) { 97 | conn.closeSync(); 98 | } 99 | 100 | test.done(); 101 | }); 102 | }; 103 | 104 | exports.mysql_libmysqlclient_createConnection_5_AccessAllowed = function (test) { 105 | test.expect(3); 106 | 107 | cfg.mysql_libmysqlclient.createConnection(cfg.host, cfg.user, cfg.password, cfg.database, function (err, conn) { 108 | test.ok(err === null, "Error object is not present"); 109 | test.ok(conn instanceof cfg.mysql_bindings.MysqlConnection, "conn instanceof MysqlConnection"); 110 | 111 | var isConnected = conn.connectedSync(); 112 | test.ok(isConnected, "cfg.mysql_libmysqlclient.createConnection(host, user, password, database, callback)"); 113 | 114 | if (!isConnected) { 115 | // Extra debug output 116 | console.log("Error:" + conn.connectError); 117 | } else { 118 | conn.closeSync(); 119 | } 120 | 121 | test.done(); 122 | }); 123 | }; 124 | 125 | exports.mysql_libmysqlclient_createConnection_5_AccessDenied = function (test) { 126 | test.expect(3); 127 | 128 | cfg.mysql_libmysqlclient.createConnection(cfg.host, cfg.user, cfg.password, cfg.database_denied, function (err, conn) { 129 | test.ok(err, "Error object is present"); 130 | test.ok(!conn, "Connection object is not defined"); 131 | 132 | var error = "Access denied for user '" + cfg.user + "'@'" + cfg.host + "' to database '" + cfg.database_denied + "'"; 133 | var errno = 1044; 134 | 135 | test.equals(err.message, "Connection error #" + errno + ": " + error, "Callback exception"); 136 | 137 | test.done(); 138 | }); 139 | }; 140 | 141 | exports.mysql_libmysqlclient_createConnection_6 = function (test) { 142 | test.expect(3); 143 | 144 | cfg.mysql_libmysqlclient.createConnection(cfg.host, cfg.user, cfg.password, cfg.database, cfg.port, function (err, conn) { 145 | test.ok(err === null, "Error object is not present"); 146 | test.ok(conn instanceof cfg.mysql_bindings.MysqlConnection, "conn instanceof MysqlConnection"); 147 | 148 | var isConnected = conn.connectedSync(); 149 | test.ok(isConnected, "cfg.mysql_libmysqlclient.createConnection(host, user, password, database, flags, callback)"); 150 | 151 | if (!isConnected) { 152 | // Extra debug output 153 | console.log("Error:" + conn.connectError); 154 | } else { 155 | conn.closeSync(); 156 | } 157 | 158 | test.done(); 159 | }); 160 | }; 161 | 162 | exports.mysql_libmysqlclient_createConnection_8 = function (test) { 163 | test.expect(3); 164 | 165 | var compress_flag = cfg.mysql_bindings.CLIENT_COMPRESS; 166 | 167 | cfg.mysql_libmysqlclient.createConnection(cfg.host, cfg.user, cfg.password, cfg.database, null, null, compress_flag, function (err, conn) { 168 | test.ok(err === null, "Error object is not present"); 169 | test.ok(conn instanceof cfg.mysql_bindings.MysqlConnection, "conn instanceof MysqlConnection"); 170 | 171 | var isConnected = conn.connectedSync(); 172 | test.ok(isConnected, "cfg.mysql_libmysqlclient.createConnection(host, user, password, database, flags, callback)"); 173 | 174 | if (!isConnected) { 175 | // Extra debug output 176 | console.log("Error:" + conn.connectError); 177 | } else { 178 | conn.closeSync(); 179 | } 180 | 181 | test.done(); 182 | }); 183 | }; 184 | 185 | exports.mysql_libmysqlclient_createConnectionSync_DSN_1 = function (test) { 186 | test.expect(3); 187 | 188 | var dsn = require('util').format("mysql://%s:%s@%s:%s", cfg.user, cfg.password, cfg.host, cfg.port); 189 | 190 | cfg.mysql_libmysqlclient.createConnection(dsn, function (err, conn) { 191 | test.ok(err === null, "Error object is not present"); 192 | test.ok(conn instanceof cfg.mysql_bindings.MysqlConnection, "conn instanceof MysqlConnection"); 193 | 194 | var isConnected = conn.connectedSync(); 195 | test.ok(isConnected, "cfg.mysql_libmysqlclient.createConnection(dsn(user, password, host, port), callback)"); 196 | 197 | if (!isConnected) { 198 | // Extra debug output 199 | console.log("Error:" + conn.connectError); 200 | } else { 201 | conn.closeSync(); 202 | } 203 | 204 | test.done(); 205 | }); 206 | }; 207 | 208 | exports.mysql_libmysqlclient_createConnectionSync_DSN_2 = function (test) { 209 | test.expect(3); 210 | 211 | var dsn = require('util').format("mysql://%s:%s@%s:%s?qwerty=1234", cfg.user, cfg.password, cfg.host, cfg.port); 212 | 213 | cfg.mysql_libmysqlclient.createConnection(dsn, function (err, conn) { 214 | test.ok(err === null, "Error object is not present"); 215 | test.ok(conn instanceof cfg.mysql_bindings.MysqlConnection, "conn instanceof MysqlConnection"); 216 | 217 | var isConnected = conn.connectedSync(); 218 | test.ok(isConnected, "cfg.mysql_libmysqlclient.createConnection(dsn(user, password, host, port), callback)"); 219 | 220 | if (!isConnected) { 221 | // Extra debug output 222 | console.log("Error:" + conn.connectError); 223 | } else { 224 | conn.closeSync(); 225 | } 226 | 227 | test.done(); 228 | }); 229 | }; 230 | 231 | exports.mysql_libmysqlclient_createConnectionSync_DSN_3 = function (test) { 232 | test.expect(3); 233 | 234 | var dsn = require('util').format("mysql://%s:%s@%s:%s/%s/zxcvbn?qwerty=1234", cfg.user, cfg.password, cfg.host, cfg.port, cfg.database); 235 | 236 | cfg.mysql_libmysqlclient.createConnection(dsn, function (err, conn) { 237 | test.ok(err === null, "Error object is not present"); 238 | test.ok(conn instanceof cfg.mysql_bindings.MysqlConnection, "conn instanceof MysqlConnection"); 239 | 240 | var isConnected = conn.connectedSync(); 241 | test.ok(isConnected, "cfg.mysql_libmysqlclient.createConnection(dsn(user, password, host, port, database), callback)"); 242 | 243 | if (!isConnected) { 244 | // Extra debug output 245 | console.log("Error:" + conn.connectError); 246 | } else { 247 | conn.closeSync(); 248 | } 249 | 250 | test.done(); 251 | }); 252 | }; 253 | -------------------------------------------------------------------------------- /tests/low-level-sync/setup-low-level-sync.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright by Oleg Efimov and node-mysql-libmysqlclient contributors 3 | See contributors list in README 4 | 5 | See license text in LICENSE file 6 | */ 7 | 8 | // Load configuration 9 | var cfg = require('../config.js'); 10 | 11 | exports.createTestTableSimple = function (test) { 12 | test.expect(3); 13 | 14 | var 15 | conn = cfg.mysql_libmysqlclient.createConnectionSync(cfg.host, cfg.user, cfg.password, cfg.database), 16 | res, 17 | tables; 18 | 19 | if (conn.connectErrno) { 20 | console.log("Failed to connect as " + cfg.user + "@" + cfg.host + ": " + conn.connectError); 21 | } 22 | 23 | test.ok(conn, "mysql_libmysqlclient.createConnectionSync(host, user, password, database)"); 24 | 25 | conn.querySync("DROP TABLE IF EXISTS " + cfg.test_table + ";"); 26 | conn.querySync("CREATE TABLE " + cfg.test_table + 27 | " (id INT(8) NOT NULL AUTO_INCREMENT, " + 28 | "random_number INT(8) NOT NULL DEFAULT 10, " + 29 | "random_boolean BOOLEAN NOT NULL DEFAULT 1, " + 30 | "PRIMARY KEY(id)) " + cfg.store_engine + ";"); 31 | res = conn.querySync("SHOW TABLES"); 32 | test.ok(res.fieldCount === 1, "SHOW TABLES result field count === 1"); 33 | tables = res.fetchAllSync(); 34 | test.ok(tables.some(function (r) { 35 | return r['Tables_in_' + cfg.database] === cfg.test_table; 36 | }), "Find the test table in result"); 37 | 38 | conn.querySync("DROP TABLE IF EXISTS " + cfg.test_table_notexists + ";"); 39 | 40 | conn.closeSync(); 41 | 42 | test.done(); 43 | }; 44 | 45 | -------------------------------------------------------------------------------- /tests/low-level-sync/test-connect-different-args.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright by Oleg Efimov and node-mysql-libmysqlclient contributors 3 | See contributors list in README 4 | 5 | See license text in LICENSE file 6 | */ 7 | 8 | // Load configuration 9 | var cfg = require("../config.js"); 10 | 11 | exports.ConnectSync_WithoutDb = function (test) { 12 | test.expect(1); 13 | 14 | var conn = cfg.mysql_libmysqlclient.createConnectionSync(); 15 | test.ok(conn.connectSync(cfg.host, cfg.user, cfg.password), "conn.connectSync() without database selection"); 16 | conn.closeSync(); 17 | 18 | test.done(); 19 | }; 20 | 21 | exports.ConnectSync_ManyTimes = function (test) { 22 | test.expect(1); 23 | 24 | var conn = cfg.mysql_libmysqlclient.createConnectionSync(), i; 25 | for (i = 1; i <= cfg.reconnect_count; i += 1) { 26 | conn.connectSync(cfg.host, cfg.user, cfg.password); 27 | conn.closeSync(); 28 | } 29 | test.ok(conn.connectSync(cfg.host, cfg.user, cfg.password), "conn.connect() after many times connect"); 30 | conn.closeSync(); 31 | 32 | test.done(); 33 | }; 34 | 35 | exports.ConnectSync_AllowedDb = function (test) { 36 | test.expect(1); 37 | 38 | var conn = cfg.mysql_libmysqlclient.createConnectionSync(); 39 | test.ok(conn.connectSync(cfg.host, cfg.user, cfg.password, cfg.database), "conn.connect() for allowed database"); 40 | conn.closeSync(); 41 | 42 | test.done(); 43 | }; 44 | 45 | exports.ConnectSync_DeniedDb = function (test) { 46 | test.expect(1); 47 | 48 | var conn = cfg.mysql_libmysqlclient.createConnectionSync(); 49 | test.ok(!conn.connectSync(cfg.host, cfg.user, cfg.password, cfg.database_denied), "conn.connect() for denied database"); 50 | 51 | test.done(); 52 | }; 53 | 54 | exports.ConnectSync_DeniedFollowedByAllowedDb = function (test) { 55 | test.expect(2); 56 | 57 | var conn = cfg.mysql_libmysqlclient.createConnectionSync(); 58 | test.ok(!conn.connectSync(cfg.host, cfg.user, cfg.password, cfg.database_denied), "conn.connect() for denied database"); 59 | test.ok(conn.connectSync(cfg.host, cfg.user, cfg.password, cfg.database), "conn.connect() for allowed database"); 60 | conn.closeSync(); 61 | 62 | test.done(); 63 | }; 64 | 65 | -------------------------------------------------------------------------------- /tests/low-level-sync/test-createconnection-sync.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright by Oleg Efimov and node-mysql-libmysqlclient contributors 3 | See contributors list in README 4 | 5 | See license text in LICENSE file 6 | */ 7 | 8 | // Load configuration 9 | var cfg = require('../config.js'); 10 | 11 | exports.mysql_libmysqlclient_createConnectionSync_0 = function (test) { 12 | test.expect(1); 13 | 14 | var conn = cfg.mysql_libmysqlclient.createConnectionSync(); 15 | test.ok(conn instanceof cfg.mysql_bindings.MysqlConnection, "mysql_libmysqlclient.createConnectionSync()"); 16 | 17 | if (conn.connectedSync()) { 18 | conn.closeSync(); 19 | } 20 | 21 | test.done(); 22 | }; 23 | 24 | exports.mysql_libmysqlclient_createConnectionSync_1 = function (test) { 25 | test.expect(2); 26 | 27 | var conn = cfg.mysql_libmysqlclient.createConnectionSync(cfg.host); 28 | test.ok(conn instanceof cfg.mysql_bindings.MysqlConnection, "mysql_libmysqlclient.createConnectionSync(host)"); 29 | 30 | test.ok(conn.connectError.match(/Access denied for user/)); 31 | 32 | test.done(); 33 | }; 34 | 35 | exports.mysql_libmysqlclient_createConnectionSync_2 = function (test) { 36 | test.expect(2); 37 | 38 | var conn = cfg.mysql_libmysqlclient.createConnectionSync(cfg.host, cfg.user), isConnected; 39 | test.ok(conn instanceof cfg.mysql_bindings.MysqlConnection, "mysql_libmysqlclient.createConnectionSync(host, user)"); 40 | 41 | // This depends on password, connect(host, user) === connect(host, user, NULL) 42 | if (!cfg.password) { 43 | isConnected = conn.connectedSync(); 44 | test.ok(isConnected, "mysql_libmysqlclient.createConnectionSync(host, user).connectedSync()"); 45 | 46 | if (!isConnected) { 47 | // Extra debug output 48 | console.log("Error: " + conn.connectError); 49 | } else { 50 | conn.closeSync(); 51 | } 52 | } else { 53 | test.equals(conn.connectError, 54 | "Access denied for user '" + cfg.user + "'@'" + cfg.host + "' (using password: NO)", 55 | "mysql_libmysqlclient.createConnectionSync(host, user).connectedSync()"); 56 | } 57 | 58 | test.done(); 59 | }; 60 | 61 | exports.mysql_libmysqlclient_createConnectionSync_3 = function (test) { 62 | test.expect(2); 63 | 64 | var conn = cfg.mysql_libmysqlclient.createConnectionSync(cfg.host, cfg.user, cfg.password), isConnected; 65 | test.ok(conn instanceof cfg.mysql_bindings.MysqlConnection, "cfg.mysql_libmysqlclient.createConnectionSync(host, user, password)"); 66 | 67 | isConnected = conn.connectedSync(); 68 | test.ok(isConnected, "cfg.mysql_libmysqlclient.createConnectionSync(host, user, password).connectedSync()"); 69 | 70 | if (!isConnected) { 71 | // Extra debug output 72 | console.log("Error:" + conn.connectError); 73 | } else { 74 | conn.closeSync(); 75 | } 76 | 77 | test.done(); 78 | }; 79 | 80 | exports.mysql_libmysqlclient_createConnectionSync_4_AccessAllowed = function (test) { 81 | test.expect(2); 82 | 83 | var conn = cfg.mysql_libmysqlclient.createConnectionSync(cfg.host, cfg.user, cfg.password, cfg.database), isConnected; 84 | test.ok(conn instanceof cfg.mysql_bindings.MysqlConnection, "cfg.mysql_libmysqlclient.createConnectionSync(host, user, password, database)"); 85 | 86 | isConnected = conn.connectedSync(); 87 | test.ok(isConnected, "cfg.mysql_libmysqlclient.createConnectionSync(host, user, password, database) connects"); 88 | 89 | if (!isConnected) { 90 | // Extra debug output 91 | console.log("Error:" + conn.connectError); 92 | } else { 93 | conn.closeSync(); 94 | } 95 | 96 | test.done(); 97 | }; 98 | 99 | exports.mysql_libmysqlclient_createConnectionSync_4_AccessDenied = function (test) { 100 | test.expect(3); 101 | 102 | var conn = cfg.mysql_libmysqlclient.createConnectionSync(cfg.host, cfg.user, cfg.password, cfg.database_denied), isConnected; 103 | test.ok(conn instanceof cfg.mysql_bindings.MysqlConnection, "cfg.mysql_libmysqlclient.createConnectionSync(host, user, password, database_denied)"); 104 | 105 | isConnected = conn.connectedSync(); 106 | test.ok(!isConnected, "cfg.mysql_libmysqlclient.createConnectionSync(host, user, password, database_denied) not connects"); 107 | test.equals(conn.connectError, 108 | "Access denied for user '" + cfg.user + "'@'" + cfg.host + "' to database '" + cfg.database_denied + "'", 109 | "cfg.mysql_libmysqlclient.createConnectionSync(cfg.host, cfg.user, cfg.password, cfg.database_denied).connectError"); 110 | 111 | if (isConnected) { 112 | conn.closeSync(); 113 | } 114 | 115 | test.done(); 116 | }; 117 | 118 | exports.mysql_libmysqlclient_createConnectionSync_5 = function (test) { 119 | test.expect(2); 120 | 121 | var 122 | conn = cfg.mysql_libmysqlclient.createConnectionSync(cfg.host, cfg.user, cfg.password, cfg.database, cfg.port), 123 | isConnected; 124 | test.ok(conn instanceof cfg.mysql_bindings.MysqlConnection, "cfg.mysql_libmysqlclient.createConnectionSync(host, user, password, database, null, port)"); 125 | 126 | isConnected = conn.connectedSync(); 127 | test.ok(isConnected, "cfg.mysql_libmysqlclient.createConnectionSync(host, user, password, database, null, port) connects"); 128 | 129 | if (!isConnected) { 130 | // Extra debug output 131 | console.log("Error:" + conn.connectError); 132 | } else { 133 | conn.closeSync(); 134 | } 135 | 136 | test.done(); 137 | }; 138 | 139 | exports.mysql_libmysqlclient_createConnectionSync_7 = function (test) { 140 | test.expect(2); 141 | 142 | var 143 | compress_flag = cfg.mysql_bindings.CLIENT_COMPRESS, 144 | conn = cfg.mysql_libmysqlclient.createConnectionSync(cfg.host, cfg.user, cfg.password, cfg.database, null, null, compress_flag), 145 | isConnected; 146 | test.ok(conn instanceof cfg.mysql_bindings.MysqlConnection, "cfg.mysql_libmysqlclient.createConnectionSync(host, user, password, database, flags)"); 147 | 148 | isConnected = conn.connectedSync(); 149 | test.ok(isConnected, "cfg.mysql_libmysqlclient.createConnectionSync(host, user, password, database, flags) connects"); 150 | 151 | if (!isConnected) { 152 | // Extra debug output 153 | console.log("Error:" + conn.connectError); 154 | } else { 155 | conn.closeSync(); 156 | } 157 | 158 | test.done(); 159 | }; 160 | 161 | exports.mysql_libmysqlclient_createConnectionSync_DSN_1 = function (test) { 162 | test.expect(2); 163 | 164 | var 165 | dsn = require('util').format("mysql://%s:%s@%s:%s", cfg.user, cfg.password, cfg.host, cfg.port), 166 | conn = cfg.mysql_libmysqlclient.createConnectionSync(dsn), 167 | isConnected; 168 | test.ok(conn instanceof cfg.mysql_bindings.MysqlConnection, "cfg.mysql_libmysqlclient.createConnectionSync(dsn(user, password, host, port))"); 169 | 170 | isConnected = conn.connectedSync(); 171 | test.ok(isConnected, "cfg.mysql_libmysqlclient.createConnectionSync(dsn(user, password, host, port)) connects"); 172 | 173 | if (!isConnected) { 174 | // Extra debug output 175 | console.log("Error:" + conn.connectError); 176 | } else { 177 | conn.closeSync(); 178 | } 179 | 180 | test.done(); 181 | }; 182 | 183 | exports.mysql_libmysqlclient_createConnectionSync_DSN_2 = function (test) { 184 | test.expect(2); 185 | 186 | var 187 | dsn = require('util').format("mysql://%s:%s@%s:%s?qwerty=1234", cfg.user, cfg.password, cfg.host, cfg.port), 188 | conn = cfg.mysql_libmysqlclient.createConnectionSync(dsn), 189 | isConnected; 190 | test.ok(conn instanceof cfg.mysql_bindings.MysqlConnection, "cfg.mysql_libmysqlclient.createConnectionSync(dsn(user, password, host, port))"); 191 | 192 | isConnected = conn.connectedSync(); 193 | test.ok(isConnected, "cfg.mysql_libmysqlclient.createConnectionSync(dsn(user, password, host, port)) connects"); 194 | 195 | if (!isConnected) { 196 | // Extra debug output 197 | console.log("Error:" + conn.connectError); 198 | } else { 199 | conn.closeSync(); 200 | } 201 | 202 | test.done(); 203 | }; 204 | 205 | exports.mysql_libmysqlclient_createConnectionSync_DSN_3 = function (test) { 206 | test.expect(2); 207 | 208 | var 209 | dsn = require('util').format("mysql://%s:%s@%s:%s/%s/zxcvbn?qwerty=1234", cfg.user, cfg.password, cfg.host, cfg.port, cfg.database), 210 | conn = cfg.mysql_libmysqlclient.createConnectionSync(dsn), 211 | isConnected; 212 | test.ok(conn instanceof cfg.mysql_bindings.MysqlConnection, "cfg.mysql_libmysqlclient.createConnectionSync(dsn(user, password, host, port, database))"); 213 | 214 | isConnected = conn.connectedSync(); 215 | test.ok(isConnected, "cfg.mysql_libmysqlclient.createConnectionSync(dsn(user, password, host, port, database)) connects"); 216 | 217 | if (!isConnected) { 218 | // Extra debug output 219 | console.log("Error:" + conn.connectError); 220 | } else { 221 | conn.closeSync(); 222 | } 223 | 224 | test.done(); 225 | }; 226 | -------------------------------------------------------------------------------- /tests/slow/test-connect.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright by Oleg Efimov and node-mysql-libmysqlclient contributors 3 | See contributors list in README 4 | 5 | See license text in LICENSE file 6 | */ 7 | 8 | // Load configuration 9 | var cfg = require('../config'); 10 | 11 | exports.ConnectsNested = function (test) { 12 | test.expect(1); 13 | 14 | var 15 | conn = cfg.mysql_libmysqlclient.createConnectionSync(cfg.host, cfg.user, cfg.password, cfg.database), 16 | test_order = ""; 17 | 18 | test_order += "s"; 19 | 20 | conn.closeSync(); 21 | conn.connect(cfg.host, cfg.user, cfg.password, function (err) { 22 | if (err) { 23 | throw err; 24 | } 25 | 26 | test_order += "1"; 27 | 28 | conn.closeSync(); 29 | conn.connect(cfg.host, cfg.user, cfg.password, function (err) { 30 | if (err) { 31 | throw err; 32 | } 33 | 34 | test_order += "2"; 35 | 36 | conn.closeSync(); 37 | conn.connect(cfg.host, cfg.user, cfg.password, function (err) { 38 | if (err) { 39 | throw err; 40 | } 41 | 42 | test_order += "3"; 43 | 44 | (function () { 45 | test.equals(test_order, "sf123"); 46 | 47 | conn.closeSync(); 48 | test.done(); 49 | }()); 50 | }); 51 | }); 52 | }); 53 | 54 | test_order += "f"; 55 | }; 56 | 57 | exports.ManyConnectsNested = function (test) { 58 | test.expect(0); 59 | 60 | var 61 | conn = cfg.mysql_libmysqlclient.createConnectionSync(), 62 | helper, 63 | i = 0; 64 | 65 | helper = function () { 66 | i += 1; 67 | if (i <= cfg.slow_connects_nested) { 68 | conn.connect(cfg.host, cfg.user, cfg.password, cfg.database, function (err) { 69 | if (err) { 70 | throw err; 71 | } 72 | 73 | conn.closeSync(); 74 | 75 | helper(); 76 | }); 77 | } else { 78 | test.done(); 79 | } 80 | }; 81 | 82 | helper(); 83 | }; 84 | 85 | exports.ManyConnectsInLoop = function (test) { 86 | test.expect(0); 87 | 88 | var 89 | connections = [], 90 | test_result, 91 | i = 0, ci = 0; 92 | 93 | for (i = 0; i < cfg.slow_connects_inloop; i += 1) { 94 | connections[i] = cfg.mysql_libmysqlclient.createConnectionSync(); 95 | } 96 | 97 | for (i = 0; i < cfg.slow_connects_inloop; i += 1) { 98 | connections[i].connect(cfg.host, cfg.user, cfg.password, cfg.database, function (err) { 99 | if (err) { 100 | console.log("Error:" + err); 101 | throw err; 102 | } 103 | 104 | ci += 1; 105 | 106 | if (ci === cfg.slow_connects_inloop) { 107 | for (i = 0; i < cfg.slow_connects_inloop; i += 1) { 108 | connections[i].closeSync(); 109 | } 110 | 111 | test.done(); 112 | } 113 | }); 114 | } 115 | }; 116 | 117 | -------------------------------------------------------------------------------- /tests/slow/test-fetchAll.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright by Oleg Efimov and node-mysql-libmysqlclient contributors 3 | See contributors list in README 4 | 5 | See license text in LICENSE file 6 | */ 7 | 8 | // Load configuration 9 | var cfg = require('../config'); 10 | 11 | exports.FetchesNested = function (test) { 12 | test.expect(5); 13 | 14 | var 15 | conn = cfg.mysql_libmysqlclient.createConnectionSync(cfg.host, cfg.user, cfg.password, cfg.database), 16 | t1, t2, t3, 17 | test_order = ""; 18 | 19 | test_order += "s"; 20 | 21 | conn.querySync("SHOW TABLES;").fetchAll(function (err, tables) { 22 | if (err) { 23 | throw err; 24 | } 25 | 26 | t1 = tables; 27 | 28 | test_order += "1"; 29 | 30 | conn.querySync("SHOW TABLES;").fetchAll(function (err, tables) { 31 | if (err) { 32 | throw err; 33 | } 34 | 35 | t2 = tables; 36 | 37 | test_order += "2"; 38 | 39 | conn.querySync("SHOW TABLES;").fetchAll(function (err, tables) { 40 | if (err) { 41 | throw err; 42 | } 43 | 44 | t3 = tables; 45 | 46 | test_order += "3"; 47 | 48 | (function () { 49 | test.equals(test_order, "sf123"); 50 | 51 | tables = conn.querySync("SHOW TABLES;").fetchAllSync(); 52 | test.ok(tables.some(function (r) { 53 | return r['Tables_in_' + cfg.database] === cfg.test_table; 54 | }), "Find the test table in result"); 55 | test.same(t1, tables); 56 | test.same(t2, tables); 57 | test.same(t3, tables); 58 | 59 | conn.closeSync(); 60 | 61 | test.done(); 62 | }()); 63 | }); 64 | }); 65 | }); 66 | 67 | test_order += "f"; 68 | }; 69 | 70 | exports.ManyFetchesNested = function (test) { 71 | test.expect(1); 72 | 73 | var 74 | conn = cfg.mysql_libmysqlclient.createConnectionSync(cfg.host, cfg.user, cfg.password, cfg.database), 75 | helper, 76 | initial_result, 77 | test_result, 78 | i = 0; 79 | 80 | initial_result = conn.querySync("SHOW TABLES;").fetchAllSync(); 81 | 82 | helper = function () { 83 | i += 1; 84 | if (i <= cfg.slow_fetches_nested) { 85 | conn.querySync("SHOW TABLES;").fetchAll(function (err, tables) { 86 | if (err) { 87 | throw err; 88 | } 89 | 90 | helper(); 91 | }); 92 | } else { 93 | test_result = conn.querySync("SHOW TABLES;").fetchAllSync(); 94 | test.same(test_result, initial_result); 95 | 96 | if (cfg.slow_fetches_nested <= 0) { 97 | console.log("ManyFetchesNested test ignored, cfg.slow_fetches_nested <=0"); 98 | } 99 | 100 | conn.closeSync(); 101 | test.done(); 102 | } 103 | }; 104 | 105 | helper(); 106 | }; 107 | 108 | exports.ManyFetchesInLoop = function (test) { 109 | test.expect(1); 110 | 111 | var 112 | conn = cfg.mysql_libmysqlclient.createConnectionSync(cfg.host, cfg.user, cfg.password, cfg.database), 113 | initial_result, 114 | test_result, 115 | i = 0, ci = 0; 116 | 117 | if (cfg.slow_fetches_inloop <= 0) { 118 | console.log("ManyFetchesInLoop test ignored, cfg.slow_fetches_inloop <=0"); 119 | conn.closeSync(); 120 | test.done(); 121 | return; 122 | } 123 | 124 | initial_result = conn.querySync("SHOW TABLES;").fetchAllSync(); 125 | 126 | for (i = 0; i < cfg.slow_fetches_inloop; i += 1) { 127 | conn.querySync("SHOW TABLES;").fetchAll(function (err, tables) { 128 | if (err) { 129 | throw err; 130 | } 131 | 132 | ci += 1; 133 | 134 | if (ci === cfg.slow_fetches_inloop) { 135 | test_result = conn.querySync("SHOW TABLES;").fetchAllSync(); 136 | test.same(test_result, initial_result); 137 | 138 | conn.closeSync(); 139 | test.done(); 140 | } 141 | }); 142 | } 143 | }; 144 | 145 | -------------------------------------------------------------------------------- /tests/slow/test-query.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright by Oleg Efimov and node-mysql-libmysqlclient contributors 3 | See contributors list in README 4 | 5 | See license text in LICENSE file 6 | */ 7 | 8 | // Load configuration 9 | var cfg = require('../config'); 10 | 11 | exports.Setup = function (test) { 12 | test.expect(0); 13 | 14 | var conn = cfg.mysql_libmysqlclient.createConnectionSync(cfg.host, cfg.user, cfg.password, cfg.database); 15 | 16 | conn.querySync("DROP TABLE IF EXISTS " + cfg.test_table + ";"); 17 | conn.querySync("CREATE TABLE " + cfg.test_table + 18 | " (number INT(8) NOT NULL) ENGINE=MEMORY;"); 19 | 20 | conn.closeSync(); 21 | 22 | test.done(); 23 | }; 24 | 25 | exports.QueryNested = function (test) { 26 | test.expect(2); 27 | 28 | var 29 | conn = cfg.mysql_libmysqlclient.createConnectionSync(cfg.host, cfg.user, cfg.password, cfg.database), 30 | test_result, 31 | test_order = ""; 32 | 33 | test_order += "s"; 34 | 35 | conn.query("INSERT INTO " + cfg.test_table + " (number) VALUES ('1');", function (err, res) { 36 | if (err) { 37 | throw err; 38 | } 39 | 40 | test_order += "1"; 41 | 42 | conn.query("INSERT INTO " + cfg.test_table + " (number) VALUES ('2');", function (err, res) { 43 | if (err) { 44 | throw err; 45 | } 46 | 47 | test_order += "2"; 48 | 49 | conn.query("INSERT INTO " + cfg.test_table + " (number) VALUES ('3');", function (err, res) { 50 | if (err) { 51 | throw err; 52 | } 53 | 54 | test_order += "3"; 55 | 56 | (function () { 57 | test.equals(test_order, "sf123"); 58 | 59 | test_result = conn.querySync("SELECT number FROM " + cfg.test_table + ";").fetchAllSync(); 60 | test.same(test_result, [{number: 1}, {number: 2}, {number: 3}]); 61 | 62 | conn.closeSync(); 63 | test.done(); 64 | }()); 65 | }); 66 | }); 67 | }); 68 | 69 | test_order += "f"; 70 | }; 71 | 72 | exports.QueryNestedDeeper = function (test) { 73 | test.expect(1); 74 | 75 | var 76 | conn = cfg.mysql_libmysqlclient.createConnectionSync(cfg.host, cfg.user, cfg.password, cfg.database), 77 | helper, 78 | test_result, 79 | i = 0; 80 | 81 | helper = function () { 82 | i += 1; 83 | if (i <= cfg.slow_inserts_count) { 84 | conn.query("INSERT INTO " + cfg.test_table + " (number) VALUES ('" + i + "');", function (err, res) { 85 | if (err) { 86 | throw err; 87 | } 88 | 89 | helper(); 90 | }); 91 | } else { 92 | test_result = conn.querySync("SELECT COUNT(number) AS c FROM " + cfg.test_table + ";").fetchAllSync()[0].c; 93 | test.equals(test_result, cfg.slow_inserts_count + 3); 94 | 95 | conn.closeSync(); 96 | test.done(); 97 | } 98 | }; 99 | 100 | helper(); 101 | }; 102 | 103 | exports.QueryInLoop = function (test) { 104 | test.expect(1); 105 | 106 | var 107 | conn = cfg.mysql_libmysqlclient.createConnectionSync(cfg.host, cfg.user, cfg.password, cfg.database), 108 | test_result, 109 | i, ci = 0; 110 | 111 | for (i = 0; i < cfg.slow_inserts_count; i += 1) { 112 | conn.query("INSERT INTO " + cfg.test_table + " (number) VALUES ('" + i + "');", function (err, res) { 113 | if (err) { 114 | throw err; 115 | } 116 | 117 | ci += 1; 118 | 119 | if (ci === cfg.slow_inserts_count) { 120 | test_result = conn.querySync("SELECT COUNT(number) AS c FROM " + cfg.test_table + ";").fetchAllSync()[0].c; 121 | test.equals(test_result, 2 * cfg.slow_inserts_count + 3); 122 | 123 | conn.closeSync(); 124 | test.done(); 125 | } 126 | }); 127 | } 128 | }; 129 | 130 | -------------------------------------------------------------------------------- /tests/slow/test-querySend.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright by Oleg Efimov and node-mysql-libmysqlclient contributors 3 | See contributors list in README 4 | 5 | See license text in LICENSE file 6 | */ 7 | 8 | // Load configuration 9 | var cfg = require('../config'); 10 | 11 | exports.Setup = function (test) { 12 | test.expect(0); 13 | 14 | var conn = cfg.mysql_libmysqlclient.createConnectionSync(cfg.host, cfg.user, cfg.password, cfg.database); 15 | 16 | conn.querySync("DROP TABLE IF EXISTS " + cfg.test_table + ";"); 17 | conn.querySync("CREATE TABLE " + cfg.test_table + 18 | " (number INT(8) NOT NULL) ENGINE=MEMORY;"); 19 | 20 | conn.closeSync(); 21 | 22 | test.done(); 23 | }; 24 | 25 | exports.QuerySendNested = function (test) { 26 | test.expect(2); 27 | 28 | var 29 | conn = cfg.mysql_libmysqlclient.createConnectionSync(cfg.host, cfg.user, cfg.password, cfg.database), 30 | test_result, 31 | test_order = ""; 32 | 33 | test_order += "s"; 34 | 35 | conn.querySend("INSERT INTO " + cfg.test_table + " (number) VALUES ('1');", function (err, res) { 36 | if (err) { 37 | throw err; 38 | } 39 | 40 | test_order += "1"; 41 | 42 | conn.querySend("INSERT INTO " + cfg.test_table + " (number) VALUES ('2');", function (err, res) { 43 | if (err) { 44 | throw err; 45 | } 46 | 47 | test_order += "2"; 48 | 49 | conn.querySend("INSERT INTO " + cfg.test_table + " (number) VALUES ('3');", function (err, res) { 50 | if (err) { 51 | throw err; 52 | } 53 | 54 | test_order += "3"; 55 | 56 | (function () { 57 | test.equals(test_order, "sf123"); 58 | 59 | test_result = conn.querySync("SELECT number FROM " + cfg.test_table + ";").fetchAllSync(); 60 | test.same(test_result, [{number: 1}, {number: 2}, {number: 3}]); 61 | 62 | conn.closeSync(); 63 | test.done(); 64 | }()); 65 | }); 66 | }); 67 | }); 68 | 69 | test_order += "f"; 70 | }; 71 | 72 | exports.QuerySendNestedDeeper = function (test) { 73 | test.expect(1); 74 | 75 | var 76 | conn = cfg.mysql_libmysqlclient.createConnectionSync(cfg.host, cfg.user, cfg.password, cfg.database), 77 | helper, 78 | test_result, 79 | i = 0; 80 | 81 | helper = function () { 82 | i += 1; 83 | if (i <= cfg.slow_inserts_count) { 84 | conn.querySend("INSERT INTO " + cfg.test_table + " (number) VALUES ('" + i + "');", function (err, res) { 85 | if (err) { 86 | throw err; 87 | } 88 | 89 | helper(); 90 | }); 91 | } else { 92 | test_result = conn.querySync("SELECT COUNT(number) AS c FROM " + cfg.test_table + ";").fetchAllSync()[0].c; 93 | test.equals(test_result, cfg.slow_inserts_count + 3); 94 | 95 | conn.closeSync(); 96 | test.done(); 97 | } 98 | }; 99 | 100 | helper(); 101 | }; 102 | 103 | exports.QuerySendParallelShouldFail = function (test) { 104 | test.expect(0); 105 | 106 | var 107 | conn = cfg.mysql_libmysqlclient.createConnectionSync(cfg.host, cfg.user, cfg.password, cfg.database); 108 | 109 | conn.querySend("SELECT SLEEP(2);", function (err, res) { 110 | if (err) { 111 | throw err; 112 | } 113 | }); 114 | 115 | conn.querySend("SELECT SLEEP(1);", function (err, res) { 116 | if (err) { 117 | test.done(); 118 | } 119 | }); 120 | }; 121 | -------------------------------------------------------------------------------- /tests/ssl-fixtures/ca-cert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDcDCCAlgCAQEwDQYJKoZIhvcNAQEFBQAwfjELMAkGA1UEBhMCUlUxFjAUBgNV 3 | BAgMDU1vc2NvdyBSZWdpb24xDzANBgNVBAcMBk1vc2NvdzESMBAGA1UECgwJU2Fu 4 | bmlzLlJ1MQ8wDQYDVQQDDAZTYW5uaXMxITAfBgkqhkiG9w0BCQEWEmVmaW1vdm92 5 | QGdtYWlsLmNvbTAeFw0xMjA3MTYyMTA1MjdaFw0xNTA3MTYyMTA1MjdaMH4xCzAJ 6 | BgNVBAYTAlJVMRYwFAYDVQQIDA1Nb3Njb3cgUmVnaW9uMQ8wDQYDVQQHDAZNb3Nj 7 | b3cxEjAQBgNVBAoMCVNhbm5pcy5SdTEPMA0GA1UEAwwGU2FubmlzMSEwHwYJKoZI 8 | hvcNAQkBFhJlZmltb3ZvdkBnbWFpbC5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IB 9 | DwAwggEKAoIBAQC5BNRev+LlpuX4NDEUf99KQTd6ZuvHM9bPoujBDPtDP3lAwH8a 10 | L717K8NcLnjrat+AxwrFkiHxlNVtr+ID/7SWUO2k7r+4zfj1SAFRKQOp+HPBBfv/ 11 | ZguVN+igzNDzjS0ebphKg/0wytLmCzyf02fa/RSRtWWxc8fE0TGKDGdhkOZ0MD/U 12 | GLIlPAUqkKCgsmIvVKYuXwQU7dlocioDprAZQWqMOgPZnXiiCIhJBJfKuN3rofoj 13 | w6ECxtzSri1WJI+lcnaf/98d8++bw+MVUU7gdg90R1CMBFaqh+wv0MDp6QvGj6mo 14 | 8fD3srGQ/m0jRVLEdxfSrobM3z+Npdjeup/TAgMBAAEwDQYJKoZIhvcNAQEFBQAD 15 | ggEBAD2su2Tfu3iG/v4NFIBnMMIHP22kUwvU9A58pcJYpLU8CpwTDSBn+vpd4mQv 16 | zsnjuKfHpgrh6t3XvcoN5cFhf7n4fJa6nAfg78Flw5Wu7m/7hxuQ017kTo3UlcYc 17 | AfPuZtoY30W1qdC9121xYCBX6A4h4f4C+UC/xgP9kyo17EFRKZdknCD8CqjqDoCg 18 | QfCzQoxN36BRURrM4Li0bzMNQkGJvbU3taIukp7BdhN921vEV/ja+xQax643KHGb 19 | mJCqqHhqipUdfIBHcGT4U6AbiPrzJZn1gMvrwvcdb2uHUIAMnME+OpXdUj+5fXDF 20 | xrBBWNX/+T9+3b6NcpsnnKmdA48= 21 | -----END CERTIFICATE----- 22 | -----BEGIN CERTIFICATE----- 23 | MIIDNzCCAh8CAQEwDQYJKoZIhvcNAQEFBQAwfjELMAkGA1UEBhMCUlUxFjAUBgNV 24 | BAgMDU1vc2NvdyBSZWdpb24xDzANBgNVBAcMBk1vc2NvdzESMBAGA1UECgwJU2Fu 25 | bmlzLlJ1MQ8wDQYDVQQDDAZTYW5uaXMxITAfBgkqhkiG9w0BCQEWEmVmaW1vdm92 26 | QGdtYWlsLmNvbTAeFw0xMjA3MTYyMjE2MTNaFw0xNTA0MTIyMjE2MTNaMEUxCzAJ 27 | BgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5l 28 | dCBXaWRnaXRzIFB0eSBMdGQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB 29 | AQC0vhvdhLs7jndrcdxjog/ZOJr+e7GWLX+zJhEg7+kCDUiCls7pUSGd7yYZJcsY 30 | 5AotX0TtI0liaPB8nEbYyDDfwZ4NU9TUuw7/fJa+Q3ilYQBIbjGHoNA0JpDc4wVD 31 | 0F2KpB/C4JmpntFjEjKdqAses893vzI1jKdHeMWENUyR67HGDFeuStLmuawPAknL 32 | aq7sn+PcnYvzEWQx7Z7wmns/ccSutvgASPswe1RNxHmk++SD8QKp8o38TpIp+jie 33 | F6hoxlmpnDSNhaVkiXPheOFy+DbeBIO72MG2mrYyd1etF+Qx65lqqBsoHVR5yNwX 34 | 6N4l9d1uEqlgBAeQIsn9GviHAgMBAAEwDQYJKoZIhvcNAQEFBQADggEBAFgy+QR0 35 | 1d8Tw3d2KmbPB50patt2WXuBarDh12Gx3bKYIq8/8SVSp+pAZhiywPi+jZsGicyF 36 | g0aOhzmw9rRCCixraK7cEHaUgmhBpfBAghsbudTXtrt6xJcgDiBy9CfhCpKVXoSt 37 | mB7dfzy+ajjfgBBdhKJJE59h7S3KleieM2jxKGcK1PqpHCHKq6xvziOKsYhn3SqV 38 | t4sZ4Nk1Ux4TtMk4dtcP39PHCQHai/MSZmZkT/g/DlgDRQn/IYSRdlD1RVlzpbZi 39 | 7N8I/C9TC1JQ8A5o99x9eYbvQizC83xdx9aYDCbX62e0+7NecX2qsurNauJrqWwz 40 | U0suIX8Ey/482EI= 41 | -----END CERTIFICATE----- 42 | -------------------------------------------------------------------------------- /tests/ssl-fixtures/ca-key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIIEowIBAAKCAQEAnFaLkMvqIF1FVhhgc5TKiAmf/3DSVrROWfwqe3mZsN9TjtIw 3 | r/Esmi/HDER33NPu3Q+sUrvrcoFlrJELPH4oAHASw+/PinU7aJYOwGFcD/rfbD0u 4 | GuWfFnJcJys5zuVFL0ajTg7R0iNsRcZqw0WTM2Fj0LFE0Fkbv1Moli7QeHdd1fRI 5 | j9Pm8FZcKJGOoUG7T7tAEp1S6ME74pNLnoYizTz2SHjWch301kehLlWnuWVKK5pz 6 | U3duLx778ac7AxD5Q7jMzQDu9mxgHRD6ZNw/m2qWPla8rZw98os4oMuQ97h8QPbV 7 | xPlw+W9Hf/7L7X38DGVrsf7GwPHmnEc4no+WSQIDAQABAoIBADuHEJlPq5QrL416 8 | tq8LxppJ3+wpj02IVhUZWSuuv4CDaJOHIRa9JBiJfKcFIwaog9kUcK8H8ryk3Iv6 9 | pmagOqcABYUpuMKlpLtL9830xFMpWQ0jtnxzVkH7xW78nIRU9CTuJpxANFBpQH7I 10 | 8DnuMgBsYs9B0Evswg31ogydQq+7W1SUGvxUO3t9B0cNkObA0IdnjX003v50/VaC 11 | cnxkBQwjnLA3ueoGOgfMrPoiJZyuFaN8DQBu2SrjEZJMOBoclHdKYresy4l5iJ7P 12 | 6pHyWCTPrzIuXpn0WYdbV5cdZS+o4T/J1YUlYdYeUrhYEpJ2gzBbw+7N/D/wbiqY 13 | bUsp/gECgYEAy/LQ5J/sDZxnAAgVx42LnzoC7omXe+RBGoEaYCJTlDDHIhJhLjDB 14 | mFmon/I8mL3pwiDorIFpcUZkUeQIPfH7k9gWhZ4OuWC2fm2bxB+2fjzWBkw6YaQz 15 | JYnh/BqiHRabCMNPt52Kh//3X9r2QKgjDMfkWPpKDfHi821DOVRqGuECgYEAxD0N 16 | hd55PVrS35VSzd13IKh2TcCPiFGA+UYQFZ65QwrrzCuKwq9LIDSTd0Pc0i4FWIwv 17 | Zt/imNOC6a9tGxSwDZXUhqToXm7Rf1xa/yPre+euhGVIB6Y3y+axVMq43mBNzVoL 18 | G57L2Gv58BITvMEWLuecTBRS7GloDrU8lhlskGkCgYA4f2SE4RR4VMpnxNWbuUdj 19 | baOgRvdy97FdUURoOzoiBD014BeRvynyNWw0GtvUiE+4Wnt6RkNagOCLmvr5hg5m 20 | T2c1zqpPik4jyeNruklIwTuc9QL7R4xvqrmyqAIewsNh8xEjUX4t3Ke/ox2ynaFQ 21 | ChPk3jkjkc2IF82WlR7roQKBgQDACltcgX42W9Z3tULmce+txw6XQnV0WwaTa0w8 22 | TCtS/7IICShvI2qqpqkVkxTbnuveXrnYvAqdsoevttxYHyO298SWy3UXTO257KCk 23 | hPtjMzRnHlKiIbkC0s0BhK3r+WTKLG8oZXtpXSmoFZi5JGBYIJKlJVKNRw3tLtGO 24 | tmy22QKBgFyjvDg1DuaeHogde3SiaJdXuQqIgoZqsbFhe10RvmS4XNyeufS3+c7B 25 | 9bZ8VPemknYyXH9cOREbq/GGGHYpuX4E4YG08cVHkBBjnArvs9wA+yPAZrmj0OCh 26 | AL1lmrq2HaCyAa/N1xEVBuBwj76vOJx8CbjT2faNgyvtVo5ON5hA 27 | -----END RSA PRIVATE KEY----- 28 | -------------------------------------------------------------------------------- /tests/ssl-fixtures/client-cert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDNzCCAh8CAQEwDQYJKoZIhvcNAQEFBQAwfjELMAkGA1UEBhMCUlUxFjAUBgNV 3 | BAgMDU1vc2NvdyBSZWdpb24xDzANBgNVBAcMBk1vc2NvdzESMBAGA1UECgwJU2Fu 4 | bmlzLlJ1MQ8wDQYDVQQDDAZTYW5uaXMxITAfBgkqhkiG9w0BCQEWEmVmaW1vdm92 5 | QGdtYWlsLmNvbTAeFw0xMjA3MTYyMjE2MTNaFw0xNTA0MTIyMjE2MTNaMEUxCzAJ 6 | BgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5l 7 | dCBXaWRnaXRzIFB0eSBMdGQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB 8 | AQC0vhvdhLs7jndrcdxjog/ZOJr+e7GWLX+zJhEg7+kCDUiCls7pUSGd7yYZJcsY 9 | 5AotX0TtI0liaPB8nEbYyDDfwZ4NU9TUuw7/fJa+Q3ilYQBIbjGHoNA0JpDc4wVD 10 | 0F2KpB/C4JmpntFjEjKdqAses893vzI1jKdHeMWENUyR67HGDFeuStLmuawPAknL 11 | aq7sn+PcnYvzEWQx7Z7wmns/ccSutvgASPswe1RNxHmk++SD8QKp8o38TpIp+jie 12 | F6hoxlmpnDSNhaVkiXPheOFy+DbeBIO72MG2mrYyd1etF+Qx65lqqBsoHVR5yNwX 13 | 6N4l9d1uEqlgBAeQIsn9GviHAgMBAAEwDQYJKoZIhvcNAQEFBQADggEBAFgy+QR0 14 | 1d8Tw3d2KmbPB50patt2WXuBarDh12Gx3bKYIq8/8SVSp+pAZhiywPi+jZsGicyF 15 | g0aOhzmw9rRCCixraK7cEHaUgmhBpfBAghsbudTXtrt6xJcgDiBy9CfhCpKVXoSt 16 | mB7dfzy+ajjfgBBdhKJJE59h7S3KleieM2jxKGcK1PqpHCHKq6xvziOKsYhn3SqV 17 | t4sZ4Nk1Ux4TtMk4dtcP39PHCQHai/MSZmZkT/g/DlgDRQn/IYSRdlD1RVlzpbZi 18 | 7N8I/C9TC1JQ8A5o99x9eYbvQizC83xdx9aYDCbX62e0+7NecX2qsurNauJrqWwz 19 | U0suIX8Ey/482EI= 20 | -----END CERTIFICATE----- 21 | -------------------------------------------------------------------------------- /tests/ssl-fixtures/client-key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIIEpAIBAAKCAQEAtL4b3YS7O453a3HcY6IP2Tia/nuxli1/syYRIO/pAg1IgpbO 3 | 6VEhne8mGSXLGOQKLV9E7SNJYmjwfJxG2Mgw38GeDVPU1LsO/3yWvkN4pWEASG4x 4 | h6DQNCaQ3OMFQ9BdiqQfwuCZqZ7RYxIynagLHrPPd78yNYynR3jFhDVMkeuxxgxX 5 | rkrS5rmsDwJJy2qu7J/j3J2L8xFkMe2e8Jp7P3HErrb4AEj7MHtUTcR5pPvkg/EC 6 | qfKN/E6SKfo4nheoaMZZqZw0jYWlZIlz4Xjhcvg23gSDu9jBtpq2MndXrRfkMeuZ 7 | aqgbKB1UecjcF+jeJfXdbhKpYAQHkCLJ/Rr4hwIDAQABAoIBAQCNp8HnJ7QmxU3L 8 | I/37CHUrZjXz5bYVYauIGPmrutwAA7EkyFV6f1+9jEVryDcZVwCy9svqn5FQU7bH 9 | syPDm4LSm8jn4SAZalIi4t6yV+cilpfGLLcc+Wi0ttUqibMCpzfpBSDvd2B3lEW/ 10 | Q+/vqFiuw3aC/5K2bXpdhcYoDC3q3mGvmgB1W1/E0cSov5ouZaJ+EQ10jXQPzf2k 11 | OslERooZBwO9QqKYYjmDif+tQuunUdjhR/UA7dBOGnOHWKGCRqqBdZc7PtSVAg1l 12 | CGW3QTWthFryv720vgZal8JVbYdlJr+7LUssFroGHIAicpkgLGcRXa67o5C5Vj4f 13 | 0c2/1tbBAoGBAN2AndpkW1SPp8KTTCHiQY6/q/hqTsCumB/G8PTyX4vFUry8BkqV 14 | 8ujKyJrZ/f9GZ1vprT5tMlAdsXpkj+zyWp8cr29xR5ITeMMhDJnEQ1VE08MSi7E9 15 | GiApmp+Rp0o0b5EFevlllJ8GvA1srHkZaMqLGlsPW/o3pOBNdW+nadapAoGBANDk 16 | Yk7hc3cVF/cbZhPnpXufyYmxDWFmeXq2gMDia5Z23bdnlXcdPTO4wSl/Pt4omwgj 17 | cO4yzwc0gTbIZ6PLRsqJocRHA2VQQERp74LQwmll5MYisvlEu1iZ8sQ0zKOyXKmv 18 | 1X2A49jPMM007f9W6NMpmLPnmohWaM4dncFG20OvAoGAF7FEMTH+2uKqzRM4V39+ 19 | B6jU2jN0zQNf3jZHW8v5EFhA61MpUR0M6H2YS4f5tS5wq9Io576CXTNv4mmTQ4MA 20 | 0ngdA8yYHTXb+vM0B9aIZTyBciIvsvuYKcyJb3wC6tsE+/wcFUUaSpBL2RvArwta 21 | vB946DiSXAdLqXpfj1vW5FECgYAL9LZnu2GndC6d9xR9mSmQjNG1LswMQhg73Mw7 22 | vfnYb8862xPj8Gl7V1y+6kiH4J0W9yhUidXtnKS0pP3BkzXnC7+Vg1b/antzLvkF 23 | bLtj2vAgIwZJXBS4+n65migISoIhOC4o88KWuy0Y4ampjqjexSe3TE889G0lNu67 24 | jDmqgwKBgQCs3nHH3HRsU1rHZDeI3IphB/OM+OmtY9Z0zR2GwyJJ99ZHt8JCLeVD 25 | Js1d/CrdPdm19Wbj+peH9M6v08mgrWz1O/vBYaF3jDqjyXYL9fyQjaJzdsnNZpWM 26 | HyOFCJQTo5Vv4Lm/b9zHBLGIgBjwkMSORdryWN7oocTO7W+RiUQ1zg== 27 | -----END RSA PRIVATE KEY----- 28 | -------------------------------------------------------------------------------- /tests/ssl-fixtures/server-cert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDcDCCAlgCAQEwDQYJKoZIhvcNAQEFBQAwfjELMAkGA1UEBhMCUlUxFjAUBgNV 3 | BAgMDU1vc2NvdyBSZWdpb24xDzANBgNVBAcMBk1vc2NvdzESMBAGA1UECgwJU2Fu 4 | bmlzLlJ1MQ8wDQYDVQQDDAZTYW5uaXMxITAfBgkqhkiG9w0BCQEWEmVmaW1vdm92 5 | QGdtYWlsLmNvbTAeFw0xMjA3MTYyMTA1MjdaFw0xNTA3MTYyMTA1MjdaMH4xCzAJ 6 | BgNVBAYTAlJVMRYwFAYDVQQIDA1Nb3Njb3cgUmVnaW9uMQ8wDQYDVQQHDAZNb3Nj 7 | b3cxEjAQBgNVBAoMCVNhbm5pcy5SdTEPMA0GA1UEAwwGU2FubmlzMSEwHwYJKoZI 8 | hvcNAQkBFhJlZmltb3ZvdkBnbWFpbC5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IB 9 | DwAwggEKAoIBAQC5BNRev+LlpuX4NDEUf99KQTd6ZuvHM9bPoujBDPtDP3lAwH8a 10 | L717K8NcLnjrat+AxwrFkiHxlNVtr+ID/7SWUO2k7r+4zfj1SAFRKQOp+HPBBfv/ 11 | ZguVN+igzNDzjS0ebphKg/0wytLmCzyf02fa/RSRtWWxc8fE0TGKDGdhkOZ0MD/U 12 | GLIlPAUqkKCgsmIvVKYuXwQU7dlocioDprAZQWqMOgPZnXiiCIhJBJfKuN3rofoj 13 | w6ECxtzSri1WJI+lcnaf/98d8++bw+MVUU7gdg90R1CMBFaqh+wv0MDp6QvGj6mo 14 | 8fD3srGQ/m0jRVLEdxfSrobM3z+Npdjeup/TAgMBAAEwDQYJKoZIhvcNAQEFBQAD 15 | ggEBAD2su2Tfu3iG/v4NFIBnMMIHP22kUwvU9A58pcJYpLU8CpwTDSBn+vpd4mQv 16 | zsnjuKfHpgrh6t3XvcoN5cFhf7n4fJa6nAfg78Flw5Wu7m/7hxuQ017kTo3UlcYc 17 | AfPuZtoY30W1qdC9121xYCBX6A4h4f4C+UC/xgP9kyo17EFRKZdknCD8CqjqDoCg 18 | QfCzQoxN36BRURrM4Li0bzMNQkGJvbU3taIukp7BdhN921vEV/ja+xQax643KHGb 19 | mJCqqHhqipUdfIBHcGT4U6AbiPrzJZn1gMvrwvcdb2uHUIAMnME+OpXdUj+5fXDF 20 | xrBBWNX/+T9+3b6NcpsnnKmdA48= 21 | -----END CERTIFICATE----- 22 | -------------------------------------------------------------------------------- /tests/ssl-fixtures/server-key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIIEpAIBAAKCAQEAuQTUXr/i5abl+DQxFH/fSkE3embrxzPWz6LowQz7Qz95QMB/ 3 | Gi+9eyvDXC5462rfgMcKxZIh8ZTVba/iA/+0llDtpO6/uM349UgBUSkDqfhzwQX7 4 | /2YLlTfooMzQ840tHm6YSoP9MMrS5gs8n9Nn2v0UkbVlsXPHxNExigxnYZDmdDA/ 5 | 1BiyJTwFKpCgoLJiL1SmLl8EFO3ZaHIqA6awGUFqjDoD2Z14ogiISQSXyrjd66H6 6 | I8OhAsbc0q4tViSPpXJ2n//fHfPvm8PjFVFO4HYPdEdQjARWqofsL9DA6ekLxo+p 7 | qPHw97KxkP5tI0VSxHcX0q6GzN8/jaXY3rqf0wIDAQABAoIBAA2rZ61ga/kfrZn6 8 | 8S1cjTjFPL4UYJMlJ1fL53pr5RyA0gqQrlNW957kCtkCrfhmuwCetBMIyu04W9Rw 9 | zDgTalo4vHYVFaEnxp8IpOBEMXsbWiIGuSmTdoOdz9ghicaUxaKb9TB8M/ao5ZAN 10 | gHsmeWPakux5BHxp23aVJh3W8MRqegoZy/s1eR3eJvEff6c4gN8ber0f+7vUT+16 11 | DoZVtCkGgbaGTkAm8sKgly6+C6Hc3w4rK5dxO7uk7OGedfFdHzKhHGEXNFbXAUqt 12 | gI9IdbnRLMf8YmW06w6yn0iC9mPhQdrH2SaDg72OFt8clkdNzbyhUjJnKvMIBGgf 13 | rmNgfRECgYEA5Fy2jxFAeZ9AO0vxPLpZyGMrfmEVJTuWx4qOfiNBWIBX9sKZvsDX 14 | zV4hpaK6wTfnPdLEOl2dIG7CHMFjIfdkeo1mEkacDdDCPdTW8tClBhq0BH3lCLkm 15 | uus5Rb19UQtYI6fWFpXIcsByH0zxjjhw5IKWvplL4xVYVpJGbJvlL40CgYEAz2k4 16 | 3dwKOCKgEWOfPlLUGhUakkBnHZBFNlvUBYZKxmAzAmDV1v7oaOHO5GBvJSTtR/Wk 17 | cy9Ry0p+UzsYhe8H9PYx4HqdXv4iWt/WqtxAlg4JmR+PuqdxLtqa/xqMLCZ9JajW 18 | w0YYI1PPuQJp2Ye+6QAMnEdgdARZk6QhpJC4BN8CgYEAviJLhdcRXbIwYq6aTrvB 19 | oUygm/rtBjEVG1LLzU5BTBSgKL5iECa0BzPGxAg3gkSvbhQceZQUDTrqt9J0XYWD 20 | zV4JjFHqAL6924lo5oa9v9Vf6RWBKsAt9ReAegaJXn8ZhaZqZCeV26VL36/Kt2Va 21 | 6YepR0yPmKTfBkWICUnLiskCgYEApWK/55jnxS9G99a6ShX97vZZA7m6/4Xkyp2a 22 | iPU2dsyKoCDbIt6ML+Wu9cg3mCTD2Bd1lCttS28RIAkFWvbpH1mZF+htyCtY9aF7 23 | KS8LiRuUZ7cVAr81ryi9YyGmGCZwsDDbX0ZrRPA1uM7F3KEzh9N0OsFnldtKGkJM 24 | WU7UjX0CgYAW2Pdcye9V+a+18/JiHNFarjnHdL856gSpwN6xLHo92sH69NnXMKDS 25 | 8SqdUQipoWYYUQMFAoNaO4sobvXPXPto5mDo2yTjc5i6mDO3FKhzWDh/3rlNLKOg 26 | TrowxpB+8dZdhHGF01/0KGNGhMdz7/AtRfL3XVhYYCO9ktMaFQ24Cw== 27 | -----END RSA PRIVATE KEY----- 28 | -------------------------------------------------------------------------------- /tools/check-all-classes-methods-tests-exists.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | /* 3 | Copyright by Oleg Efimov and node-mysql-libmysqlclient contributors 4 | See contributors list in README 5 | 6 | See license text in LICENSE file 7 | */ 8 | 9 | // Require modules 10 | var 11 | assert = require("assert"), 12 | util = require("util"), 13 | fs = require("fs"), 14 | path = require("path"); 15 | 16 | var 17 | regex_class_source_filename = 18 | /mysql_bindings_.*\.h$/, 19 | regex_class_name = 20 | /class [a-z:\s]*?([a-z]*) :[a-z:\s]*\{/i, 21 | regex_class_methods = 22 | /static Handle ([a-z]*)\(const Arguments& args\);/ig, 23 | regex_class_properties_getters = 24 | /static Handle ([a-z]*Getter)\(Local property/ig, 25 | regex_class_properties_setters = 26 | /static Handle ([a-z]*Setter)\(Local property/ig, 27 | regex_method_is_sync = 28 | /^(.*Sync|New)$/; 29 | 30 | var root_dir = path.normalize(__dirname + "/.."); 31 | var source_dir = path.normalize(root_dir + "/src"); 32 | var tests_dir = path.normalize(root_dir + "/tests"); 33 | 34 | function getBindingsClasses() { 35 | var 36 | source_files = fs.readdirSync(source_dir), 37 | file_content, 38 | class_name, 39 | classes = [], 40 | class_method_match, 41 | class_methods = [], 42 | class_property_getter_match, 43 | class_properties_getters = [], 44 | class_property_setter_match, 45 | class_properties_setters = [], 46 | i; 47 | 48 | for (i = 0; i < source_files.length; i += 1) { 49 | console.log("Parsing " + source_files[i] + "..."); 50 | 51 | if (source_files[i].match(regex_class_source_filename)) { 52 | file_content = fs.readFileSync(source_dir + "/" + source_files[i]).toString(); 53 | 54 | class_name = file_content.match(regex_class_name)[1]; 55 | 56 | class_properties_getters = []; 57 | 58 | regex_class_properties_getters.lastIndex = 0; 59 | while ((class_property_getter_match = regex_class_properties_getters.exec(file_content))) { 60 | class_properties_getters.push(class_property_getter_match[1]); 61 | regex_class_properties_getters.lastIndex += 1; 62 | } 63 | 64 | class_properties_setters = []; 65 | 66 | regex_class_properties_setters.lastIndex = 0; 67 | while ((class_property_setter_match = regex_class_properties_setters.exec(file_content))) { 68 | class_properties_setters.push(class_property_setter_match[1]); 69 | regex_class_properties_setters.lastIndex += 1; 70 | } 71 | 72 | class_methods = []; 73 | 74 | regex_class_methods.lastIndex = 0; 75 | while ((class_method_match = regex_class_methods.exec(file_content))) { 76 | class_methods.push(class_method_match[1]); 77 | regex_class_methods.lastIndex += 1; 78 | } 79 | 80 | classes.push({ 81 | name: class_name, 82 | properties_getters: class_properties_getters, 83 | properties_setters: class_properties_setters, 84 | methods: class_methods 85 | }); 86 | } 87 | } 88 | 89 | classes.sort(function (a, b) { 90 | if (a.name < b.name) { 91 | return -1; 92 | } 93 | if (a.name > b.name) { 94 | return 1; 95 | } 96 | return 0; 97 | }); 98 | 99 | return classes; 100 | } 101 | 102 | var red = function (str) { 103 | return "\u001b[31m" + str + "\u001b[39m"; 104 | }; 105 | 106 | var green = function (str) { 107 | return "\u001b[32m" + str + "\u001b[39m"; 108 | }; 109 | 110 | var bold = function (str) { 111 | return "\u001b[1m" + str + "\u001b[22m"; 112 | }; 113 | 114 | var 115 | bindings_classes = getBindingsClasses(), 116 | i, j, 117 | test_file_name, 118 | test_require, 119 | notexist_tests = 0; 120 | 121 | for (i = 0; i < bindings_classes.length; i += 1) { 122 | test_file_name_sync = tests_dir + "/low-level-sync/test-class-" + bindings_classes[i].name.toLowerCase() + "-sync.js"; 123 | 124 | console.log(bold(bindings_classes[i].name + ": " + path.relative(root_dir, test_file_name_sync))); 125 | 126 | try { 127 | test_require_sync = require(test_file_name_sync.replace(/\.js$/, '')); 128 | } 129 | catch (e) { 130 | test_require_sync = false; 131 | } 132 | 133 | for (j = 0; j < bindings_classes[i].properties_getters.length; j += 1) { 134 | if (test_require_sync 135 | && (typeof test_require_sync[bindings_classes[i].properties_getters[j]] !== 'undefined') 136 | ) { 137 | console.log(green('✔ ' + bindings_classes[i].properties_getters[j])); 138 | } else { 139 | console.log(red('✖ ' + bindings_classes[i].properties_getters[j])); 140 | notexist_tests += 1; 141 | } 142 | } 143 | 144 | for (j = 0; j < bindings_classes[i].properties_setters.length; j += 1) { 145 | if (test_require_sync 146 | && (typeof test_require_sync[bindings_classes[i].properties_setters[j]] !== 'undefined') 147 | ) { 148 | console.log(green('✔ ' + bindings_classes[i].properties_setters[j])); 149 | } else { 150 | console.log(red('✖ ' + bindings_classes[i].properties_setters[j])); 151 | notexist_tests += 1; 152 | } 153 | } 154 | 155 | for (j = 0; j < bindings_classes[i].methods.length; j += 1) { 156 | if (bindings_classes[i].methods[j].match(regex_method_is_sync)) { 157 | if (test_require_sync 158 | && (typeof test_require_sync[bindings_classes[i].methods[j]] !== 'undefined') 159 | ) { 160 | console.log(green('✔ ' + bindings_classes[i].methods[j])); 161 | } else { 162 | console.log(red('✖ ' + bindings_classes[i].methods[j])); 163 | notexist_tests += 1; 164 | } 165 | } 166 | } 167 | 168 | test_file_name = tests_dir + "/low-level-async/test-class-" + bindings_classes[i].name.toLowerCase() + "-async.js"; 169 | 170 | console.log(bold(bindings_classes[i].name + ": " + path.relative(root_dir, test_file_name))); 171 | 172 | try { 173 | test_require = require(test_file_name.replace(/\.js$/, '')); 174 | } 175 | catch (e) { 176 | test_require = false; 177 | } 178 | 179 | for (j = 0; j < bindings_classes[i].methods.length; j += 1) { 180 | if (!bindings_classes[i].methods[j].match(regex_method_is_sync)) { 181 | if (test_require 182 | && (typeof test_require[bindings_classes[i].methods[j]] !== 'undefined') 183 | ) { 184 | console.log(green('✔ ' + bindings_classes[i].methods[j])); 185 | } else { 186 | console.log(red('✖ ' + bindings_classes[i].methods[j])); 187 | notexist_tests += 1; 188 | } 189 | } 190 | } 191 | } 192 | 193 | if (notexist_tests) { 194 | console.log('\n' + bold(red('NONEXISTENT METHODS TESTS: ')) + notexist_tests); 195 | } else { 196 | console.log('\n' + bold(green('OK'))); 197 | } 198 | 199 | 200 | -------------------------------------------------------------------------------- /tools/inspect-exported-classes-and-functions.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | /* 3 | Copyright by Oleg Efimov and node-mysql-libmysqlclient contributors 4 | See contributors list in README 5 | 6 | See license text in LICENSE file 7 | */ 8 | 9 | // Load configuration 10 | var cfg = require("../tests/config"); 11 | 12 | // Require modules 13 | var 14 | util = require("util"), 15 | events = require('events'), 16 | mysql_libmysqlclient = require("../lib/mysql-libmysqlclient"), 17 | mysql_bindings = mysql_libmysqlclient.bindings, 18 | conn, 19 | connQueued, 20 | connHighlevel, 21 | res; 22 | 23 | function debug(title, obj) { 24 | var i; 25 | 26 | util.puts("Debug '" + title + "':"); 27 | util.puts(" Inspect:"); 28 | util.puts(util.inspect(obj).replace(/^/gm, " ")); 29 | util.puts(" Foreach exclude EventEmitter.prototype:"); 30 | for (i in obj) { 31 | if ((typeof i === "string") && (typeof events.EventEmitter.prototype[i] === "undefined")) { 32 | util.puts(" " + i + " (typeof " + (typeof obj[i]) + "): " + obj[i].toString()); 33 | } 34 | } 35 | } 36 | 37 | util.print("Show debug information for NodeJS MySQL/libmysqlclient bindings...\n"); 38 | 39 | conn = mysql_libmysqlclient.createConnectionSync(cfg.host, cfg.user, cfg.password, cfg.database); 40 | res = conn.querySync("SHOW TABLES;"); 41 | 42 | debug("mysql_bindings", mysql_bindings); 43 | debug("mysql_libmysqlclient", mysql_libmysqlclient); 44 | debug("conn", conn); 45 | debug("res", res); 46 | 47 | conn.closeSync(); 48 | 49 | connQueued = mysql_libmysqlclient.createConnectionQueuedSync(cfg.host, cfg.user, cfg.password, cfg.database); 50 | connHighlevel = mysql_libmysqlclient.createConnectionHighlevelSync(cfg.host, cfg.user, cfg.password, cfg.database); 51 | 52 | debug("connQueued", connQueued); 53 | debug("connHighlevel", connHighlevel); 54 | 55 | connQueued.closeSync(); 56 | connHighlevel.closeSync(); 57 | -------------------------------------------------------------------------------- /tools/memory-helper.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright by Oleg Efimov and node-mysql-libmysqlclient contributors 3 | See contributors list in README 4 | 5 | See license text in LICENSE file 6 | */ 7 | 8 | if (require.main === module) { 9 | console.log("This is helper module and cannot be executed."); 10 | process.exit(1); 11 | } 12 | 13 | function heavyGc() { 14 | gc();gc();gc();gc();gc(); 15 | gc();gc();gc();gc();gc(); 16 | gc();gc();gc();gc();gc(); 17 | gc();gc();gc();gc();gc(); 18 | gc();gc();gc();gc();gc(); 19 | } 20 | 21 | exports.heavyGc = heavyGc; 22 | 23 | var initialMemoryUsage = null; 24 | function showMemoryUsageDeltaLine(title, value0, value1) { 25 | if (value1) { 26 | process.stdin.write(title + ": " + value1 27 | + (value1 > value0 ? " (+" : " (") 28 | + (100 * (value1 - value0) / value0).toFixed(2) + "%)\n"); 29 | } else { 30 | process.stdin.write(title + ": " + value0 + "\n"); 31 | } 32 | } 33 | function showMemoryUsageDelta() { 34 | if (!initialMemoryUsage) { 35 | initialMemoryUsage = process.memoryUsage(); 36 | 37 | process.stdin.write("Initial memory usage:\n"); 38 | process.stdin.write("rss: " + initialMemoryUsage.rss + "\n"); 39 | process.stdin.write("heapUsed: " + initialMemoryUsage.heapUsed + "\n"); 40 | process.stdin.write("heapTotal: " + initialMemoryUsage.heapTotal + "\n"); 41 | } else { 42 | var memoryUsage = process.memoryUsage(); 43 | 44 | process.stdin.write("Currect memory usage:\n"); 45 | showMemoryUsageDeltaLine("rss", initialMemoryUsage.rss, memoryUsage.rss ); 46 | showMemoryUsageDeltaLine("heapUsed", initialMemoryUsage.heapUsed, memoryUsage.heapUsed ); 47 | showMemoryUsageDeltaLine("heapTotal", initialMemoryUsage.heapTotal, memoryUsage.heapTotal); 48 | } 49 | } 50 | function resetMemoryUsageDelta() { 51 | initialMemoryUsage = null; 52 | } 53 | 54 | exports.showMemoryUsageDelta = showMemoryUsageDelta; 55 | exports.resetMemoryUsageDelta = resetMemoryUsageDelta; 56 | -------------------------------------------------------------------------------- /tools/memory-leaks-finder-repl.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node --expose-gc 2 | /* 3 | Copyright by Oleg Efimov and node-mysql-libmysqlclient contributors 4 | See contributors list in README 5 | 6 | See license text in LICENSE file 7 | */ 8 | 9 | var 10 | // Require modules 11 | util = require("util"), 12 | readline = require('readline'), 13 | rli, 14 | mysql = require("../"), 15 | mysql_bindings = mysql.bindings, 16 | helper = require("./memory-helper"), 17 | // Load configuration 18 | cfg = require("../tests/config"), 19 | // Params 20 | prompt = "mlf> ", 21 | commands; 22 | 23 | commands = { 24 | quit: function () { 25 | process.exit(0); 26 | }, 27 | showMemoryUsageDelta: function () { 28 | helper.showMemoryUsageDelta(); 29 | }, 30 | resetMemoryUsageDelta: function () { 31 | helper.resetMemoryUsageDelta(); 32 | }, 33 | gc: function () { 34 | helper.heavyGc(); 35 | }, 36 | help: function () { 37 | var cmd; 38 | process.stdout.write("List of commands:\n"); 39 | for (cmd in commands) { 40 | if (commands.hasOwnProperty(cmd)) { 41 | process.stdout.write(" " + cmd + "\n"); 42 | } 43 | } 44 | }, 45 | 46 | newConnection: function () { 47 | var conn = new mysql_bindings.MysqlConnection(); 48 | }, 49 | createConnectionSync: function () { 50 | var conn = mysql.createConnectionSync(cfg.host, cfg.user, cfg.password); 51 | }, 52 | createConnectionQueuedSync: function () { 53 | var conn = mysql.createConnectionQueuedSync(cfg.host, cfg.user, cfg.password); 54 | }, 55 | createConnectionHighlevelSync: function () { 56 | var conn = mysql.createConnectionHighlevelSync(cfg.host, cfg.user, cfg.password); 57 | }, 58 | 59 | errorOnConnect: function () { 60 | var conn = mysql.createConnectionSync(cfg.host, cfg.user, cfg.password, cfg.database_denied); 61 | 62 | var connectionError = conn.connectionError; 63 | }, 64 | errorOnQuery: function () { 65 | var conn = mysql.createConnectionSync(cfg.host, cfg.user, cfg.password); 66 | 67 | conn.querySync("USE " + cfg.database_denied + ";"); 68 | 69 | var queryError = conn.errorSync(); 70 | 71 | conn.closeSync(); 72 | }, 73 | 74 | fetchAllSync: function () { 75 | var 76 | conn = mysql.createConnectionSync(cfg.host, cfg.user, cfg.password, cfg.database), 77 | res, 78 | rows; 79 | 80 | res = conn.querySync("SELECT 'some string' as str;"); 81 | rows = res.fetchAllSync(); 82 | 83 | conn.closeSync(); 84 | }, 85 | fetchAllSyncAndFree: function () { 86 | var 87 | conn = mysql.createConnectionSync(cfg.host, cfg.user, cfg.password, cfg.database), 88 | res, 89 | rows; 90 | 91 | res = conn.querySync("SELECT 'some string' as str;"); 92 | rows = res.fetchAllSync(); 93 | 94 | res.freeSync(); 95 | conn.closeSync(); 96 | }, 97 | fetchAllByRows: function () { 98 | var 99 | conn = mysql.createConnectionSync(cfg.host, cfg.user, cfg.password, cfg.database), 100 | res, 101 | row; 102 | 103 | conn.realQuerySync("SHOW TABLES;"); 104 | res = conn.storeResultSync(); 105 | 106 | while ((row = res.fetchRowSync())) { 107 | // Empty block 108 | } 109 | 110 | conn.closeSync(); 111 | }, 112 | fetchAllByRowsAndFree: function () { 113 | var 114 | conn = mysql.createConnectionSync(cfg.host, cfg.user, cfg.password, cfg.database), 115 | res, 116 | row; 117 | 118 | conn.realQuerySync("SHOW TABLES;"); 119 | res = conn.storeResultSync(); 120 | 121 | while ((row = res.fetchRowSync())) { 122 | // Empty block 123 | } 124 | 125 | res.freeSync(); 126 | conn.closeSync(); 127 | }, 128 | 129 | escapeSync: function () { 130 | var 131 | conn = mysql.createConnectionSync(cfg.host, cfg.user, cfg.password, cfg.database), 132 | str; 133 | 134 | str = conn.escapeSync("some string"); 135 | 136 | conn.closeSync(); 137 | }, 138 | 139 | testResultsFreeAfterConnectionClose: function () { 140 | var conn = mysql.createConnectionSync(cfg.host, cfg.user, cfg.password, cfg.database); 141 | 142 | var res = conn.querySync("SELECT 'some string' AS str;"); 143 | 144 | conn.closeSync(); 145 | }, 146 | 147 | manyQueries: function (n) { 148 | var conn = mysql.createConnectionSync(cfg.host, cfg.user, cfg.password, cfg.database); 149 | 150 | var res; 151 | 152 | for (var i = 0; i < n; i++) { 153 | res = conn.querySync("SELECT 'some string' AS str;"); 154 | } 155 | } 156 | }; 157 | 158 | commands.manyQueries.passTimesAsArgument = true; 159 | 160 | // Main program 161 | process.stdout.write("Starting WebKit development tools agent...\n"); 162 | process.stdout.write("Open http://c4milo.github.com/node-webkit-agent/19.0.1084.46/inspector.html?host=localhost:1337&page=0 to use it.\n"); 163 | require('webkit-devtools-agent'); 164 | process.emit('SIGUSR2'); 165 | process.stdout.write("\n"); 166 | 167 | process.stdout.write("Welcome to the memory leaks finder!\n"); 168 | process.stdout.write("Type 'help' for options.\n"); 169 | 170 | helper.heavyGc(); 171 | helper.showMemoryUsageDelta(); 172 | 173 | rli = readline.createInterface(process.stdin, process.stdout, function completer (text) { 174 | var 175 | completions = [], 176 | completeOn, 177 | i; 178 | 179 | completeOn = text; 180 | for (i in commands) { 181 | if (i.match(new RegExp("^" + text))) { 182 | completions.push(i); 183 | } 184 | } 185 | 186 | return [completions, completeOn]; 187 | }); 188 | 189 | rli.on("SIGINT", function () { 190 | rli.close(); 191 | }); 192 | 193 | rli.on('close', function () { 194 | process.stdout.write("\n"); 195 | helper.showMemoryUsageDelta(); 196 | process.stdin.destroy(); 197 | }); 198 | 199 | rli.on('line', function (cmd) { 200 | var pair = cmd.trim().split(/\s+/), i; 201 | 202 | pair[0] = pair[0].trim(); 203 | pair[1] = parseInt(pair[1], 10) > 0 ? parseInt(pair[1], 10) : 1; 204 | 205 | if (commands[pair[0]]) { 206 | if (pair[0] === "help" || pair[0] === "quit" || pair[0] === "showMemoryUsage") { 207 | commands[pair[0]](); 208 | } else { 209 | try { 210 | process.stdout.write("Run " + pair[0] + " for " + pair[1] + " times:"); 211 | 212 | if (commands[pair[0]].passTimesAsArgument) { 213 | commands[pair[0]](pair[1]); 214 | } else { 215 | for (i = 0; i < pair[1]; i += 1) { 216 | commands[pair[0]](); 217 | } 218 | } 219 | 220 | process.stdout.write(" done.\n"); 221 | } catch (e) { 222 | process.stdout.write("Exception caused!\n"); 223 | process.stdout.write(util.inspect(e.stack) + "\n"); 224 | } 225 | 226 | helper.showMemoryUsageDelta(); 227 | } 228 | } else if (pair[0] !== "") { 229 | process.stdout.write("Unrecognized command: " + pair[0] + "\n"); 230 | commands.help(); 231 | } 232 | 233 | rli.prompt(); 234 | }); 235 | 236 | rli.setPrompt(prompt); 237 | rli.prompt(); 238 | -------------------------------------------------------------------------------- /tools/memory-usage-profile.gle: -------------------------------------------------------------------------------- 1 | size 50 12 2 | begin graph 3 | size 50 11.5 4 | 5 | xaxis min 0 hei 0.5 6 | yaxis min 0 hei 0.5 7 | 8 | title "Memory usage (Mb)" hei 1 dist 0.8 9 | data memory-usage-profile.dat 10 | 11 | xtitle "Time, seconds" hei 0.5 dist 0.5 12 | 13 | d1 line lwidth 0.05 color blue key "RSS" 14 | d2 line lwidth 0.05 color green key "Heap used" 15 | d3 line lwidth 0.05 color red key "Heap total" 16 | 17 | key pos rc compact offset -0.1 0 nobox hei 0.5 18 | end graph 19 | -------------------------------------------------------------------------------- /tools/memory-usage-profile.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node --expose-gc 2 | /* 3 | Copyright by Oleg Efimov and node-mysql-libmysqlclient contributors 4 | See contributors list in README 5 | 6 | See license text in LICENSE file 7 | */ 8 | 9 | var 10 | // Require modules 11 | fs = require("fs"), 12 | mysql = require("../"), 13 | async = require("async"), 14 | helper = require("./memory-helper"), 15 | // Load configuration 16 | cfg = require("../tests/config"), 17 | // Parameters 18 | timeLimitInSec = 120 * 60, 19 | gcLevel = 0, 20 | connType = 'binding', 21 | pauseBetweenOperationsInMs = 0, 22 | dumpMemoryUsageIntervalInMs = 500, 23 | dumpMemoryUsageInterval = null, 24 | drawMemoryUsageGraphIntervalInMs = 2 * 60 * 1000, 25 | drawMemoryUsageGraphInterval = null, 26 | bufferSize = 16 * 1024, 27 | bufferString = '', 28 | // Start time 29 | startHrTime = [0, 0], 30 | // Other 31 | filenameResult = '', 32 | filenameData = '', 33 | dataFd = null; 34 | 35 | function dumpMemoryUsage() { 36 | var 37 | currentHrTime = process.hrtime(), 38 | timeDelta = '', 39 | memoryUsage = process.memoryUsage(), 40 | Mb = 1024*1024; 41 | 42 | if (currentHrTime[1] >= startHrTime[1]) { 43 | timeDelta = (currentHrTime[0] - startHrTime[0]) + (currentHrTime[1] - startHrTime[1])/1e9; 44 | } else { 45 | timeDelta = (currentHrTime[0] - startHrTime[0] - 1) + (currentHrTime[1] - startHrTime[1] + 1e9)/1e9; 46 | } 47 | 48 | fs.writeSync(dataFd, timeDelta + '\t' + memoryUsage.rss/Mb + '\t' + memoryUsage.heapUsed/Mb + '\t' + memoryUsage.heapTotal/Mb + "\n"); 49 | } 50 | 51 | function performOperation(callback) { 52 | var connection = createConnectionSync(cfg.host, cfg.user, cfg.password, cfg.database); 53 | 54 | if (!connection.connectedSync()) { 55 | setTimeout(callback, pauseBetweenOperationsInMs); 56 | return; 57 | } 58 | 59 | // Run series of queries 60 | async.parallel([ 61 | function (cb) { 62 | connection.query("SELECT '" + connection.escapeSync(bufferString) + "' AS `str`;", function (error, result) { 63 | if (error) throw error; 64 | 65 | result.fetchAll(function (error, rows) { 66 | if (error) throw error; 67 | 68 | rows = null; 69 | 70 | cb(null); 71 | }); 72 | }); 73 | }, 74 | function (cb) { 75 | connection.query("INSERT INTO `" + cfg.test_table + "` (`text_data`) VALUES ('" + connection.escapeSync(bufferString) + "');", function (error, info) { 76 | if (error) throw error; 77 | 78 | info = null; 79 | cb(null); 80 | }); 81 | } 82 | ], function (error) { 83 | if (error) throw error; 84 | 85 | async.series([ 86 | function (cb) { 87 | connection.query("SELECT * FROM `" + cfg.test_table + "`;", function (error, result) { 88 | if (error) throw error; 89 | 90 | result.fetchAll(function (error, rows) { 91 | if (error) throw error; 92 | 93 | rows = null; 94 | 95 | cb(null); 96 | }); 97 | }); 98 | }, 99 | function (cb) { 100 | connection.query("DELETE FROM `" + cfg.test_table + "` WHERE 1;", function (error, info) { 101 | if (error) throw error; 102 | 103 | info = null; 104 | 105 | cb(null); 106 | }); 107 | } 108 | ], function (error) { 109 | if (error) throw error; 110 | 111 | process.nextTick(callback); 112 | }); 113 | }); 114 | } 115 | 116 | // Parse program arguments 117 | params = process.argv.splice(2); 118 | 119 | var gcLevelFound = false; 120 | var connTypeFound = false; 121 | params.forEach(function (param) { 122 | if (param.slice(0, 5) === "--gc=") { 123 | gcLevel = param.slice(5); 124 | } else if (param === '--gc') { 125 | gcLevelFound = true; 126 | } else if (gcLevelFound) { 127 | gcLevel = param; 128 | gcLevelFound = false; 129 | } else if (param.slice(0, 13) === "--connection=") { 130 | connType = param.slice(13); 131 | } else if (param === '--connection') { 132 | connTypeFound = true; 133 | } else if (connTypeFound) { 134 | connType = param; 135 | connTypeFound = false; 136 | } 137 | }); 138 | 139 | gcLevel = parseInt(gcLevel, 10); 140 | 141 | var myGc = function () {}; 142 | if (gcLevel > 0) { 143 | myGc = gc; 144 | } 145 | if (gcLevel > 1) { 146 | myGc = helper.heavyGc; 147 | } 148 | 149 | var createConnectionSync = mysql.createConnectionSync; 150 | if (connType === 'queued') { 151 | createConnectionSync = mysql.createConnectionQueuedSync; 152 | } 153 | if (connType === 'highlevel') { 154 | createConnectionSync = mysql.createConnectionHighlevelSync; 155 | } 156 | 157 | filenameData = "memory-usage-profile.dat"; 158 | filenameResult = "memory-usage-profile-connection-" + connType + "-gc-" + gcLevel + ".png"; 159 | 160 | // Main program 161 | createTestTable(); 162 | 163 | function createTestTable() { 164 | console.log("Creating test table..."); 165 | 166 | var connection = createConnectionSync(cfg.host, cfg.user, cfg.password, cfg.database), result = true; 167 | 168 | if (!connection.connectedSync()) { 169 | throw new Error("Cannot connect to database."); 170 | } 171 | 172 | result = result && connection.querySync("DROP TABLE IF EXISTS " + cfg.test_table + ";"); 173 | result = result && connection.querySync( 174 | "CREATE TABLE " + cfg.test_table + " (" + 175 | " id INT(8) NOT NULL AUTO_INCREMENT, " + 176 | " text_data TEXT NULL, " + 177 | " PRIMARY KEY(id)" + 178 | ") " + cfg.store_engine + ";" 179 | ); 180 | 181 | if (!result) { 182 | throw new Error("Cannot create test table."); 183 | } 184 | 185 | process.nextTick(openDataFile); 186 | } 187 | 188 | function openDataFile() { 189 | console.log("Opening data file for writing..."); 190 | 191 | fs.open(__dirname + "/" + filenameData, "w", function (error, fd) { 192 | if (error) throw error; 193 | 194 | dataFd = fd; 195 | 196 | process.nextTick(dumpMemoryUsageProfile); 197 | }); 198 | } 199 | 200 | function dumpMemoryUsageProfile() { 201 | console.log("Start writing..."); 202 | 203 | // Write data table header to file 204 | fs.writeSync(dataFd, "time\tRSS\theapUsed\theapTotal\n"); 205 | 206 | // Fill test buffer string 207 | for (var i = 0; i < bufferSize; i++) { 208 | bufferString += 'X'; 209 | } 210 | 211 | // Start timer, save initial memory usage 212 | startHrTime = process.hrtime(); 213 | if (dumpMemoryUsageIntervalInMs > 0) { 214 | dumpMemoryUsageInterval = setInterval(dumpMemoryUsage, dumpMemoryUsageIntervalInMs); 215 | } 216 | dumpMemoryUsage(); 217 | if (drawMemoryUsageGraphIntervalInMs > 0) { 218 | drawMemoryUsageGraphInterval = setInterval(drawMemoryUsageGraph, drawMemoryUsageGraphIntervalInMs); 219 | } 220 | 221 | // Start async operations 222 | async.whilst( 223 | function () { 224 | var currentHrTime = process.hrtime(); 225 | 226 | return (currentHrTime[0] - startHrTime[0]) < timeLimitInSec; 227 | }, 228 | function (callback) { 229 | performOperation(function () { 230 | myGc(); 231 | 232 | if (dumpMemoryUsageIntervalInMs === 0) { 233 | dumpMemoryUsage(); 234 | } 235 | 236 | if (pauseBetweenOperationsInMs > 0) { 237 | setTimeout(callback, pauseBetweenOperationsInMs); 238 | } else { 239 | process.nextTick(callback); 240 | } 241 | }); 242 | }, 243 | function (error) { 244 | if (error) throw error; 245 | 246 | // All ok 247 | if (dumpMemoryUsageInterval) { 248 | clearInterval(dumpMemoryUsageInterval); 249 | } 250 | if (drawMemoryUsageGraphInterval) { 251 | clearInterval(drawMemoryUsageGraphInterval); 252 | } 253 | 254 | fs.close(dataFd, function (error) { 255 | if (error) throw error; 256 | 257 | console.log("Draw graph..."); 258 | drawMemoryUsageGraph(function () { 259 | console.log("Done."); 260 | }); 261 | }); 262 | } 263 | ); 264 | } 265 | 266 | function drawMemoryUsageGraph(callback) { 267 | require("child_process").exec( 268 | "gle -output " + __dirname + "/" + filenameResult + " " + __dirname + "/memory-usage-profile.gle", 269 | function (error) { 270 | if (error) throw error; 271 | 272 | if (typeof callback === "function") { 273 | process.nextTick(callback); 274 | } 275 | } 276 | ); 277 | } 278 | --------------------------------------------------------------------------------