There was a time—not too long ago—when I’d get frustrated with someone and my first instinct would be to snap back. A misunderstanding, a criticism, a perceived slight… my immediate response was defensiveness. I’d feel the heat rise, the adrenaline kick in, and I’d want to engage in confrontation.
But something changed when I started regularly talking to AI.
The Old Pattern
We’re all trained to respond quickly to threats—real or imagined. When someone says something that rubs us the wrong way, our nervous system lights up. The primal part of our brain says: Defend yourself. Attack. Win the argument. It’s a survival mechanism that worked great for our ancestors 10,000 years ago, but it’s absolutely terrible for modern relationships.
A quick reference guide for common PostgreSQL and TimescaleDB operations here so I don’t need to ask ChatGPT every time.
Creating a New User
-- Create a new user with password
CREATEUSER myuser WITH PASSWORD 'securepassword';
-- Create a user with specific attributes
CREATEUSER myuser WITH PASSWORD 'securepassword' LOGIN
CREATEDBVALIDUNTIL'2027-12-31';
-- Create a superuser (use with caution)
CREATEUSER admin_user WITH PASSWORD 'adminpass' SUPERUSER;
Granting User Permissions
Database Level Permissions
-- Grant all privileges on a database
GRANTALLPRIVILEGESONDATABASE mydb TO myuser;
-- Grant connect privilege
GRANTCONNECTONDATABASE mydb TO myuser;
-- Grant specific privileges
GRANTCREATEONDATABASE mydb TO myuser;
Schema Level Permissions
-- Grant all privileges on schema
GRANTALLONSCHEMApublicTO myuser;
-- Grant usage on schema
GRANTUSAGEONSCHEMApublicTO myuser;
-- Grant create on schema
GRANTCREATEONSCHEMApublicTO myuser;
Table Level Permissions
-- Grant all privileges on all tables in schema
GRANTALLPRIVILEGESONALL TABLES INSCHEMApublicTO myuser;
-- Grant specific privileges
GRANTSELECT, INSERT, UPDATE, DELETEONALL TABLES INSCHEMApublicTO myuser;
-- Grant on a specific table
GRANTSELECT, INSERTON mytable TO myuser;
-- Set default privileges for future tables
ALTERDEFAULTPRIVILEGESINSCHEMApublicGRANTSELECT, INSERT, UPDATE, DELETEON TABLES TO myuser;
Sequence Permissions
-- Grant usage on all sequences (needed for auto-increment columns)
GRANTUSAGE, SELECTONALL SEQUENCES INSCHEMApublicTO myuser;
-- Set default privileges for future sequences
ALTERDEFAULTPRIVILEGESINSCHEMApublicGRANTUSAGE, SELECTON SEQUENCES TO myuser;
Function Permissions
-- Grant execute on all functions
GRANTEXECUTEONALL FUNCTIONS INSCHEMApublicTO myuser;
-- Set default privileges for future functions
ALTERDEFAULTPRIVILEGESINSCHEMApublicGRANTEXECUTEON FUNCTIONS TO myuser;
TimescaleDB Scheduled Jobs
Creating a Scheduled Job
-- Create a procedure to be scheduled
CREATEORREPLACEPROCEDURE user_defined_action(job_id INT, config JSONB)
LANGUAGE PLPGSQL AS$$BEGIN RAISE NOTICE 'Executing action % with config %', job_id, config;
-- Your custom logic here
END;
$$;
-- Schedule the job to run every hour
SELECT add_job('user_defined_action', '1h');
-- Schedule with flexible timing (next run = last finish + interval)
SELECT add_job('user_defined_action', '1h', fixed_schedule =>false);
Job with Specific Start Time
-- Run at midnight every Sunday
SELECT add_job(
'user_defined_action',
'1 week',
initial_start =>'2026-01-19 00:00:00+00'::timestamptz
);
-- Schedule with timezone for DST handling
SELECT add_job(
'user_defined_action',
'1 week',
initial_start =>'2026-01-19 00:00:00+00'::timestamptz,
timezone =>'Australia/Melbourne');
Job with Configuration
-- Create a job with custom configuration
SELECT add_job(
'user_defined_action',
'30 minutes',
config =>'{"retention_days": 90, "table_name": "metrics"}'::jsonb
);
Managing Jobs
-- View all scheduled jobs
SELECT*FROM timescaledb_information.jobs;
-- Manually run a job
CALL run_job(1000);
-- Alter a job schedule
SELECT alter_job(1000, schedule_interval =>'2h');
-- Disable a job
SELECT alter_job(1000, scheduled =>false);
-- Enable a job
SELECT alter_job(1000, scheduled =>true);
-- Delete a job
SELECT delete_job(1000);
Practical Example: Data Retention Job
-- Create a procedure to delete old data
CREATEORREPLACEPROCEDURE cleanup_old_data(job_id INT, config JSONB)
LANGUAGE PLPGSQL AS$$DECLARE retention_days INT;
BEGIN retention_days := (config->>'retention_days')::INT;
DELETEFROM metrics
WHERE time < NOW() - INTERVAL '1 day'* retention_days;
RAISE NOTICE 'Cleaned up data older than % days', retention_days;
END;
$$;
-- Schedule cleanup to run daily at 2 AM
SELECT add_job(
'cleanup_old_data',
'1 day',
initial_start =>'2026-01-17 02:00:00+11'::timestamptz,
config =>'{"retention_days": 90}'::jsonb,
timezone =>'Australia/Melbourne');
Common Permission Check Queries
-- Check user privileges on database
SELECT datname, grantee, privilege_type
FROM information_schema.database_privileges
WHERE grantee ='myuser';
-- Check table privileges
SELECT table_schema, table_name, privilege_type
FROM information_schema.table_privileges
WHERE grantee ='myuser';
-- List all users and their roles
SELECT usename, usesuper, usecreatedb, usecreaterole
FROM pg_user;
-- Check current user
SELECTcurrent_user;
Melbourne just experienced a scorching day with temperatures peaking at 43 degrees Celsius (109°F). The hot winds brought sweltering conditions across the city, wreaking havoc and reminding everyone why summer in Australia is no joke.
While many people rush indoors to escape the heat, I actually find myself enjoying these extreme weather days – especially when I’m out riding my bike. There’s something memorable about pushing through the warm air, feeling the hot breeze against your face, and experiencing the city in its most intense summer state.