Setting up a PostgreSQL database

Useful#

Video:

Questions can be asked in the comments telegram: TG: fitgame

Database tables#

Structure users_social:

Structure users:

Keys and indexes#

Keys and indexes in users_social:

Keys and indexes in users:

Create a profile#

Stored procedure for creating a player profile

CREATE OR REPLACE FUNCTION create_user(in_social json, in_user json)
RETURNS integer AS $$
DECLARE _user_id integer;
        in_inventory JSON;
BEGIN

  INSERT INTO users_social (social_type, social_id) VALUES(in_social->>'type',in_social->>'social_id') RETURNING id INTO _user_id;
  INSERT INTO users(id, json_data, points) VALUES(_user_id, (in_user->>'json_data')::json, ((in_user->>'json_data')::json->>'points')::int);

RETURN _user_id;

END;
$$ LANGUAGE plpgsql;

Request

select create_user('{"type": "vk", "social_id": 1}', '{"json_data": {"name": "FITGAME", "gold": 100, "energy": 50, "points": 100}}');

Getting a profile#

Stored procedure to get id based on site type and site id

CREATE OR REPLACE FUNCTION get_social_info(in_social JSONB)
RETURNS integer AS $$
DECLARE _user_id integer = 0;
BEGIN

  SELECT id INTO _user_id FROM users_social WHERE social_type = (in_social->>'type') AND social_id = (in_social->>'social_id');

  IF _user_id IS NULL THEN
    _user_id = 0;
  END IF;

  RETURN _user_id;

END;
$$ LANGUAGE plpgsql STABLE;

Request

select get_social_info('{"type":"vk", "social_id": "1"}');

Stored procedure to retrieve profile data based on ID

CREATE OR REPLACE FUNCTION get_user_info(in_user_id integer)
RETURNS JSONB AS $$
DECLARE out_json JSONB = '{}';
BEGIN

  SELECT row_to_json(row) INTO out_json FROM (SELECT * FROM users WHERE id = in_user_id) row;

  IF out_json IS NULL THEN
    out_json = '{}';
  END IF;

  RETURN out_json;

END;
$$ LANGUAGE plpgsql STABLE;

Request

select get_user_info(1);

Stored procedure to get all profile data based on site type and site ID

CREATE OR REPLACE FUNCTION get_user_info_2 (in_social JSONB)
RETURNS JSONB AS $$
DECLARE out_json JSONB = '{}';
BEGIN

  SELECT row_to_json(row) INTO out_json FROM (SELECT * FROM users JOIN users_social ON users_social.id = users.id WHERE social_type = (in_social->>'type') AND social_id = (in_social->>'social_id')) row;

  IF out_json IS NULL THEN
    out_json = '{}';
  END IF;

  RETURN out_json;

END;
$$ LANGUAGE plpgsql STABLE;

Request

select get_user_info_2('{"type":"vk", "social_id": "1"}');

Profile update#

Stored procedure to update player profile

CREATE OR REPLACE FUNCTION update_user(in_user_id integer, in_user JSONB)
RETURNS boolean AS $$
BEGIN

  UPDATE users SET 
    json_data =  (in_user->>'json_data')::json, points =  ((in_user->>'json_data')::json->>'points')::int
    WHERE id = in_user_id;
 

  RETURN TRUE;
END;
$$ LANGUAGE plpgsql;

Request

select update_user(1, '{"json_data": {"name": "FITGAME", "gold": 100, "energy": 50, "points": 300}}');

Top of the best#

Stored procedure to update player profile

CREATE OR REPLACE FUNCTION get_top(in_type text, in_val integer)
RETURNS JSONB AS $$
DECLARE out_json JSONB = '{}';
  json_list JSONB;
  place_num JSONB;
BEGIN

  IF in_type = 'points' THEN

    SELECT json_agg(row_to_json(t)) INTO json_list 
    FROM (
      SELECT json_data FROM users ORDER BY points DESC LIMIT 100
    ) t;

    SELECT count(1) INTO place_num FROM users WHERE points >= in_val;

  END IF;


  IF json_list IS NOT NULL THEN
    out_json = jsonb_set(out_json, '{list}', json_list, true);
  ELSE
    out_json = jsonb_set(out_json, '{list}', '[]', true);
  END IF;


  IF place_num IS NOT NULL THEN 
    out_json = jsonb_set(out_json, '{pos}', place_num, true);
  ELSE
    out_json = jsonb_set(out_json, '{pos}', -1, true);
  END IF;

  RETURN out_json;

END;
$$ LANGUAGE plpgsql STABLE;

Request

select get_top('points', 5);