public inbox for [email protected]  
help / color / mirror / Atom feed
From: Alban Hertroys <[email protected]>
To: Dan Kortschak <[email protected]>
Cc: Dominique Devienne <[email protected]>
Cc: Adrian Klaver <[email protected]>
Cc: Vincent Veyron <[email protected]>
Cc: PostgreSQL General <[email protected]>
Subject: Re: re-novice coming back to pgsql: porting an SQLite update statement to postgres
Date: Sat, 14 Sep 2024 12:05:50 +0200
Message-ID: <[email protected]> (raw)
In-Reply-To: <[email protected]>
References: <[email protected]>
	<[email protected]>
	<[email protected]>
	<CAFCRh-8d-gsERdu-6W2fb0d6HLi8_bPkS7zVqm0J4ZakpvJQYw@mail.gmail.com>
	<[email protected]>
	<[email protected]>
	<[email protected]>


> On 14 Sep 2024, at 10:33, Dan Kortschak <[email protected]> wrote:

(…)

> I'm still having difficulties with the second part which is to update
> the contents of the amend array in the JSON.
> 
> So far I'm able to append the relevant details to the append array, but
> I'm unable to correctly select the corrects elements from the $6
> argument, which is in the form
> [{"start":<RFC3339>,"end":<RFC3339>,"data":<object>}, ...]. The first
> update statement gives me broadly what I want, but includes elements of
> the array that it shouldn't.

(…)

> If I filter on the start and end time, I end up with no element coming
> through at all and the "replace" field ends up null.
> 
> update
> events
> set
> datastr = jsonb_set(
> datastr,
> '{amend}',
> datastr->'amend' || jsonb_build_object(
> 'time', $2::TEXT,
> 'msg', $3::TEXT,
> 'replace', (
> select *
> from
> jsonb($6::TEXT) as replacement
> where
> (replacement->>'start')::TIMESTAMP WITH TIME ZONE < endtime and
> (replacement->>'end')::TIMESTAMP WITH TIME ZONE > starttime
> )
> )
> )
> where
> starttime < $5 and
> endtime > $4 and
> bucketrow = (
> select rowid from buckets where id = $1
> );

That’s because the replacement data is an array of objects, not a single object.

You need to iterate through the array elements to build your replacement data, something like what I do here with a select (because that’s way easier to play around with):

with dollar6 as (
select jsonb($$[
                                                {
                                                        "data": { "foo": 1, "bar": 2
                                                        },
                                                        "end": "2023-06-12T19:54:51Z",
                                                        "start": "2023-06-12T19:54:39Z"
                                                }
                                        ]$$::text) replacement
)
select *                                
from dollar6
cross join lateral jsonb_array_elements(replacement) r
where (r->>'start')::timestamptz <= current_timestamp;


There are probably other ways to attack this problem, this is the one I came up with.


Alban Hertroys
--
If you can't see the forest for the trees,
cut the trees and you'll find there is no forest.







view thread (9+ messages)  latest in thread

reply

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Reply to all the recipients using the --to and --cc options:
  reply via email

  To: [email protected]
  Cc: [email protected], [email protected], [email protected], [email protected], [email protected]
  Subject: Re: re-novice coming back to pgsql: porting an SQLite update statement to postgres
  In-Reply-To: <[email protected]>

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox