Skip to main content
Home
Robert Abraham's Blog

Main navigation

  • Home
  • Educational materials
  • GenPass
  • ReactImages
  • Nemesis Information System
  • About
User account menu
  • Log in

Breadcrumb

  1. Home

Trying ChatGPT on PL/pgSQL

Profile picture for user admin
By admin, 8 February, 2023
Big Data Artificial Intelligence | publicdomainpictures.net

I was curious about how ChatGPT can generate code so I tried it out on PL/pgSQL for PostgreSQL and gave it a simple task of creating a function for event scheduling. Here's what we got after a few iterations.

Me: generate a plpgsql function, which takes an event ID, a past timestamp, the current timestamp, the repeating interval and calculates when the event specified by its ID becomes current (without time zone)!

Raw solution suggested by ChatGPT:

CREATE OR REPLACE FUNCTION get_current_event(event_id integer, past_timestamp timestamp without time zone, current_timestamp timestamp without time zone, repeating_interval interval)
RETURNS timestamp without time zone AS $$
DECLARE
  result timestamp without time zone;
BEGIN
  result := past_timestamp + repeating_interval * floor((current_timestamp - past_timestamp) / repeating_interval);
  RETURN result;
END;
$$ LANGUAGE plpgsql;

This function takes in an event_id, past_timestamp, current_timestamp, and repeating_interval as input and calculates the next occurrence of the event based on the repeating interval. The calculation is performed by subtracting the past_timestamp from the current_timestamp and dividing the result by the repeating_interval, then taking the floor of the result. Finally, the repeating_interval is multiplied with this result and added to the past_timestamp to get the next occurrence of the event.

Me: how do you want to apply floor() function used for floating point numbers on an interval type?

ChatGPT: I apologize for the mistake in my previous answer. The floor function cannot be used directly on an interval data type. A common way to achieve the desired result is to cast the interval to a numeric type (such as double precision) and then apply the floor function, and finally cast the result back to an interval. Here is an updated version of the function:

CREATE OR REPLACE FUNCTION get_current_event(event_id integer, past_timestamp timestamp without time zone, current_timestamp timestamp without time zone, repeating_interval interval)
RETURNS timestamp without time zone AS $$
DECLARE
  result timestamp without time zone;
  elapsed_time double precision;
BEGIN
  elapsed_time := extract(epoch from (current_timestamp - past_timestamp)) / extract(epoch from repeating_interval);
  elapsed_time := floor(elapsed_time);
  result := past_timestamp + interval '1 second' * extract(epoch from repeating_interval) * elapsed_time;
  RETURN result;
END;
$$ LANGUAGE plpgsql;

Me: I already tried epoch on fixed intervals (such as 30 days) but after a while the timestamp of the next occurence of the event started to be late.

ChatGPT: if you're experiencing drift in your results when using the extract function, it's likely due to the fact that some intervals are not exactly representable as a fixed number of seconds. Instead, you can use the date_trunc function to round down to the nearest repeating interval. Here's an updated version of the function:

CREATE OR REPLACE FUNCTION get_current_event(event_id integer, past_timestamp timestamp without time zone, current_timestamp timestamp without time zone, repeating_interval interval)
RETURNS timestamp without time zone AS $$
DECLARE
  result timestamp without time zone;
BEGIN
  result := date_trunc(text(repeating_interval), past_timestamp + (current_timestamp - past_timestamp));
  WHILE result <= past_timestamp LOOP
    result := result + repeating_interval;
  END LOOP;
  RETURN result;
END;
$$ LANGUAGE plpgsql;

This function uses the date_trunc function to round down to the nearest repeating interval, and then repeatedly adds the interval until the result is after the past_timestamp. This approach should result in more accurate timestamps for repeating events.

Me: is there any way to eliminate the WHILE ... LOOP using mathematical modulo function only?

ChatGPT: yes, it is possible to eliminate the WHILE ... LOOP by using the modulo operator (%). Here is an updated version of the function:

CREATE OR REPLACE FUNCTION get_current_event(event_id integer, past_timestamp timestamp without time zone, current_timestamp timestamp without time zone, repeating_interval interval)
RETURNS timestamp without time zone AS $$
DECLARE
  result timestamp without time zone;
BEGIN
  result := past_timestamp + ((current_timestamp - past_timestamp) / repeating_interval) * repeating_interval;
  IF result < past_timestamp THEN
    result := result + repeating_interval;
  END IF;
  RETURN result;
END;
$$ LANGUAGE plpgsql;

This function uses the modulo operator (/) to calculate the number of full intervals that have elapsed between past_timestamp and current_timestamp, and then multiplies that value by repeating_interval to get the next occurrence of the event. If the result is still before past_timestamp, an additional repeating_interval is added to ensure that the next occurrence is in the future.

Me: are you sure you can multiply by interval and the modulo operator isn't %?

ChatGPT: I apologize for the mistake. You are correct, the modulo operator is % in PL/pgSQL, not /. Here is the corrected version of the function:

