@platformatic/sql-mapper 3.55.0 → 3.57.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.js CHANGED
@@ -13,6 +13,7 @@ import {
13
13
  import * as queriesFactory from './lib/queries/index.js'
14
14
  import { setupTelemetry } from './lib/telemetry.js'
15
15
  import { areSchemasSupported } from './lib/utils.js'
16
+ import { parseVector } from './lib/vector.js'
16
17
 
17
18
  // Ignore the function as it is only used only for MySQL and PostgreSQL
18
19
  /* istanbul ignore next */
@@ -76,6 +77,16 @@ const defaultAutoTimestampFields = {
76
77
  updatedAt: 'updated_at'
77
78
  }
78
79
 
80
+ async function registerPostgreSQLExtensionTypes (db) {
81
+ try {
82
+ await db.registerTypeParser('vector', parseVector)
83
+ } catch {}
84
+
85
+ try {
86
+ await db.registerTypeParser('_vector', value => db.parseArray(value, parseVector))
87
+ } catch {}
88
+ }
89
+
79
90
  export async function createConnectionPool ({
80
91
  log,
81
92
  connectionString,
@@ -102,6 +113,7 @@ export async function createConnectionPool ({
102
113
  queueTimeoutMilliseconds,
103
114
  acquireLockTimeoutMilliseconds
104
115
  )
116
+ await registerPostgreSQLExtensionTypes(db)
105
117
  sql = createConnectionPoolPg.sql
106
118
  db.isPg = true
107
119
  } else if (connectionString.indexOf('mysql') === 0) {
package/lib/entity.js CHANGED
@@ -14,6 +14,7 @@ import {
14
14
  } from './errors.js'
15
15
  import { wrapDB } from './telemetry.js'
16
16
  import { sanitizeLimit, tableName, toLowerFirst, toSingular, toUpperFirst } from './utils.js'
17
+ import { isVectorType, parseVector, serializeVector } from './vector.js'
17
18
 
18
19
  function createMapper (
19
20
  defaultDb,
@@ -75,7 +76,7 @@ function createMapper (
75
76
  function fixInput (input) {
76
77
  const newInput = {}
77
78
  for (const key of Object.keys(input)) {
78
- const value = input[key]
79
+ let value = input[key]
79
80
  let newKey = inputToFieldMap[key]
80
81
  if (newKey === undefined) {
81
82
  if (fields[key] !== undefined) {
@@ -84,6 +85,11 @@ function createMapper (
84
85
  throw new UnknownFieldError(key)
85
86
  }
86
87
  }
88
+
89
+ if (isVectorType(fields[newKey].sqlType)) {
90
+ value = serializeVector(value)
91
+ }
92
+
87
93
  newInput[newKey] = value
88
94
  }
89
95
  return newInput
@@ -100,6 +106,9 @@ function createMapper (
100
106
  if (primaryKeys.has(key) && value !== null && value !== undefined) {
101
107
  value = value.toString()
102
108
  }
109
+ if (newKey && isVectorType(fields[key].sqlType)) {
110
+ value = parseVector(value)
111
+ }
103
112
  newOutput[newKey] = value
104
113
  }
105
114
  return newOutput
@@ -327,6 +336,10 @@ function createMapper (
327
336
  }
328
337
 
329
338
  function computeCriteriaValue (fieldWrap, value) {
339
+ if (isVectorType(fieldWrap.sqlType)) {
340
+ return sql`${serializeVector(value)}`
341
+ }
342
+
330
343
  if (Array.isArray(value)) {
331
344
  return sql`(${sql.join(
332
345
  value.map(v => computeCriteriaValue(fieldWrap, v)),
@@ -487,7 +500,8 @@ export function buildEntity (
487
500
  acc[column.column_name] = {
488
501
  sqlType: column.udt_name,
489
502
  isNullable: column.is_nullable === 'YES',
490
- isArray: column.isArray
503
+ isArray: column.isArray,
504
+ vectorDimensions: column.vectorDimensions
491
505
  }
492
506
 
493
507
  // To get enum values in mysql and mariadb
package/lib/queries/pg.js CHANGED
@@ -46,10 +46,16 @@ export async function listColumns (db, sql, table, schema) {
46
46
  */
47
47
 
48
48
  const res = await db.query(sql`
49
- SELECT column_name, udt_name, is_nullable, is_generated, data_type
50
- FROM information_schema.columns
51
- WHERE table_name = ${table}
52
- AND table_schema = ${schema}
49
+ SELECT c.column_name, c.udt_name, c.is_nullable, c.is_generated, c.data_type,
50
+ pg_catalog.format_type(a.atttypid, a.atttypmod) AS formatted_type
51
+ FROM information_schema.columns c
52
+ JOIN pg_catalog.pg_class cls ON cls.relname = c.table_name
53
+ JOIN pg_catalog.pg_namespace ns ON ns.oid = cls.relnamespace AND ns.nspname = c.table_schema
54
+ JOIN pg_catalog.pg_attribute a ON a.attrelid = cls.oid AND a.attname = c.column_name
55
+ WHERE c.table_name = ${table}
56
+ AND c.table_schema = ${schema}
57
+ AND a.attnum > 0
58
+ AND NOT a.attisdropped
53
59
  `)
54
60
 
55
61
  for (const col of res) {
@@ -59,6 +65,11 @@ export async function listColumns (db, sql, table, schema) {
59
65
  } else {
60
66
  col.isArray = false
61
67
  }
68
+
69
+ const match = col.formatted_type?.match(/^vector\((\d+)\)$/)
70
+ if (match) {
71
+ col.vectorDimensions = Number(match[1])
72
+ }
62
73
  }
63
74
 
64
75
  return res
package/lib/vector.js ADDED
@@ -0,0 +1,34 @@
1
+ export function isVectorType (sqlType) {
2
+ return sqlType === 'vector'
3
+ }
4
+
5
+ export function serializeVector (value) {
6
+ if (Array.isArray(value)) {
7
+ return JSON.stringify(value)
8
+ }
9
+
10
+ if (ArrayBuffer.isView(value)) {
11
+ return JSON.stringify(Array.from(value))
12
+ }
13
+
14
+ return value
15
+ }
16
+
17
+ export function parseVector (value) {
18
+ if (value === null || value === undefined || Array.isArray(value)) {
19
+ return value
20
+ }
21
+
22
+ if (typeof value !== 'string') {
23
+ return value
24
+ }
25
+
26
+ try {
27
+ const parsed = JSON.parse(value)
28
+ if (Array.isArray(parsed)) {
29
+ return parsed
30
+ }
31
+ } catch {}
32
+
33
+ return value
34
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@platformatic/sql-mapper",
3
- "version": "3.55.0",
3
+ "version": "3.57.0",
4
4
  "description": "A data mapper utility for SQL databases",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -35,8 +35,8 @@
35
35
  "camelcase": "^6.3.0",
36
36
  "fastify-plugin": "^5.0.0",
37
37
  "inflected": "^2.1.0",
38
- "@platformatic/foundation": "3.55.0",
39
- "@platformatic/telemetry": "3.55.0"
38
+ "@platformatic/foundation": "3.57.0",
39
+ "@platformatic/telemetry": "3.57.0"
40
40
  },
41
41
  "engines": {
42
42
  "node": ">=22.19.0"