Postgres: add description of an ENUM value? - django

I've got an ENUM column in Postgres 9.6:
CREATE TYPE my_type AS ENUM('foo', 'bar');
I'd like to add a human-readable description for each value in the enum, e.g. for foo, This is the foo value and it does stuff.
Is there any way to do this in Postgres? I'd like something like Django's choices field.

Nothing fancy can be done I think. Standard comment?..
t=# \x
Expanded display is on.
t=# comment on type my_type is 'foo: something fooish, bar: a place to avoid';
COMMENT
t=# \dT+ my_type
List of data types
-[ RECORD 1 ]-----+---------------------------------------------
Schema | public
Name | my_type
Internal name | my_type
Size | 4
Elements | foo +
| bar
Owner | postgres
Access privileges |
Description | foo: something fooish, bar: a place to avoid
with some nerd sniping:
t=# comment on type my_type is '{"foo": "something fooish", "bar": "a place to avoid"}';
COMMENT
t=# select pg_catalog.obj_description(t.oid, 'pg_type')::json->>'foo' from pg_type t where typname = 'my_type';
?column?
------------------
something fooish
(1 row)

Teoretically you can create two type with same dimension and use something like this:
CREATE TYPE my_type AS ENUM('foo', 'bar');
CREATE TYPE my_type_description AS ENUM('foo desc', 'bar desc');
CREATE FUNCTION show_desc(i my_type) RETURNS my_type_description AS $sql$
SELECT ((enum_range(NULL::my_type_description))[array_length(enum_range(NULL, i), 1)])::my_type_description;
$sql$ LANGUAGE SQL STABLE;
SELECT show_desc('foo');
show_desc
-----------
foo desc
(1 row)
SELECT show_desc('bar');
show_desc
-----------
bar desc
(1 row)

Related

Why NamedTuple of same types are not compatible?

Why NamedTuple of the same type are not compatible?
alias Data = NamedTuple(
title: String?
)
data : Data = { title: nil } # Explicitly specifying that
# it has ` : Data` type
proc = ->(data : Data){ p data }
proc.call data # And yet it says it's not
# of `Data` type
Error
Error: type must be NamedTuple(title: String | Nil), not NamedTuple(title: Nil)
Your assumption is incorrect: data : Data restricts the type of the local variable to Data (which is an alias for NamedTuple(title: String | Nil)). This type restriction does not affect the value assignment on the right hand side. The literal value {type: nil} is typed as NamedTuple(title: Nil). This type is compatible with the type restriction to Data, so it can be assigned to the variable.
This implicitly covariant type restriction does not apply with proc types. I'm not sure about the reasoning behind that. It seems that this should be able to work. So maybe it just needs to be implemented.
You can however explicitly cast NamedTuple(Nil) to NamedTuple(String | Nil):
alias Data = NamedTuple(
title: String?
)
data = { title: nil }.as(Data) # Cast named tuple to Data
proc = ->(data : Data){ p data }
proc.call data
However, it is usually not a good idea to work with named tuples as regular data types. They are only recommended for very specific use cases such as named arguments. Defining custom structs (for example using the record macro) is a better idea and gives you a more powerful and flexible data type.
I'd implement your example like this:
record Data,
title : String?
data = Data.new(title: nil)
proc = ->(data : Data){ p data }
proc.call data
This is a bug, please report it in the issue tracker. Thank you!

Problems using `u8` in Substrate and ink

I am trying to add a simple u8 to my Substrate Runtime Module:
decl_storage! {
trait Store for Module<T: Trait> as TemplateModule {
MyByte: u8;
}
}
However, I get a compiler error that it does not implement Parity Codec's Encode or Decode:
error[E0277]: the trait bound `u8: _IMPL_DECODE_FOR_Event::_parity_codec::Encode` is not satisfied
--> /Users/shawntabrizi/Documents/GitHub/substrate-package/substrate-node-template/runtime/src/template.rs:23:1
|
23 | / decl_storage! {
24 | | trait Store for Module<T: Trait> as TemplateModule {
25 | | MyByte: u8;
26 | | }
27 | | }
| |_^ the trait `_IMPL_DECODE_FOR_Event::_parity_codec::Encode` is not implemented for `u8`
A similar problem occurs when I try to store a u8 in a Substrate Smart Contract using ink!:
contract! {
struct MyContract {
value: storage::Value<u8>,
}
...
}
Error:
error[E0277]: the trait bound `u8: parity_codec::codec::Encode` is not satisfied
--> src/lib.rs:26:1
|
26 | / contract! {
27 | | struct MyContract {
28 | | value: storage::Value<u8>,
29 | | }
... |
49 | | }
50 | | }
| |_^ the trait `parity_codec::codec::Encode` is not implemented for `u8`
Why is that, and what can I do to resolve the issue?
Today, the parity_codec does not support Encoding of u8 due to avoid a type collision, since Vec<u8> is a special case from Vec<T>.
See: https://github.com/paritytech/parity-codec/issues/47
gavofyork:
Because it would otherwise make the two encodings: Vec<u8> and Vec<T: Codec> clash.
It is possible this could be fixed in the future with additional Rust features, but for now, you will need to store your single bytes as [u8; 1] and work with that type.
Substrate Runtime Module
One hacky solution for a Substrate Runtime Module looks something like this:
use support::{decl_module, decl_storage, decl_event, StorageValue, dispatch::Result};
use system::ensure_signed;
pub trait Trait: system::Trait {
type Event: From<Event<Self>> + Into<<Self as system::Trait>::Event>;
}
type U8 = [u8; 1];
decl_storage! {
trait Store for Module<T: Trait> as TemplateModule {
MyByte get(my_byte): U8;
}
}
decl_module! {
pub struct Module<T: Trait> for enum Call where origin: T::Origin {
fn deposit_event<T>() = default;
pub fn set_my_byte(origin, input: U8) -> Result {
let who = ensure_signed(origin)?;
<MyByte<T>>::put(input);
Self::deposit_event(RawEvent::MyByteStored(input, who));
Ok(())
}
pub fn add_to_byte(origin, input: U8) -> Result {
let who = ensure_signed(origin)?;
let my_byte = Self::my_byte()[0];
let my_new_byte = my_byte.checked_add(input[0]).ok_or("Overflow")?;
<MyByte<T>>::put([my_new_byte]);
Self::deposit_event(RawEvent::MyByteStored([my_new_byte], who));
Ok(())
}
}
}
decl_event!(
pub enum Event<T> where AccountId = <T as system::Trait>::AccountId {
MyByteStored(U8, AccountId),
}
);
Where we assign a new type type U8 = [u8; 1];. The choice of our new type name is important since it will trick the Polkadot UI to treat this value simply as a u8 for any input/output fields it generates. If you try to use a custom type like type Byte = [u8; 1], the UI will ask you to import the definition of that custom type. If you try to use [u8; 1] directly, the Polkadot UI will not know how to render the input/output of that value.
Furthermore, as of the time of writing this post, the decl_event! macro has an issue depositing a [u8; 1] directly due to pattern matching.
Note that you will need to treat this type like an array when you use it. add_to_byte() shows an example of that. So ultimately, you need to extract the first item of the array to extract the byte, and you need to wrap your byte in an array to set a U8:
let my_byte = Self::my_byte()[0];
...
<MyByte<T>>::put([my_new_byte]);
Other solutions may involve using other types which are natively supported like Vec<u8> or u16, and doing the appropriate checks on your runtime that this is treated like a single u8, but the UI will not know better.
Substrate Smart Contracts
I have not found a great solution for ink! yet, but you should be able to use [u8; 1] directly in all of your code. Again, you will need to treat it like an array for getters and setters. But when generating the ABI you will need to manually change the instances of [u8; 1] to u8 to trick the UI to do what you want.

Is it possible to create a polymorphic variant type dynamically using modules?

I'm trying to organzine and reuse my reasonML code. I have model module types that look like the following:
module Diet = {
type schemaType = [`DietSchema];
type idType = [`DietId(UUID.t)];
let schema = `DietSchema;
type idAsType('a) = [> | idType] as 'a;
};
module Ingredient = {
type schemaType = [`IngredientSchema];
type idType = [`IngredientId(UUID.t)];
let schema = `IngredientSchema;
type idAsType('a) = [> | idType] as 'a;
};
module Restriction = {
type schemaType = [`RestrictionSchema];
type idType = [`RestrictionId(UUID.t)];
let schema = `RestrictionSchema;
type idAsType('a) = [> | idType] as 'a;
};
And I would like to generate a types and functions from the idTypes and schemaTypes.
examples are:
type modelIdType = [
| Diet.idType
| Restriction.idType
| Ingredient.idType
];
type schemaType = [
| Diet.schemaType
| Restriction.schemaType
| Ingredient.schemaType
];
let modelIdToIdFunction = (recordIdType): (schemaType, UUID.t) =>
switch (recordIdType) {
| `DietId(uuid) => (Diet.schema, uuid)
| `RestrictionId(uuid) => (Restriction.schema, uuid)
| `IngredientId(uuid) => (Ingredient.schema, uuid)
};
So I'm attempting to construct a module using a functor passing each of the schemas through
module Diet : SchemaType = {
/* ... */
};
module type SchemaType {
type schemaType;
type idType;
let schema: [> schemaType];
type idAsType('a) = [> | idType] as 'a;
};
module ProcessSchema = (
Schema : SchemaType,
PrevFullSchema : FullSchema
) : (FullSchema) => {
type id = [> Schema.idType' | PrevFullSchema.id'('a)] as 'a;
/* type id = [PrevFullSchema.openId(PrevFullSchema.id) | Schema.idType]; */
/* type schema = [PrevFullSchema.schema | Schema.schema]; */
/* type openSchema = [PrevFullSchema.schema | Schema.schema]; */
};
The code above didn't work. I'm having trouble adding module types to the model modules at the top. I also attempted through a SchemaType module type but kept hitting The type idType is not a polymorphic variant type, When I wanted each model to have distinct polymorphic variable types.
So overall, I want to know if it is possible to create a polymorphic variant type that can be created or extended using modules and functors?
If not is it possible to construct polymorphic variant types using a "list of modules"?
Thanks
Someone asked a similar question back in 2002. According to one of the OCaml language developers, it's not possible to dynamically extend polymorphic variant types like that: https://caml-list.inria.narkive.com/VVwLM96e/module-types-and-polymorphic-variants . The relevant bit:
The functor definition is refused because
"The type M.t is not a polymorphic variant type"
Is there a workaround?
Not that I know. Polymorphic variant extension only works for known
closed variant types, otherwise it would not be sound.
The rest of the post has a suggestion which boils down to capturing the new variant types inside different tags, but again that wouldn't work for your use case of dynamically 'adding together' types using a functor.
For the types you can use an extensible variant type. But for the modelIdToIdFunction function given a list of modules I think you can only search through the list, which won't scale.
You should extend the uuid with an ID for each module so you can create a lookup table from module_id to the module from the list for fast access.

How to select all member which has a given attribute name with UDA?

Considering an attribute which take a delegate ( predicate function as std.algorithm.filter )
struct Section( alias pred ){}
This is used to annotate a field like this:
struct A {
#Section!( ( words ) => words[0] == '#' )
string b;
int c;
}
Field b is annotate by a delegate which return true if a string start by # when called
So how to retrieve all field which are annotated by #Section ?
Is it possible to called at runtime his delegate with a string as parameter and know if is true or not ?
thanks
So how to retrieve all field which are annotated by #Section ?
First, use allMembers or .tupleof to enumerate over all the fields of the struct.
Then, enumerate over all attributes attached to each field using getAttributes. Check if #Section is present in the field.
Is it possible to called at runtime his delegate with a string as parameter and know if is true or not ?
You should save an alias within the Section structure. For example:
struct Section(alias pred)
{
alias fun = pred;
}
Then, just reference the getAttributes result tuple member.

CASTING attributes for Ordering on a Doctrine2 DQL Query

I am trying to get Doctrine2 Entities, ordered by their ID which apparently is a String even though it contains only Numbers.
So what I would like to do is something like this:
SELECT entity1, cast (entity1.id AS integer) AS orderId
FROM Namespace\Bla\MyEntity
ORDER BY orderId
Is there a way to do something like this in Doctrine2?
Or, what would be the best practise to get my Result if i can't change the type of the id (due to customer requirements of course)?
Attention: I am not asking SQL Code, i am asking for a Doctrine2 Solution, preferably in DQL
You should be able to add your own function to implement this feature.
The class would look something like this:
namespace MyProject\Query;
use Doctrine\ORM\Query\AST\Functions\FunctionNode;
use Doctrine\ORM\Query\Lexer;
use Doctrine\ORM\Query\Parser;
use Doctrine\ORM\Query\SqlWalker;
class CastAsInteger extends FunctionNode
{
public $stringPrimary;
public function getSql(SqlWalker $sqlWalker)
{
return 'CAST(' . $this->stringPrimary->dispatch($sqlWalker) . ' AS integer)';
}
public function parse(Parser $parser)
{
$parser->match(Lexer::T_IDENTIFIER);
$parser->match(Lexer::T_OPEN_PARENTHESIS);
$this->stringPrimary = $parser->StringPrimary();
$parser->match(Lexer::T_CLOSE_PARENTHESIS);
}
}
You'll need to register your function:
$config = $em->getConfiguration();
$config->addCustomNumericFunction('INT', CastAsInteger::class);
Then you can use it:
SELECT e, INT(e.id) AS HIDDEN orderId
FROM Namespace\Bla\MyEntity e
ORDER BY orderId
PS: By adding the HIDDEN keyword, the alias orderId won't be in the results (and is only used for ordering).
Based on Jasper N. Brouwer answer, this is a little bit enhanced solution:
<?php
namespace MyProject\Query;
use Doctrine\ORM\Query\AST\Functions\FunctionNode;
use Doctrine\ORM\Query\Lexer;
use Doctrine\ORM\Query\Parser;
use Doctrine\ORM\Query\SqlWalker;
class Cast extends FunctionNode
{
/** #var \Doctrine\ORM\Query\AST\PathExpression */
protected $first;
/** #var string */
protected $second;
/**
* #param SqlWalker $sqlWalker
*
* #return string
*/
public function getSql(SqlWalker $sqlWalker)
{
return sprintf("CAST(%s AS %s)",
$this->first->dispatch($sqlWalker),
$this->second
);
}
/**
* #param Parser $parser
*
* #return void
*/
public function parse(Parser $parser)
{
$parser->match(Lexer::T_IDENTIFIER);
$parser->match(Lexer::T_OPEN_PARENTHESIS);
$this->first = $parser->ArithmeticPrimary();
$parser->match(Lexer::T_AS);
$parser->match(Lexer::T_IDENTIFIER);
$this->second = $parser->getLexer()->token['value'];
$parser->match(Lexer::T_CLOSE_PARENTHESIS);
}
}
Now it should be possible to write DQL like this:
SELECT e, CAST(e.id AS integer) AS HIDDEN orderId FROM Namespace\Bla\MyEntity e ORDER BY orderId
Try this one by with out changing the data type
select (entity1 * 1) as display_value, entity1 as return_value
from Table_Name
order by 1 asc;
Think it's better to use some extra functional in such cases ( without trying "to circumvent" theirs). E.g. an excellent solution adding almost all necessary ( not supported from box ) stuff for Doctrine 2 is DoctrineExtensions by beberlei (github). With it it's possible to use directly CAST-statement like in OP's case:
("Symfony-example") E.g. in your config.xml add lines:
orm:
..
entity_managers:
....
dql:
....
string_functions:
CAST: DoctrineExtensions\Query\Mysql\Cast
Then U can use it like:
SELECT entity1, CAST(entity1.id AS integer) AS orderId
FROM Namespace\Bla\MyEntity
ORDER BY orderId
Not sure if this works, but to access an entity ID you need the IDENTITY() DQL function. Try this:
SELECT entity1 FROM Namespace\Bla\MyEntity ORDER BY IDENTITY(entity1)
I think you want order by entity1. if your entity1 data type is integer then no need to change it into integer or if it is not then you should do it. below is query for you.try this one.
select entity1,cast(entity1 as integer) as order_id from Table_Name order by 1 asc;
I just did something similar in my own code yesterday. I was able to do:
select cast(entity1 as int) as OrderID
from yourtablename
where yourconditions
I had to actually cast mine as money and then int, but if you don't have a decimal, you should not have that issue. You can also try casting as numeric or using convert instead of cast, but cast is better in this situation.
Why do you need entity1 as a column if you already have the same value in OrderID?