PLSwift icon indicating copy to clipboard operation
PLSwift copied to clipboard

Test PostgreSQL 12 compatibility

Open helje5 opened this issue 5 years ago • 6 comments

hello, I am reading your http://www.alwaysrightinstitute.com/plswift/ but I found that it is incompatible for postgresql 12. can you update your to support postgresql 12?

Need to check that out.

helje5 avatar Jul 17 '20 11:07 helje5

I tried to work on it for pgsql >= 12 in PGFunction.swift

public extension FunctionCallInfoBaseData {
  
  /// Access PostgreSQL function call arguments as a Datum
  subscript(datum idx: Int) -> Datum? {
    // convert tuple to index
    switch idx {
      case 0: return args.0
      case 1: return args.1
      case 2: return args.2
      case 3: return args.3
      case 4: return args.4
      case 5: return args.5
      case 6: return args.6
      case 7: return args.7
      default: return nil
    }
  }
  
  /// Access PostgreSQL function call arguments as an Int
  subscript(int idx: Int) -> Int {
    guard let datum = self[datum: idx] else { return -42 }
    return datum.intValue
  }
}

Structure changed from

typedef struct FunctionCallInfoData
{
	FmgrInfo   *flinfo;			/* ptr to lookup info used for this call */
	fmNodePtr	context;		/* pass info about context of call */
	fmNodePtr	resultinfo;		/* pass or return extra info about result */
	Oid			fncollation;	/* collation for function to use */
	bool		isnull;			/* function must set true if result is NULL */
	short		nargs;			/* # arguments actually passed */
	Datum		arg[FUNC_MAX_ARGS];		/* Arguments passed to function */
	bool		argnull[FUNC_MAX_ARGS]; /* T if arg[i] is actually NULL */
} FunctionCallInfoData;

to

typedef struct FunctionCallInfoBaseData
{
        FmgrInfo   *flinfo;                     /* ptr to lookup info used for this call */
        fmNodePtr       context;                /* pass info about context of call */
        fmNodePtr       resultinfo;             /* pass or return extra info about result */
        Oid                     fncollation;    /* collation for function to use */
#define FIELDNO_FUNCTIONCALLINFODATA_ISNULL 4
        bool            isnull;                 /* function must set true if result is NULL */
        short           nargs;                  /* # arguments actually passed */
#define FIELDNO_FUNCTIONCALLINFODATA_ARGS 6
        NullableDatum args[FLEXIBLE_ARRAY_MEMBER];
} FunctionCallInfoBaseData;

Build log

# swift pl build
/root/helloswiftpl/.build/checkouts/PLSwift/Sources/PLSwift/PGFunction.swift:17:22: error: cannot find 'args' in scope
      case 0: return args.0
                     ^~~~
/root/helloswiftpl/.build/checkouts/PLSwift/Sources/PLSwift/PGFunction.swift:18:22: error: cannot find 'args' in scope
      case 1: return args.1
                     ^~~~
/root/helloswiftpl/.build/checkouts/PLSwift/Sources/PLSwift/PGFunction.swift:19:22: error: cannot find 'args' in scope
      case 2: return args.2
                     ^~~~
/root/helloswiftpl/.build/checkouts/PLSwift/Sources/PLSwift/PGFunction.swift:20:22: error: cannot find 'args' in scope
      case 3: return args.3
                     ^~~~
/root/helloswiftpl/.build/checkouts/PLSwift/Sources/PLSwift/PGFunction.swift:21:22: error: cannot find 'args' in scope
      case 4: return args.4
                     ^~~~
/root/helloswiftpl/.build/checkouts/PLSwift/Sources/PLSwift/PGFunction.swift:22:22: error: cannot find 'args' in scope
      case 5: return args.5
                     ^~~~
/root/helloswiftpl/.build/checkouts/PLSwift/Sources/PLSwift/PGFunction.swift:23:22: error: cannot find 'args' in scope
      case 6: return args.6
                     ^~~~
/root/helloswiftpl/.build/checkouts/PLSwift/Sources/PLSwift/PGFunction.swift:24:22: error: cannot find 'args' in scope
      case 7: return args.7
                     ^~~~
[1/1] Compiling PLSwift PGFunction.swift

It is strange args is not in scope. This is commit broke the lib https://github.com/postgres/postgres/commit/a9c35cf85ca1ff72f16f0f10d7ddee6e582b62b8

zloidemon avatar Nov 11 '21 17:11 zloidemon

Swift has no way of dealing with args safely because there is no known length at compile time, and bounds checking would not work as it does with native Swift arrays.

To get this compiling I just commented out everything in this file. I think if I end up using this project at all, I will either write a C helper that fetches a certain argument and expose it to Swift, or will organise the code so that the low-level interactions with the postgres API happen in C and the business logic happens in Swift

ephemer avatar Jul 07 '22 12:07 ephemer

Swift has no way of dealing with args safely because there is no known length at compile time, and bounds checking would not work as it does with native Swift arrays.

I don't understand that comment. Swift Array lengths are always dynamic and not known at compile time. The length of the pgarray is in nargs.

Presumably in the new setup it is not exposed as an args tuple anymore? When dealing w/ inline C arrays in Swift, you usually grab the start and then just index the values. Would be nice to see what PG12 shows when cmd-clicking on a FunctionCallInfoBaseData (i.e. how it is exposed to Swift).

helje5 avatar Jul 07 '22 12:07 helje5