CREATE OR REPLACE FUNCTION get_current_event(event_id integer, past_timestamp timestamp without time zone, current_timestamp timestamp without time zone, repeating_interval interval)
RETURNS timestamp without time zone AS $$
DECLARE
  result timestamp without time zone;
  num_intervals double precision;
BEGIN
  num_intervals := (current_timestamp - past_timestamp) / repeating_interval;
  num_intervals := floor(num_intervals);
  result := past_timestamp + num_intervals * repeating_interval;
  IF result < current_timestamp THEN
    result := result + repeating_interval;
  END IF;
  RETURN result;
END;
$$ LANGUAGE plpgsql;

This function uses the / operator to calculate the number of full intervals that have elapsed between past_timestamp and current_timestamp. The floor function is then used to round down to the nearest whole number of intervals, which is multiplied by repeating_interval to get the next occurrence of the event. If the result is still before current_timestamp, an additional repeating_interval is added to ensure that the next occurrence is in the future.

Me: are you sure you can divide an interval by another interval?

ChatGPT: I apologize for the mistake. Dividing an interval by another interval is not supported in PostgreSQL. Instead, you can divide the interval by a numeric value to get a new interval value. Here is the corrected version of the function:

CREATE OR REPLACE FUNCTION get_current_event(event_id integer, past_timestamp timestamp without time zone, current_timestamp timestamp without time zone, repeating_interval interval)
RETURNS timestamp without time zone AS $$
DECLARE
  result timestamp without time zone;
  elapsed_time interval;
  num_intervals double precision;
BEGIN
  elapsed_time := current_timestamp - past_timestamp;
  num_intervals := elapsed_time / repeating_interval;
  num_intervals := floor(num_intervals);
  result := past_timestamp + num_intervals * repeating_interval;
  IF result < current_timestamp THEN
    result := result + repeating_interval;
  END IF;
  RETURN result;
END;
$$ LANGUAGE plpgsql;

This function calculates the ... (?)

Me: you are still dividing elapsed_time (interval) by repeating_interval (interval).

ChatGPT: I apologize for the mistake. You are correct, dividing an interval by an interval is not possible. Here is a corrected version of the function, which uses a constant to divide the interval:

CREATE OR REPLACE FUNCTION get_current_event(event_id integer, past_timestamp timestamp without time zone, current_timestamp timestamp without time zone, repeating_interval interval)
RETURNS timestamp without time zone AS $$
DECLARE
  result timestamp without time zone;
  elapsed_time interval;
  num_intervals double precision;
  interval_length double precision;
BEGIN
  elapsed_time := current_timestamp - past_timestamp;
  interval_length := extract(epoch from repeating_interval);
  num_intervals := extract(epoch from elapsed_time) / interval_length;
  num_intervals := floor(num_intervals);
  result := past_timestamp + (num_intervals * repeating_interval);
  IF result < current_timestamp THEN
    result := result + repeating_interval;
  END IF;
  RETURN result;
END;
$$ LANGUAGE plpgsql;

This function uses the extract function to convert the repeating_interval and elapsed_time intervals to their respective epoch values in seconds, and then divides elapsed_time by interval_length to calculate the number of full intervals that have elapsed. The floor function is then used to round down to the nearest whole number of intervals, which is multiplied by repeating_interval to get the next occurrence of the event. If the result is still before current_timestamp, an additional repeating_interval is added to ensure that the next occurrence is in the future.

Me: looks good!

ChatGPT: I'm glad it looks good. If you have any further questions or if there's anything else I can help with, please don't hesitate to ask.

This is how far we got yet. With only minor modifications (we don't actually need event_id parameter for instance as we care only about the timestamp) I could make this function work on a PostgreSQL database server instance so I can say ChatGPT comes handy when you have to write a smaller block of code from stratch but not too large (as there will be errors in the code but the idea behind it will probably work and suit your needs). I'm sure the service will get many improvements in the future, this was just a quick test and I'm impressed! It's pretty good!

You can give ChatGPT a try on the following website (and it really worth it): https://chat.openai.com/

(All links are valid at the time of writing.)

Tags

  • PostgreSQL
  • PL/pgSQL
  • ChatGPT
  • OpenAI
  • coding

Comments

Recent content

  • Multilingual text recognition with translation
    Wed, 10/23/2024 - 18:46
  • Encrypted mini-server on Raspberry Pi with VeraCrypt and LXD containers
    Tue, 10/15/2024 - 23:34
  • Trying ChatGPT on PL/pgSQL
    Wed, 02/08/2023 - 19:28
  • How to create encrypted Windows 7 - Ubuntu dualboot system with DiskCryptor
    Tue, 09/06/2022 - 18:19

Monthly archive

  • October 2024 (1)
  • September 2024 (1)
  • February 2023 (1)
  • July 2022 (1)
  • April 2022 (1)
  • November 2019 (4)

Footer

  • Privacy Policy
  • Cookie Policy
  • About
Powered by Drupal