I have a table called persons that have three columns called id, name and birth.
I can get name and birth but I need to calculate the age of the person using its birth date. I want to use the PostgreSQL's function: age(timestamp). But I don't know to use it.
Is there any way to use a PostgreSQL's function?
I was trying to use it in the view but then I realize it will not work:
$person = \app\models\Persons::findOne(['id' => 1234]);
$myName = $person->name;
$myBirth = $person->birth;
$myAge = $person->age(birth);
Should I change the model? I don't know where to use the age function.
In your model you should define public property public $age;. Then, your select statement should be like this:
$person = Persons::find()->select(['name', 'birth', 'age(birth) as age'])->andWhere(['id' => 1234])->one();
Then you can access it as property:
$person->age;
Related
I have an order table and an orderStatus table, their relationship is as seen below:
I want to be able to change 'StatusID' to the value 2, of a specific order (i am able to get the specific order ID, and have loaded it into an integer variable) using a lambda expression within an action result - would there be any easy way of doing this?
So far i have tried:
//get specific order ID
int currentOrderId = newConfirmedOrderLine.OrderID;
//-----
Order statusChange = new Order();
statusChange.OrderStatus.StatusID = 2;
DBAccessor.SaveChanges();
I am new to linq and lambda, so any explanation with an answer would be greatly appreciated!
If DBAccessor is a DbContext then this could/should work. You need to load the Order entity that you want to change from the DBAccessor.Order DbSet, change it by setting a property, and then call SaveChanges.
var orderStatus = DBAccessor.OrderStatus.First(x => x.StatusID == 2);
var order = DBAccessor.Order.Find(currentOrderId);
order.OrderStatus = orderStatus;
DBAccessor.SaveChanges();
I modified my models date property to can calculate birthdays, but now when the date is loaded in my form(I use Form collective) I get it like 1979-07-17 00:00:00 right output should be 1979-07-17
protected $dates = ['geburtstag'];
public function age()
{
return $this->geburtstag->diffInYears(Carbon::now());
}
I tried to modify from model like
protected $geburtstagFormat = 'Y-m-d';
but did not help.
What I do wrong in this case
Why don't you just use $model->geburtstag->format('Y-m-d')?
You can also create a mutaror in your model like:
public function getGeburstagDateAttribute($value) {
return $this->geburtstag->format('Y-m-d');
}
and use it like this:
$model->geburtstag_date // outputs geburtstag date in 'Y-m-d' format
To set the date format in a model, use protected $dateFormat = 'Y-m-d'; inside the model.
Another way of doing it
First parse the $this->geburtstag->diffInYears(Carbon::now())
$createdAt = Carbon::parse($this->geburtstag->diffInYears(Carbon::now()));
Then you can use
$suborder['payment_date'] = $createdAt->format('M d Y');
If you don't want to store the time of birth you should change the data type in your database to date instead of from timestamp or datetime. This will solve the problem automatically since when you call the attribute on your view, this extract exactly how it's shown on database. Otherwise, if you want to keep the database unchanged you have to define a mutator in your model, like this:
public function getGeburstag($value){
return Carbon::parse($value)->toDateString();
}
This will replace the original value of geburtag attribute to its values in Y-m-d format.
This is the query I am trying to run in PostgreSQL:
SELECT * FROM message WHERE id IN (
SELECT unnest(message_ids) "mid"
FROM session_messages WHERE session_id = '?' ORDER BY "mid" ASC
);
However, I am not able do something:
create.selectFrom(Tables.MESSAGE).where(Tables.MESSAGE.ID.in(
create.select(DSL.unnest(..))
Because DSL.unnest is a Table<?>, which makes sense since it is trying to take a List-like object (mostly a literal) and convert it to table.
I have a feeling that I need to find a way to wrap the function around my field name, but I have no clue as to how to proceed.
NOTE. The field message_ids is of type bigint[].
EDIT
So, this is how I am doing it now, and it works exactly as expected, but I am not sure if this is the best way to do it:
Field<Long> unnestMessageIdField = DSL.field(
"unnest(" + SESSION_MESSAGES.MESSAGE_IDS.getName() + ")",
Long.class)
.as("mid");
Field<Long> messageIdField = DSL.field("mid", Long.class);
MESSAGE.ID.in(
ctx.select(messageIdField).from(
ctx.select(unnestMessageIdField)
.from(Tables.CHAT_SESSION_MESSAGES)
.where(Tables.CHAT_SESSION_MESSAGES.SESSION_ID.eq(sessionId))
)
.where(condition)
)
EDIT2
After going through the code on https://github.com/jOOQ/jOOQ/blob/master/jOOQ/src/main/java/org/jooq/impl/DSL.java I guess the right way to do this would be:
DSL.function("unnest", SQLDataTypes.BIGINT.getArrayType(), SESSION_MESSAGES.MESSAGE_IDS)
EDIT3
Since as always lukas is here for my jOOQ woes, I am going to capitalize on this :)
Trying to generalize this function, in a signature of sort
public <T> Field<T> unnest(Field<T[]> arrayField) {
return DSL.function("unnest", <??>, arrayField);
}
I don't know how I can fetch the datatype. There seems to be a way to get DataType<T[]> from DataType<T> using DataType::getArrayDataType(), but the reverse is not possible. There is this class I found ArrayDataType, but it seems to be package-private, so I cannot use it (and even if I could, it does not expose the field elementType).
Old PostgreSQL versions had this funky idea that it is OK to produce a table from within the SELECT clause, and expand it into the "outer" table, as if it were declared in the FROM clause. That is a very obscure PostgreSQL legacy, and this example is a good chance to get rid of it, and use LATERAL instead. Your query is equivalent to this one:
SELECT *
FROM message
WHERE id IN (
SELECT "mid"
FROM session_messages
CROSS JOIN LATERAL unnest(message_ids) AS t("mid")
WHERE session_id = '?'
);
This can be translated to jOOQ much more easily as:
DSL.using(configuration)
.select()
.from(MESSAGE)
.where(MESSAGE.ID).in(
select(field(name("mid"), MESSAGE.ID.getDataType()))
.from(SESSION_MESSAGES)
.crossJoin(lateral(unnest(SESSION_MESSAGES.MESSAGE_IDS)).as("t", "mid"))
.where(SESSION_MESSAGES.SESSION_ID.eq("'?'"))
)
The Edit3 in the question is quite close to a decent solution for this problem.
We can create a custom generic unnest method for jOOQ which accepts Field and use it in jOOQ query normally.
Helper method:
public static <T> Field<T> unnest(Field<T[]> field) {
var type = (Class<T>) field.getType().getComponentType();
return DSL.function("unnest", type, field);
}
Usage:
public void query(SessionId sessionId) {
var field = unnest(SESSION_MESSAGES.MESSAGE_IDS, UUID.class);
dsl.select().from(MESSAGE).where(
MESSAGE.ID.in(
dsl.select(field).from(SESSION_MESSAGES)
.where(SESSION_MESSAGES.SESSION_ID.eq(sessionId.id))
.orderBy(field)
)
);
}
I have an issue with defining model in spyne to generate several levels "in" SOAP11.
I used example at first, but my task is to generate service for tables already existing, so I got stuck and try to understand wheter to seek in Spyne properties or Sqlalchemy.
To be precise, i'll take example from site and show what i'm trying to reach:
class Permission(TableModel):
__tablename__ = 'permission'
id = UnsignedInteger32(pk=True)
application = Unicode(values=('usermgr', 'accountmgr'))
operation = Unicode(values=('read', 'modify', 'delete'))
perm_user_id = integer
last field is the FK for user table, but its name is different from user_id
class User(TableModel):
__tablename__ = 'user'
id = UnsignedInteger32(pk=True)
user_name = Unicode(32, min_len=4, pattern='[a-z0-9.]+', unique=True)
full_name = Unicode(64, pattern='\w+( \w+)+')
email = Unicode(64, pattern=r'[a-z0-9._%+-]+#[a-z0-9.-]+\.[A-Z]{2,4}')
last_pos = Point(2, index='gist')
permissions = Array(Permission).store_as('table')
--- SQL generated tries to add "WHEN user.id = permission.user_id" but I need another field (perm_user_id) to be filtered
Help me to define class to get correct inner tags.. actually it'll be about 3 more classes deep.
Thanx in Advance, Yury
Your answer is correct. Just as an alternative for simple tables, you can omit column definitions and let sqlalchemy's reflection engine figure it out.
meta = TableModel.Attributes.sqla_metadata
meta.reflect()
class User(TableModel):
__table__ = meta.tables['user']
The User class will be reconstructed using as much information as possible from the table columns and their types.
Found it myself, sorry to disturb anyone,
from spyne.model.complex import table
Permissions= Array(permission).customize(store_as=table(right='perm_user_id'))
I found out how to create the properties of the class, like this:
private m_Name as string
public property get Name() as string
Name = m_Name
end sub
public property let Name(sval as string)
m_name = sval
end sub
The user will create a document and choose some fields (Name, Birthday, Phone....) inside this document, as I can't know exactly which fields will be chosen by the user, I thought create a class would be the best option.
After I create the class like above, how may I make a loop through this class to check which fields has been chosen by the user?
Any better option for my situation, please, let me know...
If I understood you correctly, you want to know which fields (out of a number of existing fields) user used/initialized?
I see several ways to do it:
1) If your variables do not have default values and must have a non-empty/non-zero values, then you can simply check if a variable is empty or zero. If it is, it hasn't been initialized.
If m_name = "" Then MsgBox "Variable is not initialized"
2) for each field you have, create a boolean fieldName_Initialized so for each field, you would have something like this:
private m_Name as string
private m_name_Initialized as Boolean
public property get Name() as string
Name = m_Name
end sub
public property let Name(sval as string)
m_name = sval
m_name_Initialized = True
end sub
3) you could have a list and add variable names to the list as they become initialized:
Make sure to add Microsoft Scripting Runtime to your References for Dictionary to work.
Dim initialized As Dictionary
Set initialized = New Dictionary
private m_Name as string
private m_name_Initialized as Boolean
public property get Name() as string
Name = m_Name
end sub
public property let Name(sval as string)
m_name = sval
initialized.Add "m_name", True
end sub
Then, to check if the var has been initialized:
If initialized.Exists("m_name") Then
' Var is initialized
4) similar to #3, except use an array of booleans. Tie specific var to a specific index, like m_name is index 0. This way you skip the hassle of controlling variable names (adds to maintenance cause as far as I know you can't get the name of the variable)
Personally, #1 is the most simple, but may not be possible in a certain situations. If #1 does not apply, I would personally pick #2, unless someone can figure out how to get a string representation of a variable name from the variable itself, then #3 is preferred.
I guess what you need is a kind of Nullable-behaviour. Yes you can do this ins VB6 with the datatype Variant. Then you can use the function "IsEmpty()" to check if a property was already set or not.
a little code-example:
Option Explicit
Private m_Vars()
'0 : Name
'1 : Birthday
'2 : Phone
Private Sub Class_Initialize()
ReDim m_Vars(0 To 2)
End Sub
Public Property Get Name() As String
Name = m_Vars(0)
End Property
Public Property Let Name(RHS As String)
m_Vars(0) = RHS
End Property
Public Property Get Birthday() As Date
Birthday = m_Vars(1)
End Property
Public Property Let Birthday(RHS As Date)
m_Vars(1) = RHS
End Property
Public Sub DoSomething()
Dim i As Integer
For i = 0 To UBound(m_Vars)
Dim v: v = m_Vars(i)
If IsEmpty(v) Then
MsgBox "is empty"
Else
MsgBox v
End If
Next
End Sub
If I understand correctly, the user will add tags or something to something like a document (e.g. [Name]) and you want to know how to map your class members to these tags. To do this, you dont really want to loop thru the class members, but the document tags to find out what is needed. When you find a "tag", submit it to your class to fill in the blank.
Part 1 is a parser to find the tags...my VB6 is very rusty, so pseudocode for this:
Const TagStart = "[" ' "$[" is better as it is not likely to appear
Const TagStop = "]" ' "]$" " " "
' make this a loop looking for tags
i = Instr(docScript, TagStart)
j = Instr(docScript, TagStop)
thisTag = Mid(docScript, TagStart, TagEnd )
' not correct, but the idea is to get the text WITH the Start and Stop markers
' like [Name] or [Address]
' get the translation...see below
docText = MyClass.Vocab(thisTag)
' put it back
Mid(docScript, TagStart, TagEnd) = docText
It is actually better to look for each possible legal tag (ie Instr(docScript, "[Name]")) which are stored in an array but you may have to do that in 2 loops to allow that a given tag could be requested more than once.
Part 2 supply the replacement text from MyClass:
Friend Function Vocab(tag as string) As String
Dim Ret as string
Select Case tag
Case "$[NAME]$"
ret = "Name: " & m_Name
' if the caption is part of the "script" then just:
'ret = m_Name
Case "$[ADDRESS]$"
ret = "Address: " & m_Addr
' if not found, return the tag so you can add new Vocab items
' or user can fix typos like '[NMAR]'
Case Else
ret = tag
...
End Select
Return Ret
End Function
The parsing routines in Part 1 could also be a method in your class to process the document "script" which calls a private Vocab.
Edit
a fraction of a 'script' might look like this:
Customer's Name:| $[CUST_FNAME]$ $[CUST_LNAME]$ (ignore the pipe (|) it was a table cell marker)
The parser looks thru the string to find "$[", when it does, it isolates the related tag $[CUST_FNAME]$. If you have a large number, the first part (CUST) can be used as a router to send it to the correct class. Next, call the method to get the translation:
newText = Cust.Vocab(thisTag)
Cust Class just looks at the tag and returns "Bob" or whatever and the parsing loop replaces the tag with the data:
Customer's Name:| Bob $[CUST_LNAME]$
Then just continue until all the tags have been replaced.
With "just" 22 vocab items, you could create a dedicated class for it:
Vocab.Translate(tag ...) as string
Case "$[CUST_FNAME]$"
return Cust.FirstName
...or
Are you trying to work out a way to do this via a DOC object from office? The above is more of from the ground up document composition type thing. For office I'd think you just need some sort of collection of replacement text.
HTH
If the user has a form that they do something to create their document, why not use simple checkbox controls, one for each possible field? If you want to use a loop to check for selected fields make the checkboxes a control array and loop though the array. You can assign the field name to the Tag property, then if the checkbox is checked add the field to an array.