使用knex.raw()创建枚举类型时的语法错误

时间:2018-12-11 03:55:10

标签: knex.js

我想使用knex.raw()方法创建一个枚举类型,这是我的migrate代码:

import * as Knex from 'knex';
import { ChannelEnum } from '../types';

exports.up = function(knex: Knex): Promise<any> {
  return Promise.all([
    knex.schema
      .createTable('channel', (t: Knex.TableBuilder) => {
        t.increments();
        const enumOptions: Knex.EnumOptions = {
          useNative: true,
          enumName: 'channel_nme_b'
        };
        t.enum('channel_nme_a', [ChannelEnum.FACEBOOK, ChannelEnum.GOOGLE, ChannelEnum.INSTAGRAM]);
        t.enum('channel_nme_b', [ChannelEnum.FACEBOOK, ChannelEnum.GOOGLE, ChannelEnum.INSTAGRAM], enumOptions);
      })
      .then(() => {
        return knex.raw(`create type "channel_nme_c" as enum (?,?,?);`, [
          ChannelEnum.FACEBOOK,
          ChannelEnum.GOOGLE,
          ChannelEnum.INSTAGRAM
        ]);
      })
      .then(() => {
        return knex.raw(`alter table "channel" add column if not exists channel_nme_c channel_nme_c;`);
      })
  ]);
};

但是出现错误:

{ method: 'raw',
  sql: 'create type "channel_nme_c" as enum (?,?,?);',
  bindings: [ 'FACEBOOK', 'GOOGLE', 'INSTAGRAM' ],
  options: {},
  __knexQueryUid: 'f8fdf6f3-50d1-4b2e-afbc-8d9e971471fb' }
migration file "20181211102654_db.ts" failed
migration failed with error: create type "channel_nme_c" as enum ($1,$2,$3); - syntax error at or near "$1"
{ method: 'update',
  options: {},
  timeout: false,
  cancelOnTimeout: false,
  bindings: [ 0 ],
  __knexQueryUid: '38a05697-3446-432a-a3f5-5d0ca7940049',
  sql: 'update "knex_migrations_lock" set "is_locked" = ?',
  returning: undefined }
error: syntax error at or near "$1"
    at Connection.parseE (/Users/ldu020/workspace/nodejs-pg-knex-samples/node_modules/pg/lib/connection.js:554:11)
    at Connection.parseMessage (/Users/ldu020/workspace/nodejs-pg-knex-samples/node_modules/pg/lib/connection.js:379:19)
    at Socket.<anonymous> (/Users/ldu020/workspace/nodejs-pg-knex-samples/node_modules/pg/lib/connection.js:119:22)
    at emitOne (events.js:116:13)
    at Socket.emit (events.js:211:7)
    at addChunk (_stream_readable.js:263:12)
    at readableAddChunk (_stream_readable.js:250:11)
    at Socket.Readable.push (_stream_readable.js:208:10)
    at TCP.onread (net.js:597:20)

似乎bindings的raw错误,但不知道为什么。

2 个答案:

答案 0 :(得分:0)

可能postgresql不允许将值绑定用于枚举值。您需要将这些值插入到SQL字符串中,例如:

return knex.raw(`create type "channel_nme_c" as enum ('${ChannelEnum.FACEBOOK}', '${ChannelEnum.GOOGLE}', '${ChannelEnum.INSTAGRAM}')`);

答案 1 :(得分:0)

我为使用pg驱动程序创建枚举类型进行了更多测试。在这种情况下,pg驱动程序似乎不支持值绑定。

const sql = `
  create type "channel_nme_d" as enum ($1, $2, $3);
`;
const res = await client.query(sql, [ChannelEnum.FACEBOOK, ChannelEnum.GOOGLE, ChannelEnum.INSTAGRAM]);

以上代码将引发错误:error: syntax error at or near "$1"

下面的代码可以正常工作。

const sql = `
  create type "channel_nme_e" as enum ('${ChannelEnum.FACEBOOK}','${ChannelEnum.GOOGLE}','${
  ChannelEnum.INSTAGRAM
}');
`;
const res = await client.query(sql);

检查枚举类型:

nodejs-pg-knex-samples-# \dT
          List of data types
 Schema |     Name      | Description
--------+---------------+-------------
 public | channel_nme_b |
 public | channel_nme_c |
 public | channel_nme_e |
(3 rows)

似乎knex.raw(sql, bindings)只是直接将原始SQL和绑定传递给query的{​​{1}}方法。