Casts

This section describes introspection of EdgeDB type casts. Features like whether the casts are implicit can be discovered by introspecting schema::Cast.

Introspection of the schema::Cast:

  1. db>
  2. ...
  3. ...
  4. ...
  5. ...
  6. ...
  7. ...
  8. ...
  9. ...
  10. ...
  11. ...
  1. with module schema
  2. select ObjectType {
  3. name,
  4. links: {
  5. name,
  6. },
  7. properties: {
  8. name,
  9. }
  10. }
  11. filter .name = 'schema::Cast';
  1. {
  2. Object {
  3. name: 'schema::Cast',
  4. links: {
  5. Object { name: '__type__' },
  6. Object { name: 'from_type' },
  7. Object { name: 'to_type' }
  8. },
  9. properties: {
  10. Object { name: 'allow_assignment' },
  11. Object { name: 'allow_implicit' },
  12. Object { name: 'id' },
  13. Object { name: 'name' }
  14. }
  15. }
  16. }

Introspection of the possible casts from std::int64 to other types:

  1. db>
  2. ...
  3. ...
  4. ...
  5. ...
  6. ...
  7. ...
  8. ...
  1. with module schema
  2. select Cast {
  3. allow_assignment,
  4. allow_implicit,
  5. to_type: { name },
  6. }
  7. filter .from_type.name = 'std::int64'
  8. order by .to_type.name;
  1. {
  2. Object {
  3. allow_assignment: false,
  4. allow_implicit: true,
  5. to_type: Object { name: 'std::bigint' }
  6. },
  7. Object {
  8. allow_assignment: false,
  9. allow_implicit: true,
  10. to_type: Object { name: 'std::decimal' }
  11. },
  12. Object {
  13. allow_assignment: true,
  14. allow_implicit: false,
  15. to_type: Object { name: 'std::float32' }
  16. },
  17. Object {
  18. allow_assignment: false,
  19. allow_implicit: true,
  20. to_type: Object { name: 'std::float64' }
  21. },
  22. Object {
  23. allow_assignment: true,
  24. allow_implicit: false,
  25. to_type: Object { name: 'std::int16' }
  26. },
  27. Object {
  28. allow_assignment: true,
  29. allow_implicit: false,
  30. to_type: Object { name: 'std::int32' }
  31. },
  32. Object {
  33. allow_assignment: false,
  34. allow_implicit: false,
  35. to_type: Object { name: 'std::json' }
  36. },
  37. Object {
  38. allow_assignment: false,
  39. allow_implicit: false,
  40. to_type: Object { name: 'std::str' }
  41. }
  42. }

The allow_implicit property tells whether this is an implicit cast in all contexts (such as when determining the type of a set of mixed literals or resolving the argument types of functions or operators if there’s no exact match). For example, a literal 1 is an int64 and it is implicitly cast into a bigint or float64 if it is added to a set containing either one of those types:

  1. db>
  1. select {1, 2n};
  1. {1n, 2n}
  1. db>
  1. select {1, 2.0};
  1. {1.0, 2.0}

What happens if there’s no implicit cast between a couple of scalars in this type of example? EdgeDB checks whether there’s a scalar type such that all of the set elements can be implicitly cast into that:

  1. db>
  1. select introspect (typeof {<int64>1, <float32>2}).name;
  1. {'std::float64'}

The scalar types int64 and float32 cannot be implicitly cast into each other, but they both can be implicitly cast into float64.

The allow_assignment property tells whether this is an implicit cast during assignment if a more general implicit cast is not allowed. For example, consider the following type:

  1. type Example {
  2. property p_int16 -> int16;
  3. property p_float32 -> float32;
  4. property p_json -> json;
  5. }
  1. db>
  2. ...
  3. ...
  4. ...
  1. insert Example {
  2. p_int16 := 1,
  3. p_float32 := 2
  4. };
  1. {Object { id: <uuid>'...' }}
  1. db>
  2. ...
  3. ...
  1. insert Example {
  2. p_json := 3 # assignment cast to json not allowed
  3. };
  1. InvalidPropertyTargetError: invalid target for property
  2. 'p_json' of object type 'default::Example': 'std::int64'
  3. (expecting 'std::json')