Browse Source

always compare haxe.io.Bytes if they are different objects before updating + added forceUpdate to handle in-place changes of haxe.io.Bytes

Nicolas Cannasse 13 năm trước cách đây
mục cha
commit
dfcefd45e1
1 tập tin đã thay đổi với 48 bổ sung33 xóa
  1. 48 33
      std/sys/db/Manager.hx

+ 48 - 33
std/sys/db/Manager.hx

@@ -63,7 +63,6 @@ class Manager<T : Object> {
 
 	var table_infos : SpodInfos;
 	var table_name : String;
-	var table_fields : List<String>;
 	var table_keys : Array<String>;
 	var class_proto : { prototype : Dynamic };
 
@@ -73,10 +72,6 @@ class Manager<T : Object> {
 		table_infos = haxe.Unserializer.run(m[0]);
 		table_name = quoteField(table_infos.name);
 		table_keys = table_infos.key;
-		table_fields = new List();
-		for( f in table_infos.fields )
-			table_fields.add(f.name);
-
 		// set the manager and ready for further init
 		class_proto = cast classval;
 		#if neko
@@ -129,32 +124,29 @@ class Manager<T : Object> {
 		var s = new StringBuf();
 		var fields = new List();
 		var values = new List();
-		var pos = 0;
-		for( f in table_fields ) {
-			var v = Reflect.field(x,f);
+		for( f in table_infos.fields ) {
+			var name = f.name;
+			var v = Reflect.field(x,name);
 			if( v != null ) {
-				fields.add(quoteField(f));
+				fields.add(quoteField(name));
 				values.add(v);
-			} else {
-				var inf = table_infos.fields[pos];
+			} else if( !f.isNull ) {
 				// if the field is not defined, give it a default value on insert
-				if( !inf.isNull )
-					switch( inf.t ) {
-					case DUInt, DTinyInt, DInt, DSingle, DFloat, DFlags(_), DBigInt, DTinyUInt, DSmallInt, DSmallUInt, DMediumInt, DMediumUInt:
-						Reflect.setField(x, f, 0);
-					case DBool:
-						Reflect.setField(x, f, false);
-					case DTinyText, DText, DString(_), DSmallText, DSerialized:
-						Reflect.setField(x, f, "");
-					case DSmallBinary, DNekoSerialized, DLongBinary, DBytes(_), DBinary:
-						Reflect.setField(x, f, haxe.io.Bytes.alloc(0));
-					case DDate, DDateTime, DTimeStamp:
-						// default date might depend on database
-					case DId, DUId, DBigId, DNull, DInterval, DEncoded:
-						// no default value for these
-					}
+				switch( f.t ) {
+				case DUInt, DTinyInt, DInt, DSingle, DFloat, DFlags(_), DBigInt, DTinyUInt, DSmallInt, DSmallUInt, DMediumInt, DMediumUInt:
+					Reflect.setField(x, name, 0);
+				case DBool:
+					Reflect.setField(x, name, false);
+				case DTinyText, DText, DString(_), DSmallText, DSerialized:
+					Reflect.setField(x, name, "");
+				case DSmallBinary, DNekoSerialized, DLongBinary, DBytes(_), DBinary:
+					Reflect.setField(x, name, haxe.io.Bytes.alloc(0));
+				case DDate, DDateTime, DTimeStamp:
+					// default date might depend on database
+				case DId, DUId, DBigId, DNull, DInterval, DEncoded:
+					// no default value for these
+				}
 			}
-			pos++;
 		}
 		s.add("INSERT INTO ");
 		s.add(table_name);
@@ -178,6 +170,17 @@ class Manager<T : Object> {
 		addToCache(x);
 	}
 
+	inline function isBinary( t : SpodInfos.SpodType ) {
+		return switch( t ) {
+			case DSmallBinary, DNekoSerialized, DLongBinary, DBytes(_), DBinary: true;
+			default: false;
+		};
+	}
+
+	inline function hasBinaryChanged( a : haxe.io.Bytes, b : haxe.io.Bytes ) {
+		return a != b && (a == null || b == null || a.compare(b) != 0);
+	}
+
 	function doUpdate( x : T ) {
 		if( untyped !x._lock )
 			throw "Cannot update a not locked object";
@@ -188,18 +191,19 @@ class Manager<T : Object> {
 		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 ) {
+		for( f in table_infos.fields ) {
+			var name = f.name;
+			var v : Dynamic = Reflect.field(x,name);
+			var vc : Dynamic = Reflect.field(cache,name);
+			if( v != vc && (!isBinary(f.t) || hasBinaryChanged(v,vc)) ) {
 				if( mod )
 					s.add(", ");
 				else
 					mod = true;
-				s.add(quoteField(f));
+				s.add(quoteField(name));
 				s.add(" = ");
 				getCnx().addValue(s,v);
-				Reflect.setField(cache,f,v);
+				Reflect.setField(cache,name,v);
 			}
 		}
 		if( !mod )
@@ -421,6 +425,17 @@ class Manager<T : Object> {
 		return lockMode;
 	}
 
+	/**
+		Remove the cached value for the given Object field : this will ensure
+		that the value is updated when calling .update(). This is necessary if
+		you are modifying binary data in-place since the cache will be modified
+		as well.
+	**/
+	public function forceUpdate( o : T, field : String ) {
+		// set a reference that will ensure != and .compare() != 0
+		Reflect.setField(Reflect.field(o,cache_field),field,null);
+	}
+
 	/* --------------------------- INIT / CLEANUP ------------------------- */
 
 	public static function initialize() {