123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407 |
- /*
- * Copyright (c) 2005, The haXe Project Contributors
- * All rights reserved.
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE HAXE PROJECT CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE HAXE PROJECT CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- */
- package php.db;
- import php.NativeArray;
- /**
- * PDO::FETCH_COLUMN = 7
- * PDO::FETCH_CLASS = 8
- * PDO::FETCH_INTO = 9
- * PDO::PARAM_STR = 2
- * PDO::FETCH_BOTH = 4
- * PDO::FETCH_ORI_NEXT = 0
- */
- class PDO
- {
- public static function open(dsn : String, ?user : String, ?password : String, ?options : Dynamic) : Connection {
- return new PDOConnection(dsn, user, password, options);
- }
- }
- extern class PDOClass
- {
- // public function new(dns : String, ?username : String, ?password : String, ?driver_options : NativeArray) : Void;
- public function beginTransaction() : Bool;
- public function commit() : Bool;
- public function errorCode() : Dynamic;
- public function errorInfo() : NativeArray;
- public function exec(statement : String) : Int;
- public function getAttribute(attribute : Int) : Dynamic;
- public function getAvailableDrivers() : NativeArray;
- public function lastInsertId(?name : String) : String;
- public function prepare(statement : String, driver_options : NativeArray) : PDOStatement;
- public function query(statement : String, mode : Int) : PDOStatement;
- public function quote(String : String, ?parameter_type : Int = 2) : String;
- public function rollBack() : Bool;
- public function setAttribute(attribute : Int, value : Dynamic) : Bool;
- }
- extern class PDOStatement
- {
- public function bindColumn(column : Dynamic, param : Dynamic, ?type : Int, ?maxlen : Int, ?driverdata : Dynamic) : Bool;
- public function bindParam(parameter : Dynamic, variable : Dynamic, ?data_type : Int, ?length : Int, ?driver_options : Dynamic) : Bool;
- public function bindValue(parameter : Dynamic, value : Dynamic, ?data_type : Int) : Bool;
- public function closeCursor() : Bool;
- public function columnCount() : Int;
- public function debugDumpParams() : Bool;
- public function errorCode() : String;
- public function errorInfo() : NativeArray;
- public function execute(input_parameters : NativeArray) : Bool;
- public function fetch(?fetch_style : Int = 4, ?cursor_orientation : Int = 0, ?cursor_offset : Int = 0) : Dynamic;
- public function fetchAll(?fetch_style : Int) : NativeArray;
- public function fetchColumn(?column_number : Int = 0) : String;
- public function fetchObject(?class_name : String, ?ctor_args : NativeArray) : Dynamic;
- public function getAttribute(attribute : Int) : Dynamic;
- public function getColumnMeta(column : Int) : NativeArray;
- public function nextRowset() : Bool;
- public function rowCount() : Int;
- public function setAttribute(attribute : Int, value : Dynamic) : Bool;
- public function setFetchMode(mode : Int, ?fetch : Dynamic, ?ctorargs : NativeArray) : Bool;
- }
- import php.Lib;
- import php.Sys;
- private class PDOConnection implements Connection {
- var pdo : PDOClass;
- var dbname : String;
- public function new(dsn : String, ?user : String, ?password : String, ?options : Dynamic) {
- if(null == options)
- pdo = untyped __call__("new PDO", dsn, user, password);
- else
- {
- var arr : NativeArray = untyped __call__("array");
- for (key in Reflect.fields(options))
- arr[untyped key] = Reflect.field(options, key);
- pdo = untyped __call__("new PDO", dsn, user, password, arr);
- }
- dbname = dsn.split(':').shift();
- }
- public function close() {
- pdo = null;
- untyped __call__("unset", pdo);
- }
- public function request( s : String ) : php.db.ResultSet {
- var result = pdo.query(s, untyped __php__("PDO::PARAM_STR"));
- if(untyped __physeq__(result, false))
- {
- var info = Lib.toHaxeArray(pdo.errorInfo());
- throw "Error while executing " + s + " (" + info[2] + ")";
- }
- var db = dbname.toLowerCase();
- switch(db)
- {
- case "sqlite":
- return new AllResultSet(result, new DBNativeStrategy(db));
- default: // mysql
- return new PDOResultSet(result, new PHPNativeStrategy());
- }
- }
- public function escape( s : String ) {
- var output = pdo.quote(s);
- return output.length > 2 ? output.substr(1, output.length-2) : output;
- }
- public function quote( s : String ) {
- if( s.indexOf("\000") >= 0 )
- return "x'"+base16_encode(s)+"'";
- return pdo.quote(s);
- }
- public function addValue( s : StringBuf, v : Dynamic ) {
- if( untyped __call__("is_int", v) || __call__("is_null", v))
- s.add(v);
- else if( untyped __call__("is_bool", v) )
- s.add(if( v ) 1 else 0);
- else
- s.add(quote(Std.string(v)));
- }
- public function lastInsertId() {
- return cast(Std.parseInt(pdo.lastInsertId()), Int);
- }
- public function dbName() {
- return dbname;
- }
- public function startTransaction() {
- pdo.beginTransaction();
- }
- public function commit() {
- pdo.commit();
- }
- public function rollback() {
- pdo.rollBack();
- }
- function base16_encode(str : String) {
- str = untyped __call__("unpack", "H"+(2 * str.length), str);
- str = untyped __call__("chunk_split", untyped str[1]);
- return str;
- }
- }
- private class TypeStrategy {
- public function new() {
- }
- public function map(data : NativeArray) : Dynamic
- {
- return throw "must override";
- }
- public static function convert(v : String, type : String) : Dynamic {
- if (v == null) return v;
- switch(type) {
- case "bool":
- return untyped __call__("(bool)", v);
- case "int":
- return untyped __call__("intval", v);
- case "float":
- return untyped __call__("floatval", v);
- case "date":
- return Date.fromString(v);
- default:
- return v;
- }
- }
- }
- private class PHPNativeStrategy extends TypeStrategy {
- static inline var KEY = "native_type";
- override function map(data : NativeArray) : Dynamic {
- if (!untyped __call__("isset", data[KEY])) {
- if (untyped __call__("isset", data["precision"])) {
- // if (untyped __call__("isset", data["len"]) && data["len"] == 1)
- // return "bool"
- // else
- return "int";
- } else
- return "string";
- }
- var type : String = untyped data[KEY];
- type = type.toLowerCase();
- switch(type)
- {
- case "float", "decimal", "double", "newdecimal":
- return "float";
- case "date", "datetime":
- return "date";
- case "bool":
- return "bool";
- case "int", "int24", "int32", "long", "longlong", "short":
- return "int";
- default:
- return "string";
- }
- }
- }
- private class DBNativeStrategy extends PHPNativeStrategy {
- static inline var SUFFIX = ":decl_type";
- var dbname : String;
- var key : String;
- public function new(dbname : String)
- {
- super();
- this.dbname = dbname.toLowerCase();
- this.key = dbname + SUFFIX;
- }
- override function map(data : NativeArray) : Dynamic {
- if (!untyped __call__("isset", data[key]))
- return super.map(data);
- var type : String = untyped data[key];
- type = type.toLowerCase();
- switch(type)
- {
- case "real":
- return "float";
- case "integer":
- return "int";
- default:
- return "string";
- }
- }
- }
- private class BaseResultSet implements php.db.ResultSet {
- var pdo : PDOStatement;
- var typeStrategy : TypeStrategy;
- var _fields : Int;
- var _columnNames : Array<String>;
- var _columnTypes : Array<String>;
- public var length(getLength, null) : Int;
- public var nfields(getNFields, null) : Int;
- public function new(pdo : PDOStatement, typeStrategy : TypeStrategy)
- {
- this.pdo = pdo;
- this.typeStrategy = typeStrategy;
- this._fields = pdo.columnCount();
- this._columnNames = [];
- this._columnTypes = [];
- feedColumns();
- }
- private function feedColumns() {
- for (i in 0..._fields) {
- var data = pdo.getColumnMeta(i);
- _columnNames.push(data[untyped 'name']);
- _columnTypes.push(typeStrategy.map(data));
- }
- }
- public function getFloatResult(index : Int) : Float {
- return untyped __call__("floatval", getResult(index));
- }
- public function getIntResult(index : Int) : Int {
- return untyped __call__("intval", getResult(index));
- }
- public function getResult(index : Int) : String {
- return throw "must override";
- }
- public function hasNext() : Bool {
- return throw "must override";
- }
- function getLength() : Int {
- return throw "must override";
- }
- function nextRow() : NativeArray {
- return throw "must override";
- }
- public function next() : Dynamic {
- var row = nextRow();
- var o : Dynamic = { };
- for (i in 0..._fields)
- Reflect.setField(o, _columnNames[i], TypeStrategy.convert(row[i], _columnTypes[i]));
- return o;
- }
- function getNFields() : Int {
- return _fields;
- }
- public function results() : List<Dynamic>
- {
- var list = new List();
- while (hasNext())
- list.add(next());
- return list;
- }
- public function getFieldsNames() : Array<String> {
- return throw "Not implemented";
- }
- }
- private class AllResultSet extends BaseResultSet {
- var all : NativeArray;
- var pos : Int;
- var _length : Int;
- public function new(pdo : PDOStatement, typeStrategy : TypeStrategy)
- {
- super(pdo, typeStrategy);
- this.all = pdo.fetchAll(untyped __php__("PDO::FETCH_NUM"));
- this.pos = 0;
- this._length = untyped __call__("count", all);
- }
- override function getResult(index : Int) : String {
- untyped if(__call__("isset", all[0]) && __call__("isset", all[0][index]))
- return all[0][index];
- else
- return null;
- }
- override function hasNext() : Bool {
- return pos < _length;
- }
- override function getLength() : Int {
- return _length;
- }
- override function nextRow() : NativeArray {
- return all[pos++];
- }
- }
- private class PDOResultSet extends BaseResultSet {
- private var cache : NativeArray;
- public function new(pdo : PDOStatement, typeStrategy : TypeStrategy)
- {
- super(pdo, typeStrategy);
- }
- override function getResult(index : Int) : String {
- if (!hasNext())
- return null;
- return cache[index];
- }
- override function hasNext() {
- if(untyped __physeq__(null, cache))
- cacheRow();
- return (untyped cache);
- }
- override function getLength() {
- if (untyped __physeq__(pdo, false))
- return 0;
- return pdo.rowCount();
- }
- private function cacheRow() {
- cache = untyped pdo.fetch(__php__("PDO::FETCH_NUM"), __php__("PDO::FETCH_ORI_NEXT"));
- }
- override function nextRow()
- {
- if (!hasNext())
- return null;
- else {
- var v = cache;
- cache = null;
- return v;
- }
- }
- }
|