locked
Table Type Ascription Only Partially Renames Columns RRS feed

  • Question

  • Hello,

    If a table is ascribed with a new type, the new type's column names are only partly applied to the table's columns. Is this partial renaming a feature or a bug? :-)
    let
      Data = #table({"A"}, {{1}}),
      WithNewType = Value.ReplaceType(Data, type table [Z = number])
    in
      Table.Schema(WithNewType) // reports the column name as Z
    
      //WithNewType[Z] // works
      //WithNewType[A] // errors because the column is now named Z
    
      //Table.SelectRows(WithNewType, each [Z] = 1) // doesn't work, even though Table.Schema now reports the column name as Z
      //Table.SelectRows(WithNewType, each [A] = 1) // works

    Above, Table.Schema(WithNewType) reports the column under its new (renamed) name of "Z". WithNewType[Z] also works. However, Table.SelectRows(WithNewType, each [Z] = 1) does not work; instead, the column needs to be referenced using its original name of "A" (instead of "Z").

    What's going on here? :-) Shouldn't the column be consistently referenceable by its new name?

    Thanks,

    Ben

    Tuesday, August 18, 2020 7:45 PM

Answers

  • The type and the underlying values can be out of sync. But PQ will assume they're consistent. There are some cases where only the type metadata is consulted, and other where the underlying values are used. Thus the apparent disconnect.

    Ehren

    • Marked as answer by Ben Gribaudo Thursday, August 27, 2020 4:14 PM
    Tuesday, August 25, 2020 6:53 PM
  • I don't think Value.ReplaceType is intended to allow renames. It's intended to allow the type metadata to be updated (i.e. the metadata attached to the types). So even if renaming something via Value.ReplaceType "works", it's probably not by design.

    EDIT: The way to do what you show above would be create a new function: (other as any) as any => Function(other)

    Ehren


    Wednesday, August 26, 2020 6:53 PM

All replies

  • For context, ascription seems to fully rename record fields. All of the cases below "see" the renamed field under its new name of Z.

    let
      Data = [A=123],
      WithNewType = Value.ReplaceType(Data, type [Z = number])
    in
      // WithNewType[Z] // works
      // Record.FieldNames(WithNewType) // reports the new field name of Z
      // Record.Field(WithNewType, "Z") // works - returns 123
      // Record.ToTable(WithNewType) // reports the new field name of Z
      // Table.FromRecords({WithNewType}) // returns a table with a single column named Z
      Table.SelectRows(Table.FromRecords({WithNewType}), each [Z] < 500) // works



    Wednesday, August 19, 2020 2:12 PM
  • The type and the underlying values can be out of sync. But PQ will assume they're consistent. There are some cases where only the type metadata is consulted, and other where the underlying values are used. Thus the apparent disconnect.

    Ehren

    • Marked as answer by Ben Gribaudo Thursday, August 27, 2020 4:14 PM
    Tuesday, August 25, 2020 6:53 PM
  • Thank you, Ehren!

    It sounds like when ascribing custom table and record types, the new type's field/column names should be identical to, and in the same order as, the value's current field/column types in order for M to work properly (even though the mashup engine doesn't enforce this when ascription occurs).

    What about for functions? From the language spec: "Formal parameter names are ignored for the purposes of determining function type conformance." Does this imply M will work fine even if an ascribed type's argument names differ from the function's original argument names?

    Thanks,
    Ben

    Wednesday, August 26, 2020 3:15 PM
  • Hi Ben. Regarding functions, I'm not sure exactly what you're asking. Can you provide an M example?

    Ehren

    Wednesday, August 26, 2020 4:50 PM
  • Sure!

    Is the following safe (note the argument rename)?

    let
        Function = (input) => input,
        NewType = type function (other as any) as any
    in
        Value.ReplaceType(Function, NewType)

    Based on this thread, my understanding is that renaming a field or column by ascribing a new record or table type (respectively) is not appropriate/safe. What about in the case of functions (this example)?

    Thanks,
    Ben

    Wednesday, August 26, 2020 6:49 PM
  • I don't think Value.ReplaceType is intended to allow renames. It's intended to allow the type metadata to be updated (i.e. the metadata attached to the types). So even if renaming something via Value.ReplaceType "works", it's probably not by design.

    EDIT: The way to do what you show above would be create a new function: (other as any) as any => Function(other)

    Ehren


    Wednesday, August 26, 2020 6:53 PM
  • Thank you, Ehren!

    I've updated Power Query M Primer (Part 18): Type System III – Custom Types to reflect this.

    Ben

    Thursday, August 27, 2020 4:15 PM