How to use LIKE for an Inet column? - postgresql

I have a column in my database called mgmt which is an inet type
I would like to do this:
select * from source
where mgmt LIKE inet('10.208.6%')
but this gives the error "ERROR: invalid input syntax for type inet:"
Any idea how I can use the LIKE clause for an inet type?

First idea:
Casting into text and try then:
WHERE mgmt::text LIKE '10.208.6%'
Second idea:
Try this
WHERE mgmt BETWEEN inet('10.208.60.0') AND inet('10.208.69.255')
(or, even more precise, because your wildcard covers both, 6 and 60s)
WHERE (mgmt BETWEEN inet('10.208.60.0') AND inet('10.208.69.255'))
OR (mgmt BETWEEN inet('10.208.6.0') AND inet('10.208.6.255'))
Third idea:
If you just want to check the 6 range, use the << operator to check the IP range:
WHERE mgmt << inet('10.208.6/24')

I would use the << operator to do inet operations:
postgres=# SELECT '192.168.1.1'::inet << '192.168.1.0/24'::inet;
?column?
----------
t
(1 row)
postgres=# SELECT '192.168.10.1'::inet << '192.168.1.0/24'::inet;
?column?
----------
f
(1 row)
But if you really must use ILIKE for some reason, you can cast to text:
postgres=# SELECT text('192.168.10.1'::inet) ilike '192.168.1%';
?column?
----------
t
(1 row)
More information can be found in the documentation

Related

Convert Informatica Functions into Postgres

I have a workflows in the Informatica which has Expression RTRIM(LTRIM(EMP_NUM,'0')). This function I want to convert it in to the Postgres query. How can we do that ?
SELECT EMP_NUM, EMP_NAME, EMP_EMAIL FROM TEST.EMPLOYEE
Any pointers ?
Sample Data of EMP_NUM
01000
11
0000176
00090900088
08009345353
To replicate what you show:
select rtrim(ltrim('001000 ', ' 0'));
rtrim
-------
1000
(1 row)
String operators and functions for Postgres:
https://www.postgresql.org/docs/current/functions-string.html
An alternate solution(converts to numeric):
select to_number('01000 ', '99999');
to_number
-----------
1000
(1 row)
https://www.postgresql.org/docs/current/functions-formatting.html
to_number(text, text) numeric convert string to numeric to_number('12,454.8-', '99G999D9S')

Postgres FTS Priority Field

I am using Postgres FTS to search a field in a table. The only issue is for some reason the below issue is happening.
store=# select name from service where to_tsvector(name) ## to_tsquery('find:*') = true;
name
--------------
Finding Nora
(1 row)
store=# select name from service where to_tsvector(name) ## to_tsquery('findi:*') = true;
name
------
(0 rows)
store=# select name from service where to_tsvector(name) ## to_tsquery('findi:*') = true;
How come when searching using the query findi:*,the result doesnt show?
In my PG 12.2 with default text search configuration I have:
# select to_tsvector('Finding Nora');
to_tsvector
-------------------
'find':1 'nora':2
(1 row)
# select to_tsquery('findi:*');
to_tsquery
------------
'findi':*
(1 row)
I understand that because there is no lexeme findi in the default dictionary, the query does not find any match.

PostgreSQL full text search yielding weird results

