CREATE FUNCTION crash_test() RETURNS boolean
LANGUAGE pljs IMMUTABLE STRICT
AS $$
  var a = new ArrayBuffer(8);
  return true;
$$;

SELECT crash_test();

-- ES6 / harmony features
CREATE TABLE rectangle (
  id    INTEGER,
  data  JSON
);

INSERT INTO rectangle (id, data) VALUES
(1, '{"width": 20.3, "height": 1.5}'),
(2, '{"width": 10.2, "height": 9.5}'),
(3, '{"width": 3.5,  "height": 5.2}'),
(4, '{"width": 8.2,  "height": 8.2}'),
(5, '{"width": 9.4,  "height": 0.2}'),
(6, '{"width": 1.2,  "height": 1.5}');

-- for..of loop over result array with break
CREATE OR REPLACE FUNCTION get_rectangles_area(min_area NUMERIC)
RETURNS json AS $$
  var rectangles = pljs.execute('SELECT id, data FROM rectangle ORDER BY id');
  var result = [];
  var area = 0.0;
  for (var rectangle of rectangles) {
    area += rectangle.data.width * rectangle.data.height;
    result.push({id: rectangle.id, data: rectangle.data});
    if (area >= min_area) {
      break;
    }
  }
  return result;
$$ LANGUAGE pljs STABLE STRICT;

SELECT get_rectangles_area(130.0);

-- same for..of loop, this time using a cursor within a generator
CREATE OR REPLACE FUNCTION get_rectangles_area(min_area NUMERIC)
RETURNS json AS $$
  var plan = pljs.prepare('SELECT id, data FROM rectangle ORDER BY id');
  var cursor = plan.cursor();
  var generator = function* () {
    var row;
    while (row = cursor.fetch()) {
      yield row;
    }
  };
  var rectangles = generator();
  var result = [];
  var area = 0.0;
  for (var rectangle of rectangles) {
    area += rectangle.data.width * rectangle.data.height;
    result.push({id: rectangle.id, data: rectangle.data});
    if (area >= min_area) {
      break;
    }
  }
  cursor.close();
  plan.free();
  return result;
$$ LANGUAGE pljs STABLE STRICT;

SELECT get_rectangles_area(130.0);
