@@ -680,7 +680,8 @@ export class BaseRawConnection {
680680 capabilitiesFlags : number = RESTRICTED_CAPABILITIES ,
681681 options ?: QueryOptions ,
682682 ) : Promise < errors . EdgeDBError [ ] > {
683- let ctx : CodecContext | null = null ;
683+ let ctx = state . makeCodecContext ( ) ;
684+
684685 const wb = new WriteMessageBuffer ( ) ;
685686 wb . beginMessage ( chars . $O ) ;
686687
@@ -699,9 +700,6 @@ export class BaseRawConnection {
699700 wb . writeBuffer ( outCodec . tidBuffer ) ;
700701
701702 if ( inCodec ) {
702- if ( ctx == null ) {
703- ctx = new CodecContext ( state . codecs ) ;
704- }
705703 wb . writeBuffer ( this . _encodeArgs ( args , inCodec , ctx ) ) ;
706704 } else {
707705 wb . writeInt32 ( 0 ) ;
@@ -716,10 +714,6 @@ export class BaseRawConnection {
716714 let parsing = true ;
717715 let warnings : errors . EdgeDBError [ ] = [ ] ;
718716
719- if ( ctx == null ) {
720- ctx = new CodecContext ( state . codecs ) ;
721- }
722-
723717 while ( parsing ) {
724718 if ( ! this . buffer . takeMessage ( ) ) {
725719 await this . _waitForMessage ( ) ;
@@ -755,6 +749,8 @@ export class BaseRawConnection {
755749
756750 case chars . $T : {
757751 try {
752+ ctx = state . makeCodecContext ( )
753+
758754 const [
759755 newCard ,
760756 newInCodec ,
@@ -764,6 +760,37 @@ export class BaseRawConnection {
764760 __ ,
765761 _warnings ,
766762 ] = this . _parseDescribeTypeMessage ( query ) ;
763+
764+ /* Quoting the docs:
765+
766+ - If the declared input type descriptor does not match
767+ the expected value, a CommandDataDescription message is
768+ returned followed by a ParameterTypeMismatchError in
769+ an ErrorResponse message.
770+
771+ - If the declared output type descriptor does not match,
772+ the server will send a CommandDataDescription prior
773+ to sending any Data messages.
774+
775+ Therefore, basically receiving CommandDataDescription
776+ means that our codecs have outdate knowledge of the schema.
777+ The only exception to that is if our codecs were NULL codecs
778+ in the first place, in which case we're here because we want
779+ to learn
780+ */
781+ if (
782+ ( outCodec !== NULL_CODEC && outCodec . tid != newOutCodec . tid ) ||
783+ ( inCodec !== NULL_CODEC && inCodec . tid != newInCodec . tid )
784+ ) {
785+ Options . signalSchemaChange ( ) ;
786+
787+ // If this was the result of outCodec mismatch, we'll get
788+ // the information to build a new one, build it, and
789+ // then continue this loop to receiving and parsing data
790+ // messages. In this case we want a fresh new CodecContext.
791+ ctx = state . makeCodecContext ( ) ;
792+ }
793+
767794 const key = this . _getQueryCacheKey (
768795 query ,
769796 outputFormat ,
@@ -778,12 +805,30 @@ export class BaseRawConnection {
778805 outCodec = newOutCodec ;
779806 warnings = _warnings ;
780807 } catch ( e : any ) {
808+ // An error happened, so we don't know if we bumped the internal
809+ // schema tracker or not, so let's do it again to be on the safe
810+ // side.
811+ Options . signalSchemaChange ( ) ;
812+
813+ // Keep parsing the buffer, we'll raise it later.
781814 error = e ;
782815 }
783816 break ;
784817 }
785818
786819 case chars . $s : {
820+ // Quoting docs:
821+ //
822+ // If the declared state type descriptor does not match
823+ // the expected value, a StateDataDescription message is
824+ // returned followed by a StateMismatchError in
825+ // an ErrorResponse message
826+ //
827+ // If we're here it means the state data descriptor has changed,
828+ // which can be the result of a new global added, which is a schema
829+ // changes. So let's signal it just to be safe.
830+ Options . signalSchemaChange ( ) ;
831+
787832 this . _parseDescribeStateMessage ( ) ;
788833 break ;
789834 }
0 commit comments