I have a schema like this (simplified):
CREATE TABLE users (
id SERIAL PRIMARY KEY,
name NOT NULL
);
CREATE INDEX users_idx
ON users
USING GIN (to_tsvector('finnish', name));
But I'm getting completely invalid results with my queries:
# select name from users where to_tsvector('finnish', name) ## to_tsquery('lemmin');
name
------
(0 rows)
# select name from users where to_tsvector('finnish', name) ## to_tsquery('lemmink');
name
--------------------
Riitta ja Lemminki
Riitta ja Lemminki
(2 rows)
# select name from users where name ilike 'lemmink%';
name
----------------------
Lemminkäinen Matilda
Lemminkäinen Matias
Lemminkäinen Kyösti
Lemminkäinen Tuomas
(4 rows)
Another example:
# select name from users where to_tsvector('finnish', name) ## to_tsquery('partu');
name
----------
Partuuna
(1 row)
# select name from users where to_tsvector('finnish', name) ## to_tsquery('partur');
name
------------------------
Parturi-Kampaamo Raija
Parturi-Kampaamo Siema
(2 rows)
I was expecting to get the bottom two results on both queries...
Using the following version:
psql (9.4.6, server 9.5.2)
WARNING: psql major version 9.4, server major version 9.5.
Some psql features might not work.
I don't speak Finnish, but it seems expected result. FTS looks for lexemes, not for parts of words, Eg, do is not a lexemme for dog, but dog is for dogs:
t=# select to_tsvector('english', 'Dogs eats bone') ## to_tsquery('do');
NOTICE: text-search query contains only stop words or doesn't contain lexemes, ignored
?column?
----------
f
(1 row)
t=# select to_tsvector('english', 'Dogs eats bone') ## to_tsquery('dog');
?column?
----------
t
(1 row)
So I believe in Parturi last i is optional ending - right?..
Update:
from https://en.wiktionary.org/wiki/parturi :
partur[i], partur[eita] => lexeme will be partur

postgresql + textsearch + german umlauts + UTF8

I'm really at my wits end, with this Problem, and I really hope someone could help me. I am using a Postgresql 9.3. My Database contains mostly german texts but not only, so it's encoded in utf-8. I want to establish a fulltextsearch wich supports german language, nothing special so far.
But the search is behaving really strange,, and I can't find out what I am doing wrong.
So, given the following table given as example
select * from test;
a
-------------
ein Baum
viele Bäume
Überleben
Tisch
Tische
Café
\d test
Tabelle »public.test«
Spalte | Typ | Attribute
--------+------+-----------
a | text |
sintext=# \d
Liste der Relationen
Schema | Name | Typ | Eigentümer
--------+---------------------+---------+------------
(...)
public | test | Tabelle | paf
Now, lets have a look at some textsearch examples:
select * from test where to_tsvector('german', a) ## plainto_tsquery('Baum');
a
-------------
ein Baum
viele Bäume
select * from test where to_tsvector('german', a) ## plainto_tsquery('Bäume');
--> No Hits
select * from test where to_tsvector('german', a) ## plainto_tsquery('Überleben');
--> No Hits
select * from test where to_tsvector('german', a) ## plainto_tsquery('Tisch');
a
--------
Tisch
Tische
Whereas Tische is Plural of Tisch (table) and Bäume is plural of Baum (tree). So, Obviously Umlauts does not work while textsearch perfoms well.
But what really confuses me is, that a) non-german special characters are matching
select * from test where to_tsvector('german', a) ## plainto_tsquery('Café');
a
------
Café
and b) if I don't use the german dictionary, there is no Problem with umlauts (but of course no real textsearch as well)
select * from test where to_tsvector(a) ## plainto_tsquery('Bäume');
a
-------------
viele Bäume
So, if I use the german dictionary for Text-Search, just the german special characters do not work? Seriously? What the hell is wrong here? I Really can't figure it out, please help!
You're explicitly using the German dictionary for the to_tsvector calls, but not for the to_tsquery or plainto_tsquery calls. Presumably your default dictionary isn't set to german; check with SHOW default_text_search_config.
Compare:
regress=> select plainto_tsquery('simple', 'Bäume'),
plainto_tsquery('english','Bäume'),
plainto_tsquery('german', 'Bäume');
plainto_tsquery | plainto_tsquery | plainto_tsquery
-----------------+-----------------+-----------------
'bäume' | 'bäume' | 'baum'
(1 row)
The language setting affects word simplification and root extraction, so a vector from one language won't necessarily match a query from another:
regress=> SELECT to_tsvector('german', 'viele Bäume'), plainto_tsquery('Bäume'),
to_tsvector('german', 'viele Bäume') ## plainto_tsquery('Bäume');
to_tsvector | plainto_tsquery | ?column?
-------------------+-----------------+----------
'baum':2 'viel':1 | 'bäume' | f
(1 row)
If you use a consistent language setting, all is well:
regress=> SELECT to_tsvector('german', 'viele Bäume'), plainto_tsquery('german', 'Bäume'),
to_tsvector('german', 'viele Bäume') ## plainto_tsquery('german', 'Bäume');
to_tsvector | plainto_tsquery | ?column?
-------------------+-----------------+----------
'baum':2 'viel':1 | 'baum' | t
(1 row)

