According to TFM (Postgres docs), you use the normal concatenation operator to join two HSTOREs:
SELECT 'a=>b, c=>d'::hstore || 'c=>x, d=>q'::hstore
Result:
"a"=>"b", "c"=>"x", "d"=>"q"
However, I'm getting an error when running that exact same command:
[42883] ERROR: operator does not exist: hstore || hstore Hint: No operator matches the given name and argument type(s). You might need to add explicit type casts.
The only way I can get the desired result is to do something so hackish it makes me want to cry: converting any HSTOREs I have into text first, then concatenating the text and converting back to an HSTORE. This, of course, isn't good as the docs also state that if there are duplicate keys, there's no guarantee as to which one will survive the concatenation.
Before I file a bug with the Postgres folks, can anybody else duplicate this? Version info:
select version();
PostgreSQL 9.4.5 on x86_64-unknown-linux-gnu, compiled by gcc (Debian 4.7.2-5) 4.7.2, 64-bit
select extname,extversion from pg_catalog.pg_extension;
hstore 1.3
Figured out the issue. The HSTORE extension was installed into a separate schema; I was able to call that schema by identifying it (sys.hstore), but it was still not liking the operator ||. The fix was actually pretty simple: I added sys to the search_path.
Related
I am having issues with combining couple of different things together. I have tried a lot of things suggested on SO but nothing worked, hence posting my question.
So the requirements are
I need to build the dynamic query (to search jsonb column type) in Java
I need to use prepared statements of Java (to avoid sql injection)
I need to replace parameter which is inside single quotes
This query in CLI works perfectly
select * from items where cnt ## '$.**.text like_regex "#finance" flag "i"';
The bit that I want to parameterise is "#finance". So when I build this query
select * from items where cnt ## '$.**.text like_regex ? flag "i"';
When executing I get following error
"The column index is out of range: 1, number of columns: 0."
It's because ? is within single quote so jdbc driver is not able to identify as replaceable parameter perhaps.
The closest question/discussion I could find is in this post: JDBC Prepared statement parameter inside json.
I have tried it however this does not work for me for some reason. They query now I run is
select * from items where cnt ## ?::jsonb
but with this I get following error
org.postgresql.util.PSQLException: ERROR: operator does not exist: jsonb ## jsonb
Hint: No operator matches the given name and argument types. You might need to add explicit type casts.
Position: 106
I have tried various other ways like escaping single quotes etc but nothing really worked. I have very limited knowledge of PostgreSQL, so any help would be appreciated.
Postgres version: 13.1
Java version: 15
select * from items where cnt ## ?::jsonb
The thing on the right of the ## needs to be a jsonpath, not jsonb. So casting it to jsonb is clearly wrong. Try casting it to jsonpath instead.
I'm trying to change a column of type daterange to tsrange (I realized I need time as well as date) using a vanilla Rails migration
def self.up
change_column :events, :when, :tsrange
end
After running rake db:migrate the error is
PG::DatatypeMismatch: ERROR: column "when" cannot be cast automatically to type tsrange
HINT: Specify a USING expression to perform the conversion.
: ALTER TABLE "events" ALTER COLUMN "when" TYPE tsrange
I tried following the hint and used the following
def self.up
change_column :events, :when, :tsrange, 'tsrange USING CAST(when AS tsrange)'
end
but then got
no implicit conversion of Symbol into Integer
From what I can tell, USING CAST is mainly meant for use with ints. Assuming I don't want to drop and then recreate the column, what do you have to specify to alter the type from daterange to tsrange?
I'm using
Rails 4.0.1
ruby-2.0.0-p247
psql (9.2.4)
Some background, daterange and tsrange were introduced to Rails 4 in the following PR: https://github.com/rails/rails/pull/7345. Thanks.
The USING clause is used to specify how to convert the old values to the new ones:
The optional USING clause specifies how to compute the new column value from the old; if omitted, the default conversion is the same as an assignment cast from old data type to new. A USING clause must be provided if there is no implicit or assignment cast from old to new type.
So USING shows up any time there is no default cast from the old type to the new type. Also note that USING is specified as USING expression so any expression (whose value is of the correct type) can be used with a USING, the most common is USING CAST(...) but the expression can be pretty much anything.
Hopefully that should clear up some confusion about USING.
So what's up with the ActiveRecord error? Well, change_column is expecting to see an options Hash in the fourth argument but you're sending in a string. If you look at the change_column source, you'll see things like options[:limit] but String#[] expects integer arguments so your string argument is triggering odd looking complains about Symbols.
AFAIK there is no way to get AR to add a USING clause to the ALTER TABLE ... ALTER COLUMN that change_column generates. This leaves connection.execute(some_sql) if you need a USING clause. Of course this is further complicated by the (apparent) lack of a built-in cast from daterange to tsrange but building the necessary expression isn't terribly difficult if you pull the daterange apart with the upper and lower functions:
connection.execute(%q{
alter table events
alter column "when"
type tsrange using tsrange(lower("when"), upper("when"))
})
You can see the table change in action over here: http://sqlfiddle.com/#!15/fb047/2
That assumes that you're using the default half-open intervals ([...)) for your ranges; if you have ranges that aren't closed on the left and open on the right then you'll have to build a more complicated USING expression using the other range functions to see if the left and right ends of the ranges are open or closed.
BTW, when is a PostgreSQL keyword so it isn't the best choice for an identifier, you'll have to say "when" every time you refer to that column in SQL snippets and that might get tiring. I'd recommend using a different name for that column so that you don't have to worry about quoting.
Documentation for postgres has hstore - hstore which delete matching pairs from left operand. Installed postgres extensions.
When I try
select public.hstore('"x"=>"30", "y"=>"c"') -
public.hstore('"x"=>"30","y"=>"fred"')
is error-ing with following
ERROR: operator does not exist: public.hstore - public.hstore
LINE 3: select public.hstore('"x"=>"30", "y"=>"c"') - public.hstore...
^
HINT: No operator matches the given name and argument type(s). You might need to add explicit type casts.
You've installed the hstore extension into the public schema, which is not on your search_path. To find the types you're schema-qualifying them but you're not qualifying the - operator that works on those types.
This means that hstore's operator definitions will not be found. You must:
Schema-qualify the operator using OPERATOR(public.-);
Put public on the search_path; or
Uninstall hstore and then install it into its own dedicated schema that is on the search_path.
An example of schema-qualified operator syntax is:
SELECT 1 OPERATOR(pg_catalog.-) 2;
I ran into this issue as well, nothing worked for me from my code (worked via pgadmin - query). Eventually after looking at the functions within public I found this which worked for me.
public.fetchval(hstore, key)
I wonder if someone could have an idea what is going wrong with this simple query on a hstore column in PostgreSQL 9.2
The queries are runned in pgAdmin
select attributeValue->"CODE_MUN" from shapefile_feature
returns: « attributevalue » column does not exists
when doing:
select * from shapefile_feature;
all the columns are returned including attributeValue, the hstore column
what is the problem?
PostgreSQL distinguish between "identifiers" and 'literal'. Identifiers are schema, table, column's, .. names, literals are others. A attribute in hstore are not SQL identifiers. So you have to pass their names as literals. Operator "->" is only shortcut for function "fetchval(hstore, text)" with possibility be indexed.
select attributeValue->'CODE_MUN' from shapefile_feature
is internally transformed to (don't do this transformation by self!)
select fetchval(attributeValue, 'CODE_MUN') from shapefile_feature
on buggy example in transformed form, you can better understand to error message:
select fetchval(attributeValue, "CODE_MUN") from shapefile_feature
PostgreSQL tries to find column "CODE_MUN" in shapefile_feature, bacause used double quotes means identifiers (in case sensitive notation).
I'm trying to a simple concatenation in PostgreSQL and it keeps up throwing up an error message. I don't understand what I am doing wrong here.
select concat('abcde', 'fgh');
No function matches the given name and argument types. You might need to add explicit type casts.
select concat(cast('abcde' as text), cast('fgh' as text));
No function matches the given name and argument types. You might need to add explicit type casts.
I am using Postgres version 8.4.11. Please let me know what is going on.
The concat operator is ||, so select 'abcde' || 'fgh' should work. Also, as #jonathan.cone suggested, check out the docs.
concat was added in 9.1, it doesn't exist in 8.4. As others have noted, use the || operator.
Compare the 8.4 docs to the 9.1 docs and you'll notice that the concat function isn't present in the 8.4 docs.
See that bar at the top of the docs that says "This page in other versions" ? It's really handy when you're working with an old version, or if you find a link to an old version of a page via Google and you're on a newer version. Always make sure you're looking at the docs for the right version.
It'd be nice if the tables for functions etc included a "First appeared in version " - but unfortunately they don't.
If you're ever confused about the availablilty of a function, you can use \df in psql to list and search functions.
For example, to list all functions named concat use \df concat
For all functions in the pg_catalog schema (built-in functions) use \df pg_catalog. - note the trailing period, telling psql you mean "any function within the schema pg_catalog" not "the function named pg_catalog".
For all functions with names starting with concat use \df concat*
It's a very powerful tool. The same language works when searching for schema (\dn), tables (\dt), etc.
select 'abcde' || 'fgh';
select cast('abcde' as text) || cast('fgh' as text);