⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 manager.hx

📁 ocaml编写的一个flash编译器
💻 HX
字号:
/* * 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 neko.db;import Reflect;import neko.db.Connection;/**	SPOD Manager : the persistent object database manager. See the tutorial on	haXe website to learn how to use SPOD.**/class Manager<T : Object> {	/* ----------------------------- STATICS ------------------------------ */	public static var cnx(default,setConnection) : Connection;	private static var object_cache : Hash<Object> = new Hash();	private static var init_list : List<Manager<Object>> = new List();	private static var cache_field = "__cache__";	private static var no_update : Dynamic = function() { throw "Cannot update not locked object"; }	private static var FOR_UPDATE = "";	private static function setConnection( c : Connection ) {		Reflect.setField(Manager,"cnx",c);		if( c != null )			FOR_UPDATE = if( c.dbName() == "MySQL" ) " FOR UPDATE" else "";		return c;	}	/* ---------------------------- BASIC API ----------------------------- */	var table_name : String;	var table_fields : List<String>;	var table_keys : Array<String>;	var class_proto : { prototype : Dynamic };	public function new( classval : Class<neko.db.Object> ) {		var cl : Dynamic = classval;		// get basic infos		table_name = quoteField(if( cl.TABLE_NAME != null ) cl.TABLE_NAME else cl.__name__[cl.__name__.length-1]);		table_keys = if( cl.TABLE_IDS != null ) cl.TABLE_IDS else ["id"];		class_proto = cl;		// get the list of private fields		var apriv : Array<String> = cl.PRIVATE_FIELDS;		if( apriv == null ) apriv = new Array();		apriv.push("local_manager");		apriv.push("__class__");		// get the proto fields not marked private (excluding methods)		table_fields = new List();		var proto : Dynamic = class_proto.prototype;		for( f in Reflect.fields(proto) ) {			var isfield = !Reflect.isFunction(Reflect.field(proto,f));			if( isfield )				for( f2 in apriv )					if( f == f2 ) {						isfield = false;						break;					}			if( isfield )				table_fields.add(f);		}		// set the manager and ready for further init		proto.local_manager = this;		init_list.add(untyped this);	}	public function get( id : Int, ?lock : Bool ) : T {		if( lock == null )			lock = true;		if( table_keys.length != 1 )			throw "Invalid number of keys";		if( id == null )			return null;		var x : Dynamic = untyped object_cache.get(id + table_name);		if( x != null && (!lock || x.update != no_update) )			return x;		var s = new StringBuf();		s.add("SELECT * FROM ");		s.add(table_name);		s.add(" WHERE ");		s.add(quoteField(table_keys[0]));		s.add(" = ");		addQuote(s,id);		if( lock )		s.add(FOR_UPDATE);		return object(s.toString(),lock);	}	public function getWithKeys( keys : {}, ?lock : Bool ) : T {		if( lock == null )			lock = true;		var x : Dynamic = getFromCache(untyped keys,false);		if( x != null && (!lock || x.update != no_update) )			return x;		var s = new StringBuf();		s.add("SELECT * FROM ");		s.add(table_name);		s.add(" WHERE ");		addKeys(s,keys);		if( lock )			s.add(FOR_UPDATE);		return object(s.toString(),lock);	}	public function search( x : {}, ?lock : Bool ) : List<T> {		if( lock == null )			lock = true;		var s = new StringBuf();		s.add("SELECT * FROM ");		s.add(table_name);		s.add(" WHERE ");		var first = true;		for( f in Reflect.fields(x) ) {			if( first )				first = false;			else				s.add(" AND ");			s.add(quoteField(f));			var d = Reflect.field(x,f);			if( d == null )				s.add(" IS NULL");			else {				s.add(" = ");				addQuote(s,d);			}		}		if( first )			s.add("TRUE");		if( lock )			s.add(FOR_UPDATE);		return objects(s.toString(),lock);	}	public function all( ?lock: Bool ) : List<T> {		if( lock == null )			lock = true;		return objects("SELECT * FROM " + table_name + if( lock ) FOR_UPDATE else "",lock);	}	public function count() : Int {		return execute("SELECT COUNT(*) FROM "+table_name).getIntResult(0);	}	public function quote( s : String ) : String {		return cnx.quote( s );	}	public function result( sql : String ) : Dynamic {		return cnx.request(sql).next();	}	public function results<T>( sql : String ) : List<T> {		return cast cnx.request(sql).results();	}	/* -------------------------- SPODOBJECT API -------------------------- */	public function doInsert( x : T ) {		unmake(x);		var s = new StringBuf();		var fields = new List();		var values = new List();		for( f in table_fields ) {			var v = Reflect.field(x,f);			if( v != null ) {				fields.add(quoteField(f));				values.add(v);			}		}		s.add("INSERT INTO ");		s.add(table_name);		s.add(" (");		s.add(fields.join(","));		s.add(") VALUES (");		var first = true;		for( v in values ) {			if( first )				first = false;			else				s.add(", ");			addQuote(s,v);		}		s.add(")");		execute(s.toString());		// table with one key not defined : suppose autoincrement		if( table_keys.length == 1 && Reflect.field(x,table_keys[0]) == null )			Reflect.setField(x,table_keys[0],cnx.lastInsertId());		addToCache(x);	}	public function doUpdate( x : T ) {		unmake(x);		var s = new StringBuf();		s.add("UPDATE ");		s.add(table_name);		s.add(" SET ");		var cache = Reflect.field(x,cache_field);		var mod = false;		for( f in table_fields ) {			var v = Reflect.field(x,f);			var vc = Reflect.field(cache,f);			if( v != vc ) {				if( mod )					s.add(", ");				else					mod = true;				s.add(quoteField(f));				s.add(" = ");				addQuote(s,v);				Reflect.setField(cache,f,v);			}		}		if( !mod )			return;		s.add(" WHERE ");		addKeys(s,x);		execute(s.toString());	}	public function doDelete( x : T ) {		var s = new StringBuf();		s.add("DELETE FROM ");		s.add(table_name);		s.add(" WHERE ");		addKeys(s,x);		execute(s.toString());	}	public function doSync( i : T ) {		object_cache.remove(makeCacheKey(i));		var i2 = getWithKeys(i,(cast i).update != no_update);		// delete all fields		for( f in Reflect.fields(i) )			Reflect.deleteField(i,f);		// copy fields from new object		for( f in Reflect.fields(i2) )			Reflect.setField(i,f,Reflect.field(i2,f));		// set same field-cache		Reflect.setField(i,cache_field,Reflect.field(i2,cache_field));		addToCache(i);	}	public function objectToString( it : T ) : String {		var s = new StringBuf();		s.add(table_name);		if( table_keys.length == 1 ) {			s.add("#");			s.add(Reflect.field(it,table_keys[0]));		} else {			s.add("(");			var first = true;			for( f in table_keys ) {				if( first )					first = false;				else					s.add(",");				s.add(quoteField(f));				s.add(":");				s.add(Reflect.field(it,f));			}			s.add(")");		}		return s.toString();	}	/* ---------------------------- INTERNAL API -------------------------- */	function cacheObject( x : T, lock : Bool ) {		addToCache(x);		untyped __dollar__objsetproto(x,class_proto.prototype);		Reflect.setField(x,cache_field,untyped __dollar__new(x));		if( !lock )			x.update = no_update;	}	function make( x : T ) {	}	function unmake( x : T ) {	}	function quoteField(f : String) {		var fsmall = f.toLowerCase();		if( fsmall == "read" || fsmall == "desc" || fsmall == "out" || fsmall == "group" )			return "`"+f+"`";		return f;	}	function addQuote( s : StringBuf, v : Dynamic ) {		var t = untyped __dollar__typeof(v);		if( untyped (t == __dollar__tint || t == __dollar__tnull) )			s.add(v);		else if( untyped t == __dollar__tbool )			s.add(if( v ) 1 else 0);		else			s.add(cnx.quote(Std.string(v)));	}	function addKeys( s : StringBuf, x : {} ) {		var first = true;		for( k in table_keys ) {			if( first )				first = false;			else				s.add(" AND ");			s.add(quoteField(k));			s.add(" = ");			var f = Reflect.field(x,k);			if( f == null )				throw ("Missing key "+k);			addQuote(s,f);		}	}	function execute( sql : String ) {		return cnx.request(sql);	}	function select( cond : String ) {		var s = new StringBuf();		s.add("SELECT * FROM ");		s.add(table_name);		s.add(" WHERE ");		s.add(cond);		s.add(FOR_UPDATE);		return s.toString();	}	function selectReadOnly( cond : String ) {		var s = new StringBuf();		s.add("SELECT * FROM ");		s.add(table_name);		s.add(" WHERE ");		s.add(cond);		return s.toString();	}	public function object( sql : String, lock : Bool ) : T {		var r = cnx.request(sql).next();		if( r == null )			return null;		var c = getFromCache(r,lock);		if( c != null )			return c;		cacheObject(r,lock);		make(r);		return r;	}	public function objects( sql : String, lock : Bool ) : List<T> {		var me = this;		var l = cnx.request(sql).results();		var l2 = new List<T>();		for( x in l ) {			var c = getFromCache(x,lock);			if( c != null )				l2.add(c);			else {				cacheObject(x,lock);				make(x);				l2.add(x);			}		}		return l2;	}	/* --------------------------- INIT / CLEANUP ------------------------- */	public static function initialize() {		var l = init_list;		init_list = new List();		for( m in l ) {			var rl : Void -> Array<Dynamic> = untyped m.class_proto.RELATIONS;			if( rl != null )				for( r in rl() )					m.initRelation(r);		}	}	public static function cleanup() {		object_cache = new Hash();	}	function initRelation(r : { prop : String, key : String, manager : Manager<Object>, lock : Bool } ) {		// setup getter/setter		var manager = r.manager;		var hprop = "__"+r.prop;		var hkey = r.key;		var lock = r.lock;		if( lock == null ) lock = true;		if( manager == null || manager.table_keys == null ) throw ("Invalid manager for relation "+table_name+":"+r.prop);		if( manager.table_keys.length != 1 ) throw ("Relation "+r.prop+"("+r.key+") on a multiple key table");		Reflect.setField(class_proto.prototype,"get_"+r.prop,function() {			var othis = untyped this;			var f = Reflect.field(othis,hprop);			if( f != null )				return f;			f = manager.get(Reflect.field(othis,hkey),lock);			Reflect.setField(othis,hprop,f);			return f;		});		Reflect.setField(class_proto.prototype,"set_"+r.prop,function(f) {			var othis = untyped this;			Reflect.setField(othis,hprop,f);			Reflect.setField(othis,hkey,Reflect.field(f,manager.table_keys[0]));			return f;		});		// remove prop from precomputed table_fields		// always add key to table fields (even if not declared)		table_fields.remove(r.prop);		table_fields.remove(r.key);		table_fields.add(r.key);	}	/* ---------------------------- OBJECT CACHE -------------------------- */	function makeCacheKey( x : T ) : String {		if( table_keys.length == 1 ) {			var k = Reflect.field(x,table_keys[0]);			if( k == null )				throw("Missing key "+table_keys[0]);			return Std.string(k)+table_name;		}		var s = new StringBuf();		for( k in table_keys ) {			var v = Reflect.field(x,k);			if( k == null )				throw("Missing key "+k);			s.add(v);			s.add("#");		}		s.add(table_name);		return s.toString();	}	function addToCache( x : T ) {		object_cache.set(makeCacheKey(x),x);	}	function getFromCache( x : T, lock : Bool ) : T {		var c : Dynamic = object_cache.get(makeCacheKey(x));		// restore update method since now the object is locked		if( c != null && lock && c.update == no_update )			c.update = class_proto.prototype.update;		return c;	}}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -