From b0d3b4ec7c7220be76d392e222c73d1659b407a5 Mon Sep 17 00:00:00 2001
From: Jan Dolezel <dolezel.jan@gmail.com>
Date: Thu, 7 Feb 2019 09:13:09 +0100
Subject: [PATCH] Adding LIKE options when creating table

---
 docs/tables.md                           |  8 +++++++-
 index.d.ts                               |  9 ++++++++-
 lib/operations/tables.js                 | 18 +++++++++++++++++-
 test/migrations/076_create_table_like.js | 17 +++++++++++++++++
 4 files changed, 49 insertions(+), 3 deletions(-)
 create mode 100644 test/migrations/076_create_table_like.js

diff --git a/docs/tables.md b/docs/tables.md
index 6496c23c..8c658fe6 100644
--- a/docs/tables.md
+++ b/docs/tables.md
@@ -13,7 +13,13 @@
   - `ifNotExists` _[bool]_ - default false
   - `inherits` _[[Name](migrations.md#type)]_ - table(s) to inherit from
   - `constraints` _[object]_ - table constraints see [add constraint](constraints.md#pgmaddconstraint-tablename-constraint_name-expression-)
-  - `like` _[[Name](migrations.md#type)]_ - table(s) to inherit from
+  - `like` either:
+    - _[[Name](migrations.md#type)]_ - table(s) to inherit from
+    - or _[object]_
+      - `table` _[[Name](migrations.md#type)]_ - table(s) to inherit from
+      - `options` _[object]_ - like options (optional)
+        - `including` _[string or array of strings]_ - 'COMMENTS', 'CONSTRAINTS', 'DEFAULTS', 'IDENTITY', 'INDEXES', 'STATISTICS', 'STORAGE', 'ALL'
+        - `excluding` _[string or array of strings]_ - 'COMMENTS', 'CONSTRAINTS', 'DEFAULTS', 'IDENTITY', 'INDEXES', 'STATISTICS', 'STORAGE', 'ALL'
   - `comment` _[string]_ - adds comment on table
 
 **Reverse Operation:** `dropTable`
diff --git a/index.d.ts b/index.d.ts
index 8c6fa6ab..edad860f 100644
--- a/index.d.ts
+++ b/index.d.ts
@@ -50,11 +50,18 @@ export interface ColumnDefinition extends ReferencesOptions {
     comment?: string | null
 }
 
+export type Like = 'COMMENTS' | 'CONSTRAINTS' | 'DEFAULTS' | 'IDENTITY' | 'INDEXES' | 'STATISTICS' | 'STORAGE' | 'ALL'
+
+export interface LikeOptions {
+    including?: Like | Like[]
+    excluding?: Like | Like[]
+}
+
 export interface TableOptions {
     temporary?: boolean
     ifNotExists?: boolean
     inherits?: Name
-    like?: Name
+    like?: Name | { table: Name, options?: LikeOptions }
     constraints?: ConstraintOptions
     comment?: string | null
 }
diff --git a/lib/operations/tables.js b/lib/operations/tables.js
index 3e48e0a6..8a9695e5 100644
--- a/lib/operations/tables.js
+++ b/lib/operations/tables.js
@@ -185,6 +185,22 @@ const parseConstraints = (table, options, genName) => {
     : constraints;
 };
 
+const parseLike = like => {
+  const formatOptions = (name, options) =>
+    (_.isArray(options) ? options : [options])
+      .map(option => ` ${name} ${option}`)
+      .join("");
+
+  const table = typeof like === "string" || !like.table ? like : like.table;
+  const options = like.options
+    ? [
+        formatOptions("INCLUDING", like.options.including),
+        formatOptions("EXCLUDING", like.options.excluding)
+      ].join("")
+    : "";
+  return template`LIKE "${table}"${options}`;
+};
+
 // TABLE
 function dropTable(tableName, { ifExists, cascade } = {}) {
   const ifExistsStr = ifExists ? " IF EXISTS" : "";
@@ -221,7 +237,7 @@ function createTable(typeShorthands) {
     const constraints = { ...optionsConstraints, ...columnsConstraints };
     const constraintLines = parseConstraints(tableName, constraints, true);
     const tableDefinition = [...columnLines, ...constraintLines].concat(
-      like ? [template`LIKE "${like}"`] : []
+      like ? [parseLike(like)] : []
     );
 
     const temporaryStr = temporary ? " TEMPORARY" : "";
diff --git a/test/migrations/076_create_table_like.js b/test/migrations/076_create_table_like.js
new file mode 100644
index 00000000..27a6f045
--- /dev/null
+++ b/test/migrations/076_create_table_like.js
@@ -0,0 +1,17 @@
+exports.up = pgm => {
+  pgm.createTable(
+    "t_like",
+    {},
+    {
+      like: {
+        table: "t1",
+        options: {
+          including: ["COMMENTS", "CONSTRAINTS"],
+          excluding: ["STATISTICS", "STORAGE"]
+        }
+      }
+    }
+  );
+};
+
+exports.down = () => null;