diff --git a/tests/busted/run_tests b/tests/busted/run_tests index eca1d87..3e38b7d 100755 --- a/tests/busted/run_tests +++ b/tests/busted/run_tests @@ -1,4 +1,4 @@ -#!/bin/sh +#!/usr/bin/env bash set -ex cd `dirname $BASH_SOURCE` cyan build --prune diff --git a/types/pllua/pllua/elog.d.tl b/types/pllua/pllua/elog.d.tl new file mode 100644 index 0000000..20745a3 --- /dev/null +++ b/types/pllua/pllua/elog.d.tl @@ -0,0 +1,65 @@ +local record elog + enum Severity + "debug" + "log" + "info" + "notice" + "warning" + "error" + end + + record ELogInfo + sqlstate: string + message: string + detail: string + table: string + column: string + datatype: string + constraint: string + schema: string + end + + elog: function(Severity, message: string) + elog: function(Severity, sqlstate: string, message: string) + elog: function(Severity, sqlstate: string, message: string, detail: string) + elog: function(Severity, sqlstate: string, message: string, detail: string, hint: string) + elog: function(Severity, ELogInfo) + + debug: function(message: string) + debug: function(sqlstate: string, message: string) + debug: function(sqlstate: string, message: string, detail: string) + debug: function(sqlstate: string, message: string, detail: string, hint: string) + debug: function(ELogInfo) + + log: function(message: string) + log: function(sqlstate: string, message: string) + log: function(sqlstate: string, message: string, detail: string) + log: function(sqlstate: string, message: string, detail: string, hint: string) + log: function(ELogInfo) + + info: function(message: string) + info: function(sqlstate: string, message: string) + info: function(sqlstate: string, message: string, detail: string) + info: function(sqlstate: string, message: string, detail: string, hint: string) + info: function(ELogInfo) + + notice: function(message: string) + notice: function(sqlstate: string, message: string) + notice: function(sqlstate: string, message: string, detail: string) + notice: function(sqlstate: string, message: string, detail: string, hint: string) + notice: function(ELogInfo) + + warning: function(message: string) + warning: function(sqlstate: string, message: string) + warning: function(sqlstate: string, message: string, detail: string) + warning: function(sqlstate: string, message: string, detail: string, hint: string) + warning: function(ELogInfo) + + error: function(message: string) + error: function(sqlstate: string, message: string) + error: function(sqlstate: string, message: string, detail: string) + error: function(sqlstate: string, message: string, detail: string, hint: string) + error: function(ELogInfo) +end + +return elog diff --git a/types/pllua/pllua/error.d.tl b/types/pllua/pllua/error.d.tl new file mode 100644 index 0000000..ead5dc0 --- /dev/null +++ b/types/pllua/pllua/error.d.tl @@ -0,0 +1,48 @@ +local record err + enum SQLErrorSeverity + "error" + end + + -- SQL errors caught in Lua code are represented as objects rather than strings, + -- though print() or tostring() will give a formatted text representation + -- The pllua.error module provides the following simple functions as a table: + record SQLError + -- Mandatory fields: + category: string -- The error category name, e.g. "data_exception", or a 5-character sqlstate category code (xx000) if no name is known + errcode: string -- The error code name, e.g. "numeric_value_out_of_range", or a 5-character sqlstate if no name for the error is known + severity: SQLErrorSeverity -- A string "error" (other values like "warning" should never be seen) + sqlstate: string -- The 5-character sqlstate code for the error + message: string -- The error message text + + -- Optional fields: + context: string|nil -- The error context + column: string|nil -- Name of a column associated with the error, if any + constraint: string|nil -- Name of a constraint associated with the error, if any + datatype: string|nil -- Name of a data type associated with the error, if any + detail: string|nil -- Detail message supplied for the error, if any + hint: string|nil -- The hint text for the error + internal_position: integer|nil -- the character position within the internal query + internal_query: string|nil -- internal query text for the error + message_id: string|nil -- Untranslated error message text (not available in PostgreSQL 9.5) + pg_source_file: string|nil -- Source file of the error + pg_source_function: string|nil -- Source function name of the error + pg_source_line: integer|nil -- source line number of the error + position: integer|nil -- character position of the error within the original query + schema: string|nil -- Name of a schema associated with the error, if any + table: string|nil -- Name of a table associated with the error, if any + end + + -- returns "error" if e is an SQL error object, otherwise nothing + type: function(e: SQLError): SQLErrorSeverity + type: function(e: any): nil + + -- returns e.errcode if e is an SQL error object, otherwise nothing + errcode: function(e: SQLError): string -- returns e.errcode + errcode: function(e: any): nil + + -- returns e.category if e is an SQL error object, otherwise nothing + category: function(e: SQLError): string + category: function(e: any): nil +end + +return err diff --git a/types/pllua/pllua/jsonb.d.tl b/types/pllua/pllua/jsonb.d.tl new file mode 100644 index 0000000..78e2ac1 --- /dev/null +++ b/types/pllua/pllua/jsonb.d.tl @@ -0,0 +1,49 @@ +local record jsonb + type JsonValue = string | {string|integer:JsonValue} | number | boolean | nil + + record ConversionOptions + map: function(val: JsonValue): JsonValue + null: any + empty_object: boolean + array_thresh: integer + array_frac: integer + end + + record JsonbDatum + userdata + + -- If the returned JsonValue is a table, its metatable will indicate + -- whether it corresponds to a json array or object: + metamethod __call: function(JsonbDatum, options: ConversionOptions): JsonValue + + typeinfo: JsonbTypeInfo + end + + record JsonbTypeInfo + userdata + + metamethod __call: function(JsonbTypeInfo, json: string | {string|integer:any}): JsonbDatum + + fromstring: function(JsonbTypeInfo, string): JsonbDatum + frombinary: function(JsonbTypeInfo, string): JsonbDatum + name: function(JsonbTypeInfo, typmod: string): string + end + + is_object: function(table): boolean + is_array: function(table): boolean + set_as_array: function(table): table + set_as_object: function(table): table + set_as_unknown: function(table): table + + -- In addition the following functions are provided from version 2.0.8 on: + -- note: iterators hold their state in upvalues: + pairs: function(val: JsonbDatum): (function(): string|integer, JsonbDatum, integer) + ipairs: function(val: JsonbDatum): (function(): integer, JsonbDatum) + type: function(val: JsonbDatum) + type: function(val: JsonbDatum | JsonValue, lax: boolean) +end + +local jval: jsonb.JsonbDatum +print((jval{} as table).pelota) + +return jsonb diff --git a/types/pllua/pllua/numeric.d.tl b/types/pllua/pllua/numeric.d.tl new file mode 100644 index 0000000..3a255bd --- /dev/null +++ b/types/pllua/pllua/numeric.d.tl @@ -0,0 +1,47 @@ +require 'pllua.pgtype' + +-- NumericDatum has metamethods for mathematical operations, but care must be +-- taken if == is used, since Lua compares their types before calling __eq, so +-- the comparison of userdata and number values will always be false. +local record numeric + record NumericDatum + userdata + + metamethod __tostring: function(NumericDatum): string + metamethod __add: function(NumericDatum|number, NumericDatum|number): NumericDatum + metamethod __div: function(NumericDatum|number, NumericDatum|number): NumericDatum + metamethod __eq: function(NumericDatum|number, NumericDatum|number): NumericDatum + metamethod __idiv: function(NumericDatum|number, NumericDatum|number): NumericDatum + metamethod __le: function(NumericDatum|number, NumericDatum|number): NumericDatum + metamethod __lt: function(NumericDatum|number, NumericDatum|number): NumericDatum + metamethod __mod: function(NumericDatum|number, NumericDatum|number): NumericDatum + metamethod __mul: function(NumericDatum|number, NumericDatum|number): NumericDatum + metamethod __pow: function(NumericDatum|number, NumericDatum|number): NumericDatum + metamethod __sub: function(NumericDatum|number, NumericDatum|number): NumericDatum + metamethod __unm: function(NumericDatum): NumericDatum + + typeinfo: TypeInfo + end + + abs: function(number|NumericDatum): NumericDatum + ceil: function(number|NumericDatum): NumericDatum + equal: function(number|NumericDatum, number|NumericDatum): boolean + exp: function(number|NumericDatum): NumericDatum + floor: function(number|NumericDatum): NumericDatum + isnan: function(number|NumericDatum): boolean + sign: function(number|NumericDatum): NumericDatum -- yes, a datum with -1, 0 or 1 + sqrt: function(number|NumericDatum): NumericDatum + log: function(number|NumericDatum): NumericDatum + log: function(number|NumericDatum, base: number|NumericDatum): NumericDatum + tointeger: function(number|NumericDatum): integer|nil + tointeger: function(number|NumericDatum): integer|nil + tointeger: function(number|NumericDatum): integer|nil + trunc: function(number|NumericDatum): NumericDatum + trunc: function(number|NumericDatum, digits: integer): NumericDatum + round: function(number|NumericDatum): NumericDatum + round: function(number|NumericDatum, digits: integer): NumericDatum + + new: function(number|NumericDatum): NumericDatum +end + +return numeric diff --git a/types/pllua/pllua/paths.d.tl b/types/pllua/pllua/paths.d.tl new file mode 100644 index 0000000..02298d0 --- /dev/null +++ b/types/pllua/pllua/paths.d.tl @@ -0,0 +1,20 @@ +-- Module added in pllua version 2.0.2. + +local record paths + bin: function(): string + lib: function(): string + pkglib: function(): string + libdir: function(): string + share: function(): string + locale: function(): string | nil + -- The following directories may be defined but not exist: + doc: function(): string | nil + etc: function(): string | nil + html: function(): string | nil + include: function(): string | nil + includeserver: function(): string | nil + man: function(): string | nil + pkginclude: function(): string | nil +end + +return paths diff --git a/types/pllua/pllua/pgtype.d.tl b/types/pllua/pllua/pgtype.d.tl new file mode 100644 index 0000000..424d316 --- /dev/null +++ b/types/pllua/pllua/pgtype.d.tl @@ -0,0 +1,39 @@ +local type Datum = any + +-- TypeInfo can't be exported here since in tl a module cannot return a Map +-- with records inside nor a maprecord (map|record). This is why it's global. +global record TypeInfo + userdata + + -- Construct a new Datum object by copying from the specified value, which must already be of a compatible type + metamethod __call: function(TypeInfo, datum: Datum): Datum + -- Construct a new Datum object of the specified type from the arguments given. The nature of the arguments varies according to the category of type being constructed. + -- More info in: https://pllua.github.io/pllua/#S2.6 + -- Consider casting Datum to the correct datum type such as time.DatetimeDatum or numeric.NumericDatum, + -- or even {string|integer:Datum} for rows/arrays, but be careful when using pairs/ipairs: + metamethod __call: function(TypeInfo, ...: any): Datum + -- If cyclic requires were supported we could have: + --metamethod __call: function(TypeInfo, time.CalendarTable): time.DatetimeDatum + + -- Construct a new Datum object given its standard text representation in str. For some types the distinction between typeinfo:fromstring(str) and typeinfo(str) is significant. + fromstring: function(TypeInfo, string): Datum + -- Construct a new Datum object given its wire-protocol binary representation in str. This is less useful than it might seem because for many data types, the interpretation of the binary representation is dependent on the client_encoding setting. + frombinary: function(TypeInfo, string): Datum + --Returns the name of the type as SQL syntax (same as the format_type function in SQL, or ::regtype output) + name: function(TypeInfo, typmod: string): string + + -- For array or range types, returns the typeinfo of the element type + element: function(TypeInfo): TypeInfo + -- For row types, returns the typeinfo of the named column + element: function(TypeInfo, column_name: string): TypeInfo +end + +local type SQLTypeName = string +local type datumtofunction = function(value: Datum|any, argno: integer): TypeInfo + +-- pgtype contains as well a special entry called "array" whose type is {SQLTypeName: TypeInfo}. +-- you will have to cast pgtype to use it, or you can use pgtype['elemtype[]'] instead. +-- There's also another special entry "jsonb" which returns a JsonbTypeInfo +local pgtype: {SQLTypeName: TypeInfo} | datumtofunction + +return pgtype diff --git a/types/pllua/pllua/spi.d.tl b/types/pllua/pllua/spi.d.tl new file mode 100644 index 0000000..c754cfb --- /dev/null +++ b/types/pllua/pllua/spi.d.tl @@ -0,0 +1,129 @@ +require 'pllua.pgtype' +local elog = require 'pllua.elog' + +local record spi + -- Row is a datum (userdata) which can be indexed by name or position, giving values + -- that can have any type (depending on the query) or even be datums themselves + type Row = any + + execute: function(query: string, ...: any): {Row} | integer + execute_count: function(query: string, maxrows: integer, ...: any): {Row} | integer + + record PrepareOptions + scroll: boolean + no_scroll: boolean + hold: boolean + fast_start: boolean + custom_plan: boolean + generic_plan: boolean + fetch_count: integer + end + + record Statement + metamethod __call: function(Statement, ...: any): {Row} | integer + + execute: function(Statement, ...: any): {Row} | integer + execute_count: function(Statement, maxrows: integer, ...: any): {Row} | integer + getcursor: function(Statement, ...: any): Cursor + rows: function(Statement, ...: any): (function(): Row) -- row iterator + + numargs: function(Statement): integer + argtype: function(Statement, argnum: integer): TypeInfo + end + + prepare: function(query: string, argtypes: {string | TypeInfo}): Statement + prepare: function(query: string, argtypes: {string | TypeInfo}, options: PrepareOptions): Statement + + rows: function(query: string, ...: any): (function(): Row) -- row iterator + + record Cursor + enum Direction + -- fetch N rows forward: + "forward" + "next" + -- fetch N rows backward: + "backward" + "prior" + -- fetch row at absolute position n: + "absolute" + -- fetch row at relative position n: + "relative" + end + + open: function(Cursor, Statement, ...: any): Cursor + open: function(Cursor, query: string, ...: any): Cursor + + isopen: function(Cursor): boolean + close: function(Cursor) + + isowned: function(Cursor): boolean + own: function(Cursor): Cursor + disown: function(Cursor): Cursor + + name: function(Cursor): string | nil + + fetch: function(Cursor): {Row} -- a list with up to one fetched rows + fetch: function(Cursor, n: integer): {Row} -- up to n rows forward + fetch: function(Cursor, n: integer, dir: Direction) + + move: function(Cursor) + move: function(Cursor, n: integer) + move: function(Cursor, n: integer, dir: Direction) + end + + findcursor: function(name: string): Cursor|nil + + newcursor: function(): Cursor + newcursor: function(name: string): Cursor + + is_atomic: function(): boolean + + -- not defined before postgresql 11: + commit: function() + rollback: function() + + -- These functions from pllua.elog are accessible via spi.* for convenience. + elog: function(elog.Severity, message: string) + elog: function(elog.Severity, sqlstate: string, message: string) + elog: function(elog.Severity, sqlstate: string, message: string, detail: string) + elog: function(elog.Severity, sqlstate: string, message: string, detail: string, hint: string) + elog: function(elog.Severity, elog.ELogInfo) + + debug: function(message: string) + debug: function(sqlstate: string, message: string) + debug: function(sqlstate: string, message: string, detail: string) + debug: function(sqlstate: string, message: string, detail: string, hint: string) + debug: function(elog.ELogInfo) + + log: function(message: string) + log: function(sqlstate: string, message: string) + log: function(sqlstate: string, message: string, detail: string) + log: function(sqlstate: string, message: string, detail: string, hint: string) + log: function(elog.ELogInfo) + + info: function(message: string) + info: function(sqlstate: string, message: string) + info: function(sqlstate: string, message: string, detail: string) + info: function(sqlstate: string, message: string, detail: string, hint: string) + info: function(elog.ELogInfo) + + notice: function(message: string) + notice: function(sqlstate: string, message: string) + notice: function(sqlstate: string, message: string, detail: string) + notice: function(sqlstate: string, message: string, detail: string, hint: string) + notice: function(elog.ELogInfo) + + warning: function(message: string) + warning: function(sqlstate: string, message: string) + warning: function(sqlstate: string, message: string, detail: string) + warning: function(sqlstate: string, message: string, detail: string, hint: string) + warning: function(elog.ELogInfo) + + error: function(message: string) + error: function(sqlstate: string, message: string) + error: function(sqlstate: string, message: string, detail: string) + error: function(sqlstate: string, message: string, detail: string, hint: string) + error: function(elog.ELogInfo) +end + +return spi diff --git a/types/pllua/pllua/time.d.tl b/types/pllua/pllua/time.d.tl new file mode 100644 index 0000000..b456ab2 --- /dev/null +++ b/types/pllua/pllua/time.d.tl @@ -0,0 +1,56 @@ +-- Module added in pllua version 2.0.3. + +require 'pllua.pgtype' + +local record time + record CalendarTable + -- available for: timestamptz, timestamp, date, interval + year: integer + month: integer + day: integer + -- available for: timestamptz, timetz, timestamp, time, interval + hour: integer + min: integer + sec: integer + usec: integer + -- available for: timestamptz, timetz + timezone: integer + -- available for: timestamptz + timezone_abbrev: string + isdst: boolean + end + + record DatetimeDatum + userdata + + as_table: function(): CalendarTable + + -- only available for timestamptz, timezone cannot be an abbreviation (UTC and UTC±hh[:mm] is allowed though): + as_table: function(timezone: integer|string): CalendarTable + + typeinfo: TypeInfo + + -- available for: timestamptz, timestamp, date, interval + year: integer + month: integer + day: integer + -- available for: timestamptz, timetz, timestamp, time, interval + hour: integer + min: integer + sec: integer + usec: integer + -- available for: timestamptz, timetz + timezone: integer + -- available for: timestamptz + timezone_abbrev: string + isdst: boolean + + -- available for timestamptz, timestamp, date: + week: integer + epoch: number + epoch_msec: number + iso_year: integer + end +end + +return time diff --git a/types/pllua/pllua/trigger.d.tl b/types/pllua/pllua/trigger.d.tl new file mode 100644 index 0000000..202f752 --- /dev/null +++ b/types/pllua/pllua/trigger.d.tl @@ -0,0 +1,49 @@ +local spi = require 'pllua.spi' + +local record trigger + -- This module provides nothing directly to Lua, but a trigger parameter of + -- type Trigger is passed as the first parameter to trigger functions (and + -- a different trigger parameter to event-trigger functions). + record Trigger + event: string + tag: string + + new: spi.Row + old: spi.Row + row: spi.Row + + name: string + + enum When + "before" + "after" + "instead" + end + when: When + + enum Operation + "insert" + "update" + "delete" + "truncate" + end + operation: Operation + op: Operation + + enum Level + "row" + "statement" + end + level: Level + + record Relation + namespace: string -- eg: 'public' + attributes: {string: integer} + name: string + oid: integer + end + relation: Relation + end +end + +return trigger diff --git a/types/pllua/pllua/trusted.d.tl b/types/pllua/pllua/trusted.d.tl new file mode 100644 index 0000000..9b37273 --- /dev/null +++ b/types/pllua/pllua/trusted.d.tl @@ -0,0 +1,16 @@ +local record trusted + enum TrustedMode + "direct" + "copy" + "proxy" + "sproxy" + end + -- module can be: a module name, an array of module names or an array of the 5-uples of the allow function: + type Module = string | {string | {string, string, TrustedMode, boolean|string, boolean}} + + allow: function(module: Module, newname: string|nil, mode: TrustedMode, global: boolean|string, preload: boolean) + require: function(module: Module, newname: string, mode: TrustedMode) -- equiv. to trusted.allow(module, newname, mode, true, true) + remove: function(newname: string, global: boolean|string) +end + +return trusted