How to Compare two fields in laravel and postgres - postgresql

I'm trying to query postgres db and get a SQL error every time.
The query is correct, but why does it now work?
Query
Apireq::where('calls','<','maxcalls')->get();
Error
SQLSTATE[22P02]: invalid input syntax for integer
Field types are both set to bigint.
It's bizzare.

You need to use whereRaw instead of just where. It's weird, but it gets around the issue which I think is a Laravel Bug.
whereRaw('calls < maxcalls')

#Andrew's answer is totally correct, except that it is not a bug but expected behavior.
Here's an example why:
where('foo', '=', 'bar')
Now there are two possibilities how Laravel could interpret (or misinterpret?) this
1. Column named bar
"Sure you want to compare the column foo with bar. Here's your SQL:"
WHERE foo = bar
2. The value "bar"
"Well obviously you want all the records where foo equals "bar". Here you go:"
WHERE foo = "bar"
So Laravel has to make a decision. And because a computer (without artificial intelligence at least) can't possibly know if you want to compare with a value or another column, the developers decided it should always compare with the value (probably because it is the functionality that's needed more)
And as you already know, whereRaw is the solution:
whereRaw('calls < maxcalls')

Related

FsSql Not working when Parameterizing Columns

Using F# , FsSql and PostGres
So I'm using this function
let getSqlParameter value =
let uniqueKey = Guid.NewGuid().ToString("N")
let key = (sprintf "#%s" uniqueKey)
(key,Sql.Parameter.make(key,value))
to get me a parameter of anything I pass in dynamically
Which I then append to a query and I get something like this
select * from (select * from mytable) as innerQuery where #a29c575b69bb4629a9971dac2808b445 LIKE '%#9e3485fdf99249e5ad6adb6405f5f5ca%'
Then I take a collection of these and pass them off
Sql.asyncExecReader connectionManager query parameters
The problem that I'm having is that when I don't run this through my parameterization engine, it works fine. When I do, it doesn't work. It just returns empty sets.
The only thing I can think of is that the column names can't be parameterized. This is a problem because they're coming from the client. Is there a way to do this?
Okay so the answer here is that you can't parameterize column names as far as I can tell.
What I ended up doing was creating a whitelist of acceptable column names and then compare what was coming in to my whitelist. If it doesn't exist then I drop it.
By far a sub-optimal solution. I really wish there was a way to do this.

Npgsql and NOT IN or !=ANY Queries

It seems that there is not standard support for the IN clause in Npgsql. I see posts that recommend using = ANY instead of IN. This works great as a replacement for a standard IN clause. However, Postgres (pgsql) does not seem to have anything that allows you to do a NOT ANY or !=ANY query. It does, however, support NOT IN, but it seems that Npgsql does not. Can someone help me understand how I might write an Npgsql compatible query like this one:
select * my_table where id NOT IN(1,2,3,4)
First, this has nothing to do with Npgsql - it's a PostgreSQL question.
Second, PostgreSQL does have full standard support for IN clauses. It's important to understand the difference between IN and ANY: IN operates on rows, whereas ANY operates on arrays - the two definitely aren't the same, even though you can convert one into the other (e.g. see unnest). Read the docs carefully.
Finally, to answer your question... Saying WHERE x != ANY(some_array) means "where there's some element of some_array that isn't equal to x". This indeed isn't the same as what you want, which is "where none of some_array's elements are equal to x". You can achieve the latter with WHERE x != ALL(some_array): this checks x against each and every element, returning true only if all of them are unequal.
You can also use ANY with simple logical negation: WHERE NOT (x = ANY(SOME_ARRAY)).

Pick another column value depending on column value (postgresql)

In my frontend application I have a function that is called pick(VALUE,'col1','col2','col3'). If the VALUE is 2 the value in col2 should be picked.
This is very handsome for replacing long code using "case when", "switch case" or "if else" calculations.
I have tried to find a similar function in Postgres, but no luck so far. Seen some function array() and values() mentioned, but cannot find the correct syntax.
The goal is to set an return on of three column values depending on first column value.
Pseudo code (not working):
Select status values(column1,column2,column3)from code
I know I can do this by using "case-when-then-else-end", but I am looking for a shorter way to achieve the same thing.
Jsfiddle showing the principe. But I only want to pick ONE value depending on type:
http://sqlfiddle.com/#!15/e0b41/10
You can create an array of values from pr_* columns, then pick one of them in this way:
(array[prl_1,prl_2,prl_3])[code_type]
Here is a simple demo: http://sqlfiddle.com/#!15/e0b41/23
select *,
(array[prl_1,prl_2,prl_3])[code_type]
from code
left join prl on prl_id =1

Between... And... To work without values

I've tried to do this in a million different ways. At first I couldn't get it to work at all, but now I've managed to get it to work if I put in values.
What I need to happen is for my query to filter my records based on what I put into my form.
I've used this code in the 'Criteria' section of my MovieYear column, and when I put in numbers into my MovieYear1 and MovieYear2 text boxes in my form, it filters correctly.
Between [Forms]![SearchForm]![MovieYear1] And [Forms]![SearchForm]![MovieYear2]
But if I don't put in any values, it doesn't come up with any records at all. Any help?
I've tried pretty much everything (well, at least I think I have). I've tried using wildcards "*" but then I found out you can't actually use them with Between functions...
I've also trying doing Me.Filter in VBA, but it didn't seem to work. Maybe I just missed something?
This is my form.
Thanks in advance! :)
You can add a check for a Null in the form to the query, for example
SELECT *
FROM table
WHERE Between [Forms]![SearchForm]![MovieYear1]
And [Forms]![SearchForm]![MovieYear2]
OR [Forms]![SearchForm]![MovieYear1] Is Null
This will return all records if the first year is null. The second year will be ignored.
You could use a conditional query builder where after checking the value of the boxes you could build the query as per the following cases :
if only MovieYear1 is given then data from all years after MovieYear1 that is date>MovieYear1.
if only MovieYear2 is given then data from all years after MovieYear2 that is date<MovieYear2.
if both are given then use the between clause to get the data.
This can be implemented using CASE WHEN along the lines of following
CASE WHEN MovieYear2 IS NULL then date>MovieYear1
else when MovieYear1 IS NULL then date<MovieYear2
else date between MovieYear1 and MovieYear2

How to alter Postgres table data based on its contents?

This is probably a super simple question, but I'm struggling to come up with the right keywords to find it on Google.
I have a Postgres table that has among its contents a column of type text named content_type. That stores what type of entry is stored in that row.
There are only about 5 different types, and I decided I want to change one of them to display as something else in my application (I had been directly displaying these).
It struck me that it's funny that my view is being dictated by my database model, and I decided I would convert the types being stored in my database as strings into integers, and enumerate the possible types in my application with constants that convert them into their display names. That way, if I ever got the urge to change any category names again, I could just change it with one alteration of a constant. I also have the hunch that storing integers might be somewhat more efficient than storing text in the database.
First, a quick threshold question of, is this a good idea? Any feedback or anything I missed?
Second, and my main question, what's the Postgres command I could enter to make an alteration like this? I'm thinking I could start by renaming the old content_type column to old_content_type and then creating a new integer column content_type. However, what command would look at a row's old_content_type and fill in the new content_type column based off of that?
If you're finding that you need to change the display values, then yes, it's probably a good idea not to store them in a database. Integers are also more efficient to store and search, but I really wouldn't worry about it unless you've got millions of rows.
You just need to run an update to populate your new column:
update table_name set content_type = (case when old_content_type = 'a' then 1
when old_content_type = 'b' then 2 else 3 end);
If you're on Postgres 8.4 then using an enum type instead of a plain integer might be a good idea.
Ideally you'd have these fields referring to a table containing the definitions of type. This should be via a foreign key constraint. This way you know that your database is clean and has no invalid values (i.e. referential integrity).
There are many ways to handle this:
Having a table for each field that can contain a number of values (i.e. like an enum) is the most obvious - but it breaks down when you have a table that requires many attributes.
You can use the Entity-attribute-value model, but beware that this is too easy to abuse and cause problems when things grow.
You can use, or refer to my implementation solution PET (Parameter Enumeration Tables). This is a half way house between between 1 & 2.