how does one extract octets from an inet value in postgres sql?

I would like to convert an inet formatted IPv4 address into the integer components.
For example, turn '101.255.30.40' into oct1=101, oct2=255, oct3=30, and oct4=40.
There are regex expressions that should do this if I cast the inet as a varchar, but that seems inelegant. Is there a 1-line function for returning the nth octet of an inet?
select inet_to_octet('101.255.30.40', 4) as temp; -- returns temp=40?
I finally got an excellent answer from a co-worker...
For some flavors of sql, use "split_part" along with host(inet) to get the text field.
select split_part(host('101.255.30.40'::inet), '.', 1);
select split_part(host('101.255.30.40'::inet), '.', 2);
select split_part(host('101.255.30.40'::inet), '.', 3);
select split_part(host('101.255.30.40'::inet), '.', 4);
results in
101
255
30
40
If you want to get trickier and handle IPv6, use a mask to speed up the operation along with case statements to get the IP version:
select
(case
when family('101.255.30.40'::inet) = 4 then split_part(host(broadcast(set_masklen('101.255.30.40'::inet, 32))), '.', 4)::varchar
when family('101.255.30.40'::inet) = 6 then split_part(host(broadcast(set_masklen('101.255.30.40'::inet, 64))), ':', 4)::varchar
else null end)::varchar as octet4;
select
(case
when family('2604:8f00:4:80b0:3925:c69c:458:3f7b'::inet) = 4 then split_part(host(broadcast(set_masklen('2604:8f00:4:80b0:3925:c69c:458:3f7b'::inet, 32))), '.', 4)::varchar
when family('2604:8f00:4:80b0:3925:c69c:458:3f7b'::inet) = 6 then split_part(host(broadcast(set_masklen('2604:8f00:4:80b0:3925:c69c:458:3f7b'::inet, 64))), ':', 4)::varchar
else null end)::varchar as octet4;
results in
40
80b0
you can then add in a hex-to-int conversion into the case statement if you want to cast the IPv6 as a number instead.
Unless you want to try to contribute the function to the inet datatype, you'll need to rely on a string based version. Maybe put something like this (but with some error checking) into an SQL function for easy access?:
CREATE OR REPLACE FUNCTION extract_octet(inet, integer) RETURNS integer AS $$
SELECT ((regexp_split_to_array(host($1), E'\\.'))[$2])::int;
$$ LANGUAGE SQL;
select extract_octet(inet '192.26.22.2', 2)
Output: 26
Here are a couple of one-liners for the separate octets of an IPv4 address:
SELECT substring(host('1.2.3.4'::inet) FROM '^([0-9]+)\.[0-9]+\.[0-9]+\.[0-9]+$');
will return 1
SELECT substring(host('1.2.3.4'::inet) FROM '^[0-9]+\.([0-9]+)\.[0-9]+\.[0-9]+$');
will return 2
SELECT substring(host('1.2.3.4'::inet) FROM '^[0-9]+\.[0-9]+\.([0-9]+)\.[0-9]+$');
will return 3
SELECT substring(host('1.2.3.4'::inet) FROM '^[0-9]+\.[0-9]+\.[0-9]+\.([0-9]+)$');
will return 4