@@ -18,6 +18,7 @@ import com.google.firebase.firestore.CollectionReference
1818import com.google.firebase.firestore.FirebaseFirestore
1919import com.google.firebase.firestore.UserDataReader
2020import com.google.firebase.firestore.VectorValue
21+ import com.google.firebase.firestore.model.DocumentKey.KEY_FIELD_NAME
2122import com.google.firebase.firestore.model.MutableDocument
2223import com.google.firebase.firestore.model.ResourcePath
2324import com.google.firebase.firestore.model.Values
@@ -292,9 +293,17 @@ internal constructor(
292293 private val fields: Array <out Selectable >,
293294 options: InternalOptions = InternalOptions .EMPTY
294295) : Stage <AddFieldsStage >(" add_fields" , options) {
296+ init {
297+ for (field in fields) {
298+ val alias = field.alias
299+ require(alias != Field .DOCUMENT_ID .alias, { " Alias ${Field .DOCUMENT_ID .alias} is reserved" })
300+ require(alias != Field .CREATE_TIME .alias, { " Alias ${Field .CREATE_TIME .alias} is reserved" })
301+ require(alias != Field .UPDATE_TIME .alias, { " Alias ${Field .UPDATE_TIME .alias} is reserved" })
302+ }
303+ }
295304 override fun self (options : InternalOptions ) = AddFieldsStage (fields, options)
296305 override fun args (userDataReader : UserDataReader ): Sequence <Value > =
297- sequenceOf(encodeValue(fields.associate { it.getAlias() to it.toProto(userDataReader) }))
306+ sequenceOf(encodeValue(fields.associate { it.alias to it.toProto(userDataReader) }))
298307}
299308
300309/* *
@@ -368,8 +377,8 @@ internal constructor(
368377 fun withGroups (group : Selectable , vararg additionalGroups : Any ) =
369378 AggregateStage (
370379 accumulators,
371- mapOf (group.getAlias() to group.getExpr() )
372- .plus(additionalGroups.map(Selectable ::toSelectable).associateBy(Selectable ::getAlias ))
380+ mapOf (group.alias to group.expr )
381+ .plus(additionalGroups.map(Selectable ::toSelectable).associateBy(Selectable ::alias ))
373382 )
374383
375384 override fun args (userDataReader : UserDataReader ): Sequence <Value > =
@@ -539,7 +548,7 @@ internal constructor(private val offset: Int, options: InternalOptions = Interna
539548}
540549
541550internal class SelectStage
542- private constructor (private val fields: Array <out Selectable >, options: InternalOptions ) :
551+ private constructor (internal val fields: Array <out Selectable >, options: InternalOptions ) :
543552 Stage <SelectStage >(" select" , options) {
544553 companion object {
545554 @JvmStatic
@@ -555,14 +564,18 @@ private constructor(private val fields: Array<out Selectable>, options: Internal
555564 }
556565 override fun self (options : InternalOptions ) = SelectStage (fields, options)
557566 override fun args (userDataReader : UserDataReader ): Sequence <Value > =
558- sequenceOf(encodeValue(fields.associate { it.getAlias() to it.toProto(userDataReader) }))
567+ sequenceOf(encodeValue(fields.associate { it.alias to it.toProto(userDataReader) }))
559568}
560569
561570internal class SortStage
562571internal constructor (
563572 private val orders: Array <out Ordering >,
564573 options: InternalOptions = InternalOptions .EMPTY
565574) : Stage <SortStage >(" sort" , options) {
575+ companion object {
576+ internal val BY_DOCUMENT_ID = SortStage (arrayOf(Field .DOCUMENT_ID .ascending()))
577+ }
578+
566579 override fun self (options : InternalOptions ) = SortStage (orders, options)
567580 override fun args (userDataReader : UserDataReader ): Sequence <Value > =
568581 orders.asSequence().map { it.toProto(userDataReader) }
@@ -603,6 +616,16 @@ internal constructor(
603616 .forEach { p -> emit(p.first) }
604617 }
605618 }
619+
620+ internal fun withStableOrdering (): SortStage {
621+ val position = orders.indexOfFirst { (it.expr as ? Field )?.alias == KEY_FIELD_NAME }
622+ return if (position < 0 ) {
623+ // Append the DocumentId to orders to make ordering stable.
624+ SortStage (orders.asList().plus(Field .DOCUMENT_ID .ascending()).toTypedArray(), options)
625+ } else {
626+ this
627+ }
628+ }
606629}
607630
608631internal class DistinctStage
@@ -612,14 +635,22 @@ internal constructor(
612635) : Stage <DistinctStage >(" distinct" , options) {
613636 override fun self (options : InternalOptions ) = DistinctStage (groups, options)
614637 override fun args (userDataReader : UserDataReader ): Sequence <Value > =
615- sequenceOf(encodeValue(groups.associate { it.getAlias() to it.toProto(userDataReader) }))
638+ sequenceOf(encodeValue(groups.associate { it.alias to it.toProto(userDataReader) }))
616639}
617640
618641internal class RemoveFieldsStage
619642internal constructor (
620643 private val fields: Array <out Field >,
621644 options: InternalOptions = InternalOptions .EMPTY
622645) : Stage <RemoveFieldsStage >(" remove_fields" , options) {
646+ init {
647+ for (field in fields) {
648+ val alias = field.alias
649+ require(alias != Field .DOCUMENT_ID .alias, { " Alias ${Field .DOCUMENT_ID .alias} is required" })
650+ require(alias != Field .CREATE_TIME .alias, { " Alias ${Field .CREATE_TIME .alias} is required" })
651+ require(alias != Field .UPDATE_TIME .alias, { " Alias ${Field .UPDATE_TIME .alias} is required" })
652+ }
653+ }
623654 override fun self (options : InternalOptions ) = RemoveFieldsStage (fields, options)
624655 override fun args (userDataReader : UserDataReader ): Sequence <Value > =
625656 fields.asSequence().map(Field ::toProto)
@@ -746,11 +777,11 @@ internal constructor(
746777 */
747778 @JvmStatic
748779 fun withField (arrayField : String , alias : String ): UnnestStage =
749- UnnestStage (Expr .field(arrayField).alias(alias))
780+ UnnestStage (Expr .Companion . field(arrayField).alias(alias))
750781 }
751782 override fun self (options : InternalOptions ) = UnnestStage (selectable, options)
752783 override fun args (userDataReader : UserDataReader ): Sequence <Value > =
753- sequenceOf(encodeValue(selectable.getAlias() ), selectable.toProto(userDataReader))
784+ sequenceOf(encodeValue(selectable.alias ), selectable.toProto(userDataReader))
754785
755786 /* *
756787 * Adds index field to emitted documents
0 commit comments