@@ -685,7 +685,76 @@ $data.Class.define('$data.EntityContext', null, null,
685685 callBack = $data . typeSystem . createCallbackSetting ( callBack ) ;
686686 var that = this ;
687687 var clbWrapper = { } ;
688- clbWrapper . success = function ( query ) {
688+ clbWrapper . success = that . executeQuerySuccess ( that , returnTransaction , callBack ) ;
689+ clbWrapper . error = that . executeQueryError ( that , returnTransaction , callBack ) ;
690+
691+ var sets = query . getEntitySets ( ) ;
692+
693+ var authorizedFn = function ( ) {
694+ var ex = true ;
695+ var wait = false ;
696+ var ctx = that ;
697+
698+ var readyFn = function ( cancel ) {
699+ if ( cancel === false ) ex = false ;
700+
701+ if ( ex ) {
702+ if ( query . transaction ) {
703+ if ( $data . QueryCache && $data . QueryCache . isInCache ( that , query ) ) {
704+ $data . QueryCache . executeQuery ( that , query , clbWrapper ) ;
705+ } else {
706+ ctx . storageProvider . executeQuery ( query , clbWrapper ) ;
707+ }
708+ } else {
709+ ctx . beginTransaction ( function ( tran ) {
710+ query . transaction = tran ;
711+ if ( $data . QueryCache && $data . QueryCache . isInCache ( that , query ) ) {
712+ $data . QueryCache . executeQuery ( that , query , clbWrapper ) ;
713+ } else {
714+ ctx . storageProvider . executeQuery ( query , clbWrapper ) ;
715+ }
716+ } ) ;
717+ }
718+ } else {
719+ query . rawDataList = [ ] ;
720+ query . result = [ ] ;
721+ clbWrapper . success ( query ) ;
722+ }
723+ } ;
724+
725+ var i = 0 ;
726+ var callbackFn = function ( cancel ) {
727+ if ( cancel === false ) ex = false ;
728+
729+ var es = sets [ i ] ;
730+ if ( es . beforeRead ) {
731+ i ++ ;
732+ var r = es . beforeRead . call ( this , sets , query ) ;
733+ if ( typeof r === 'function' ) {
734+ r . call ( this , ( i < sets . length && ex ) ? callbackFn : readyFn , sets , query ) ;
735+ } else {
736+ if ( r === false ) ex = false ;
737+
738+ if ( i < sets . length && ex ) {
739+ callbackFn ( ) ;
740+ } else readyFn ( ) ;
741+ }
742+ } else readyFn ( ) ;
743+ } ;
744+
745+ if ( sets . length ) callbackFn ( ) ;
746+ else readyFn ( ) ;
747+ } ;
748+
749+ if ( this . user && this . checkPermission ) {
750+ this . checkPermission ( query . expression . nodeType === $data . Expressions . ExpressionType . BatchDelete ? $data . Access . DeleteBatch : $data . Access . Read , this . user , sets , {
751+ success : authorizedFn ,
752+ error : clbWrapper . error
753+ } ) ;
754+ } else authorizedFn ( ) ;
755+ } ,
756+ executeQuerySuccess : function ( that , returnTransaction , callBack ) {
757+ return function ( query ) {
689758 if ( $data . QueryCache && $data . QueryCache . isCacheable ( that , query ) ) {
690759 $data . QueryCache . addToCache ( that , query ) ;
691760 }
@@ -762,78 +831,166 @@ $data.Class.define('$data.EntityContext', null, null,
762831 if ( sets . length ) callbackFn ( ) ;
763832 else readyFn ( ) ;
764833 } ;
765-
766- clbWrapper . error = function ( ) {
767- if ( returnTransaction )
834+ } ,
835+ executeQueryError : function ( that , returnTransaction , callBack ) {
836+ return function ( ) {
837+ if ( returnTransaction )
768838 callBack . error . apply ( this , arguments ) ;
769839 else
770840 callBack . error . apply ( this , Array . prototype . filter . call ( arguments , function ( p ) { return ! ( p instanceof $data . Transaction ) ; } ) ) ;
771841 } ;
772- var sets = query . getEntitySets ( ) ;
842+ } ,
773843
774- var authorizedFn = function ( ) {
775- var ex = true ;
776- var wait = false ;
777- var ctx = that ;
778844
779- var readyFn = function ( cancel ) {
780- if ( cancel === false ) ex = false ;
845+ batchExecuteQuery : function ( queryableOptions , callBack , transaction ) {
846+ var pHandler = new $data . PromiseHandler ( ) ;
847+ var cbWrapper = pHandler . createCallback ( callBack ) ;
781848
782- if ( ex ) {
783- if ( query . transaction ) {
784- if ( $data . QueryCache && $data . QueryCache . isInCache ( that , query ) ) {
785- $data . QueryCache . executeQuery ( that , query , clbWrapper ) ;
786- } else {
787- ctx . storageProvider . executeQuery ( query , clbWrapper ) ;
788- }
789- } else {
790- ctx . beginTransaction ( function ( tran ) {
791- query . transaction = tran ;
792- if ( $data . QueryCache && $data . QueryCache . isInCache ( that , query ) ) {
793- $data . QueryCache . executeQuery ( that , query , clbWrapper ) ;
794- } else {
795- ctx . storageProvider . executeQuery ( query , clbWrapper ) ;
796- }
797- } ) ;
798- }
799- } else {
800- query . rawDataList = [ ] ;
801- query . result = [ ] ;
802- clbWrapper . success ( query ) ;
803- }
804- } ;
849+ var self = this ;
850+ var methodOperationMappings = {
851+ count : 'length' ,
852+ length : 'length' ,
853+ forEach : 'forEach' ,
854+ toArray : 'toArray' ,
855+ single : 'single' ,
856+ some : 'some' ,
857+ every : 'every' ,
858+ first : 'first' ,
859+ removeAll : 'batchDelete'
860+ } ;
861+ var methodFrameMappings = {
862+ count : 'CountExpression' ,
863+ length : 'CountExpression' ,
864+ forEach : 'ForEachExpression' ,
865+ toArray : 'ToArrayExpression' ,
866+ single : 'SingleExpression' ,
867+ some : 'SomeExpression' ,
868+ every : 'EveryExpression' ,
869+ first : 'FirstExpression' ,
870+ removeAll : 'BatchDeleteExpression'
871+ } ;
805872
806- var i = 0 ;
807- var callbackFn = function ( cancel ) {
808- if ( cancel === false ) ex = false ;
809873
810- var es = sets [ i ] ;
811- if ( es . beforeRead ) {
812- i ++ ;
813- var r = es . beforeRead . call ( this , sets , query ) ;
814- if ( typeof r === 'function' ) {
815- r . call ( this , ( i < sets . length && ex ) ? callbackFn : readyFn , sets , query ) ;
816- } else {
817- if ( r === false ) ex = false ;
874+ var returnFunc = function ( ) {
875+ return pHandler . getPromise ( ) ;
876+ }
818877
819- if ( i < sets . length && ex ) {
820- callbackFn ( ) ;
821- } else readyFn ( ) ;
878+ if ( typeof queryableOptions . length != "number" ) {
879+ cbWrapper . error ( new Exception ( 'QueryableOptions array parameter missing' , 'Invalid arguments' ) ) ;
880+ return returnFunc ( ) ;
881+ }
882+
883+ var qOptions = [ ] ;
884+ for ( var i = 0 ; i < queryableOptions . length ; i ++ ) {
885+ var queryOption = { } ;
886+ if ( queryableOptions [ i ] instanceof $data . Queryable ) {
887+ queryOption . queryable = queryableOptions [ i ] ;
888+ queryOption . method = 'toArray' ;
889+ } else if ( queryableOptions [ i ] . queryable instanceof $data . Queryable ) {
890+ queryOption . queryable = queryableOptions [ i ] . queryable ;
891+ queryOption . method = queryableOptions [ i ] . method || 'toArray' ;
892+ } else if ( queryableOptions [ i ] [ 0 ] instanceof $data . Queryable ) {
893+ queryOption . queryable = queryableOptions [ i ] [ 0 ] ;
894+ queryOption . method = queryableOptions [ i ] [ 1 ] || 'toArray' ;
895+ } else {
896+ cbWrapper . error ( new Exception ( '$data.Queryable is missing in queryableOptions at index ' + i , 'Invalid arguments' ) ) ;
897+ return returnFunc ( ) ;
898+ }
899+
900+ if ( queryOption . queryable . entityContext !== self ) {
901+ cbWrapper . error ( new Exception ( 'Queryable at index ' + i + ' contains different entity context' , 'Invalid arguments' ) ) ;
902+ return returnFunc ( ) ;
903+ }
904+
905+ queryOption . queryable . _checkOperation ( methodOperationMappings [ queryOption . method ] || queryOption . method ) ;
906+ qOptions . push ( queryOption ) ;
907+ }
908+
909+
910+ var executableQueries = [ ] ;
911+ for ( var i = 0 ; i < qOptions . length ; i ++ ) {
912+ var queryOption = qOptions [ i ] ;
913+
914+ var frameExpressionName = methodFrameMappings [ queryOption . method ] || queryOption . method ;
915+ if ( frameExpressionName && $data . Expressions [ frameExpressionName ] && $data . Expressions [ frameExpressionName ] . isAssignableTo ( $data . Expressions . FrameOperator ) ) {
916+
917+ var queryExpression = Container [ 'create' + frameExpressionName ] ( queryOption . queryable . expression ) ;
918+ var preparator = Container . createQueryExpressionCreator ( queryOption . queryable . entityContext ) ;
919+
920+ try {
921+ var expression = preparator . Visit ( queryExpression ) ;
922+ queryOption . queryable . entityContext . log ( { event : "EntityExpression" , data : expression } ) ;
923+
924+ var queryable = Container . createQueryable ( queryOption . queryable , expression ) ;
925+ executableQueries . push ( queryable ) ;
926+ } catch ( e ) {
927+ cbWrapper . error ( e ) ;
928+ return returnFunc ( ) ;
929+ }
930+ } else {
931+ cbWrapper . error ( new Exception ( 'Invalid frame method \'' + frameExpressionName + '\' in queryableOptions at index ' + i , 'Invalid arguments' ) ) ;
932+ return returnFunc ( ) ;
933+ }
934+ }
935+
936+ var queryResults = [ ] ;
937+ if ( self . storageProvider . supportedContextOperation && self . storageProvider . supportedContextOperation . batchExecuteQuery ) {
938+ //wrap queries
939+ var batchExecuteQueryExpression = Container . createBatchExecuteQueryExpression ( executableQueries . map ( function ( queryable ) {
940+ return new $data . Query ( queryable . expression , queryable . defaultType , self ) ;
941+ } ) ) ;
942+
943+ var batchExecuteQuery = Container . createQueryable ( self , batchExecuteQueryExpression ) ;
944+ self . executeQuery ( batchExecuteQuery , {
945+ success : function ( results ) {
946+ var batchResult = [ ] ;
947+ var hasError = false ;
948+ for ( var i = 0 ; i < results . length && ! hasError ; i ++ ) {
949+ var query = results [ i ] ;
950+ self . executeQuerySuccess ( self , returnTransaction , {
951+ success : function ( result ) {
952+ batchResult . push ( result ) ;
953+ } ,
954+ error : function ( ) {
955+ hasError = true ;
956+ }
957+ } ) ( query ) ;
958+ }
959+ if ( ! hasError ) {
960+ self . _applyTransaction ( cbWrapper , cbWrapper . success , [ batchResult ] , batchExecuteQuery . transaction , returnTransaction ) ;
822961 }
823- } else readyFn ( ) ;
824- } ;
825962
826- if ( sets . length ) callbackFn ( ) ;
827- else readyFn ( ) ;
828- } ;
963+ } ,
964+ error : cbWrapper . error
965+ } , transaction ) ;
966+ } else {
967+ var returnTransaction = this . _isReturnTransaction ( transaction ) ;
968+
969+ var readIterator = function ( queries , index , iteratorCallback , itTransaction ) {
970+ var query = queries [ index ] ;
971+ if ( ! query ) {
972+ return iteratorCallback . success ( itTransaction ) ;
973+ }
829974
830- if ( this . user && this . checkPermission ) {
831- this . checkPermission ( query . expression . nodeType === $data . Expressions . ExpressionType . BatchDelete ? $data . Access . DeleteBatch : $data . Access . Read , this . user , sets , {
832- success : authorizedFn ,
833- error : clbWrapper . error
834- } ) ;
835- } else authorizedFn ( ) ;
975+ self . executeQuery ( executableQueries [ index ] , {
976+ success : function ( result , tr ) {
977+ queryResults . push ( result ) ;
978+ readIterator ( executableQueries , index + 1 , iteratorCallback , tr ) ;
979+ } ,
980+ error : iteratorCallback . error
981+ } , itTransaction ) ;
982+ }
983+
984+ readIterator ( executableQueries , 0 , {
985+ success : function ( lastTran ) {
986+ self . _applyTransaction ( cbWrapper , cbWrapper . success , [ queryResults ] , lastTran , returnTransaction ) ;
987+ } ,
988+ error : cbWrapper . error
989+ } , transaction )
990+ }
991+ return returnFunc ( ) ;
836992 } ,
993+
837994 saveChanges : function ( callback , transaction ) {
838995 /// <signature>
839996 /// <summary>
0 commit comments