@socialgouv/matomo-postgres 2.3.13 → 2.4.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/README.md +8 -0
- package/dist/__tests__/run.test.js +0 -4
- package/dist/__tests__/visit.json +10 -0
- package/dist/importEvent.js +72 -51
- package/dist/migrations/20260407-01-ab-testing.js +343 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -213,6 +213,14 @@ Migrations run automatically on each `pnpm start` to ensure schema compatibility
|
|
|
213
213
|
- Parallel event insertion (configurable)
|
|
214
214
|
- Automatic pagination for large datasets
|
|
215
215
|
|
|
216
|
+
## ⚠️ Limitations
|
|
217
|
+
|
|
218
|
+
### Actions per visit cap
|
|
219
|
+
|
|
220
|
+
The Matomo `Live.getLastVisitsDetails` API limits the number of actions returned per visit to **99**.
|
|
221
|
+
If a user performed more than **99** actions during a visit, the extra actions will be missing from the database (see [issue #92](https://github.com/SocialGouv/matomo-postgres/issues/92)).
|
|
222
|
+
This limitation comes from Matomo’s API itself; this library does not implement any per-action workaround.
|
|
223
|
+
|
|
216
224
|
## 🐛 Troubleshooting
|
|
217
225
|
|
|
218
226
|
### Common Issues
|
|
@@ -84,10 +84,6 @@ test('run: should run SQL queries', () => __awaiter(void 0, void 0, void 0, func
|
|
|
84
84
|
jest.useFakeTimers().setSystemTime(TEST_DATE.getTime());
|
|
85
85
|
const result = yield run();
|
|
86
86
|
expect(queries).toMatchSnapshot();
|
|
87
|
-
// Updated expectation based on actual behavior with INITIAL_OFFSET=3 (5 days total: 3 days before + today + 1 day after)
|
|
88
|
-
// 5 days * (6 events per day + 1 count query per day)
|
|
89
|
-
// Note: We also capture the initial "findLastEventInMatomo" query.
|
|
90
|
-
expect(queries.length).toEqual(1 + 5 * (6 + 1));
|
|
91
87
|
expect(result).toMatchObject({
|
|
92
88
|
daysProcessed: 5,
|
|
93
89
|
eventsImportedTotal: 5 * 6
|
|
@@ -17,6 +17,16 @@
|
|
|
17
17
|
"region": "Buenos Aires",
|
|
18
18
|
"city": "Buenos Aires",
|
|
19
19
|
"resolution": "1920x1080",
|
|
20
|
+
"experiments": [
|
|
21
|
+
{
|
|
22
|
+
"idexperiment": "3",
|
|
23
|
+
"name": "search_ab_test",
|
|
24
|
+
"variation": {
|
|
25
|
+
"idvariation": 5,
|
|
26
|
+
"name": "search_v2"
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
],
|
|
20
30
|
"dimension1": "guest",
|
|
21
31
|
"dimension3": "page",
|
|
22
32
|
"dimension6": "shop",
|
package/dist/importEvent.js
CHANGED
|
@@ -8,7 +8,54 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
8
8
|
});
|
|
9
9
|
};
|
|
10
10
|
import { sql } from 'kysely';
|
|
11
|
+
import { DESTINATION_TABLE, PARTITIONED_MATOMO_TABLE_NAME } from './config.js';
|
|
11
12
|
import { db, pool } from './db.js';
|
|
13
|
+
const MATOMO_INSERT_COLUMNS = [
|
|
14
|
+
'action_id',
|
|
15
|
+
'action_timestamp',
|
|
16
|
+
'idsite',
|
|
17
|
+
'idvisit',
|
|
18
|
+
'actions',
|
|
19
|
+
'country',
|
|
20
|
+
'region',
|
|
21
|
+
'city',
|
|
22
|
+
'operatingsystemname',
|
|
23
|
+
'devicemodel',
|
|
24
|
+
'devicebrand',
|
|
25
|
+
'visitduration',
|
|
26
|
+
'dayssincefirstvisit',
|
|
27
|
+
'visitortype',
|
|
28
|
+
'sitename',
|
|
29
|
+
'userid',
|
|
30
|
+
'serverdateprettyfirstaction',
|
|
31
|
+
'action_type',
|
|
32
|
+
'action_eventcategory',
|
|
33
|
+
'action_eventaction',
|
|
34
|
+
'action_eventname',
|
|
35
|
+
'action_eventvalue',
|
|
36
|
+
'action_timespent',
|
|
37
|
+
'usercustomproperties',
|
|
38
|
+
'usercustomdimensions',
|
|
39
|
+
'dimension1',
|
|
40
|
+
'dimension2',
|
|
41
|
+
'dimension3',
|
|
42
|
+
'dimension4',
|
|
43
|
+
'dimension5',
|
|
44
|
+
'dimension6',
|
|
45
|
+
'dimension7',
|
|
46
|
+
'dimension8',
|
|
47
|
+
'dimension9',
|
|
48
|
+
'dimension10',
|
|
49
|
+
'action_url',
|
|
50
|
+
'sitesearchkeyword',
|
|
51
|
+
'action_title',
|
|
52
|
+
'visitorid',
|
|
53
|
+
'referrertype',
|
|
54
|
+
'referrername',
|
|
55
|
+
'resolution',
|
|
56
|
+
'experiments'
|
|
57
|
+
];
|
|
58
|
+
const MATOMO_INSERT_COLUMN_SQL = sql.join(MATOMO_INSERT_COLUMNS.map((column) => sql.id(column)), sql `,\n`);
|
|
12
59
|
/**
|
|
13
60
|
*
|
|
14
61
|
* @param {Client} client
|
|
@@ -17,7 +64,7 @@ import { db, pool } from './db.js';
|
|
|
17
64
|
* @return {Promise<void>}
|
|
18
65
|
*/
|
|
19
66
|
export const importEvent = (event) => __awaiter(void 0, void 0, void 0, function* () {
|
|
20
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14;
|
|
67
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15;
|
|
21
68
|
// Build a sanitized, typed data object to reduce drift and ensure defaults in one place
|
|
22
69
|
const eventData = {
|
|
23
70
|
action_id: (_a = event.action_id) !== null && _a !== void 0 ? _a : '',
|
|
@@ -67,7 +114,8 @@ export const importEvent = (event) => __awaiter(void 0, void 0, void 0, function
|
|
|
67
114
|
visitorid: (_11 = event.visitorid) !== null && _11 !== void 0 ? _11 : null,
|
|
68
115
|
referrertype: (_12 = event.referrertype) !== null && _12 !== void 0 ? _12 : null,
|
|
69
116
|
referrername: (_13 = event.referrername) !== null && _13 !== void 0 ? _13 : null,
|
|
70
|
-
resolution: (_14 = event.resolution) !== null && _14 !== void 0 ? _14 : null
|
|
117
|
+
resolution: (_14 = event.resolution) !== null && _14 !== void 0 ? _14 : null,
|
|
118
|
+
experiments: (_15 = event.experiments) !== null && _15 !== void 0 ? _15 : null
|
|
71
119
|
};
|
|
72
120
|
// Minimal runtime validation for required fields
|
|
73
121
|
if (!eventData.action_id || eventData.action_id.trim().length === 0) {
|
|
@@ -81,53 +129,26 @@ export const importEvent = (event) => __awaiter(void 0, void 0, void 0, function
|
|
|
81
129
|
if (!pool || typeof pool.connect !== 'function') {
|
|
82
130
|
throw new Error('Database connection pool is invalid or undefined');
|
|
83
131
|
}
|
|
84
|
-
//
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
${
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
${eventData.action_type},
|
|
105
|
-
${eventData.action_eventcategory},
|
|
106
|
-
${eventData.action_eventaction},
|
|
107
|
-
${eventData.action_eventname},
|
|
108
|
-
${eventData.action_eventvalue},
|
|
109
|
-
${eventData.action_timespent},
|
|
110
|
-
${eventData.usercustomproperties},
|
|
111
|
-
${eventData.usercustomdimensions},
|
|
112
|
-
${eventData.dimension1},
|
|
113
|
-
${eventData.dimension2},
|
|
114
|
-
${eventData.dimension3},
|
|
115
|
-
${eventData.dimension4},
|
|
116
|
-
${eventData.dimension5},
|
|
117
|
-
${eventData.dimension6},
|
|
118
|
-
${eventData.dimension7},
|
|
119
|
-
${eventData.dimension8},
|
|
120
|
-
${eventData.dimension9},
|
|
121
|
-
${eventData.dimension10},
|
|
122
|
-
${eventData.action_url},
|
|
123
|
-
${eventData.sitesearchkeyword},
|
|
124
|
-
${eventData.action_title},
|
|
125
|
-
${eventData.visitorid},
|
|
126
|
-
${eventData.referrertype},
|
|
127
|
-
${eventData.referrername},
|
|
128
|
-
${eventData.resolution}
|
|
129
|
-
)
|
|
130
|
-
`.execute(db);
|
|
132
|
+
// Use different insertion logic based on DESTINATION_TABLE
|
|
133
|
+
if (DESTINATION_TABLE === PARTITIONED_MATOMO_TABLE_NAME) {
|
|
134
|
+
// Use stored procedure for partitioned table (handles automatic partition creation)
|
|
135
|
+
yield sql `
|
|
136
|
+
SELECT insert_into_matomo_partitioned(
|
|
137
|
+
${sql.join(MATOMO_INSERT_COLUMNS.map((column) => sql `${eventData[column]}`), sql `, `)}
|
|
138
|
+
)
|
|
139
|
+
`.execute(db);
|
|
140
|
+
}
|
|
141
|
+
else {
|
|
142
|
+
// Direct INSERT for standard (non-partitioned) table
|
|
143
|
+
yield sql `
|
|
144
|
+
INSERT INTO ${sql.id(DESTINATION_TABLE)} (
|
|
145
|
+
${MATOMO_INSERT_COLUMN_SQL}
|
|
146
|
+
) VALUES (
|
|
147
|
+
${sql.join(MATOMO_INSERT_COLUMNS.map((column) => sql `${eventData[column]}`), sql `, `)}
|
|
148
|
+
)
|
|
149
|
+
ON CONFLICT (action_id) DO NOTHING
|
|
150
|
+
`.execute(db);
|
|
151
|
+
}
|
|
131
152
|
}
|
|
132
153
|
catch (err) {
|
|
133
154
|
// Add context for troubleshooting
|
|
@@ -178,7 +199,7 @@ const actionProps = {
|
|
|
178
199
|
};
|
|
179
200
|
export const getEventsFromMatomoVisit = (matomoVisit) => {
|
|
180
201
|
return matomoVisit.actionDetails.map((actionDetail, actionIndex) => {
|
|
181
|
-
var _a;
|
|
202
|
+
var _a, _b;
|
|
182
203
|
const usercustomproperties = {};
|
|
183
204
|
for (let k = 1; k < 10; k++) {
|
|
184
205
|
const property = (_a = actionDetail.customVariables) === null || _a === void 0 ? void 0 : _a[k];
|
|
@@ -200,7 +221,7 @@ export const getEventsFromMatomoVisit = (matomoVisit) => {
|
|
|
200
221
|
//@ts-expect-error implicit any type
|
|
201
222
|
usercustomdimensions[dimension] = value;
|
|
202
223
|
}
|
|
203
|
-
const event = Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, matomoProps.reduce((a, prop) => (Object.assign(Object.assign({}, a), { [prop.toLowerCase()]: matomoVisit[prop] })), {})), { serverdateprettyfirstaction: new Date((matomoVisit.firstActionTimestamp || 0) * 1000).toISOString() }), Object.keys(actionProps).reduce((a, prop) => (Object.assign(Object.assign({}, a), { [prop.toLowerCase()]: actionProps[prop](actionDetail) })), {
|
|
224
|
+
const event = Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, matomoProps.reduce((a, prop) => (Object.assign(Object.assign({}, a), { [prop.toLowerCase()]: matomoVisit[prop] })), {})), { experiments: (_b = matomoVisit.experiments) !== null && _b !== void 0 ? _b : null, serverdateprettyfirstaction: new Date((matomoVisit.firstActionTimestamp || 0) * 1000).toISOString() }), Object.keys(actionProps).reduce((a, prop) => (Object.assign(Object.assign({}, a), { [prop.toLowerCase()]: actionProps[prop](actionDetail) })), {
|
|
204
225
|
action_id: `${matomoVisit.idVisit}_${actionIndex}`
|
|
205
226
|
})), {
|
|
206
227
|
// custom variables
|
|
@@ -0,0 +1,343 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import { sql } from 'kysely';
|
|
11
|
+
const MATOMO_TABLE_NAME = process.env.MATOMO_TABLE_NAME || 'matomo';
|
|
12
|
+
const PARTITIONED_MATOMO_TABLE_NAME = process.env.PARTITIONED_MATOMO_TABLE_NAME || 'matomo_partitioned';
|
|
13
|
+
export function up(db) {
|
|
14
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
15
|
+
// Add column for AB Testing
|
|
16
|
+
yield db.schema
|
|
17
|
+
.alterTable(MATOMO_TABLE_NAME)
|
|
18
|
+
.addColumn('experiments', 'jsonb')
|
|
19
|
+
.execute();
|
|
20
|
+
yield db.schema
|
|
21
|
+
.alterTable(PARTITIONED_MATOMO_TABLE_NAME)
|
|
22
|
+
.addColumn('experiments', 'jsonb')
|
|
23
|
+
.execute();
|
|
24
|
+
// Drop the previous version of the stored procedure so the signature can grow
|
|
25
|
+
// (CREATE OR REPLACE refuses to change parameter lists in PL/pgSQL).
|
|
26
|
+
yield sql `DROP FUNCTION IF EXISTS insert_into_matomo_partitioned(
|
|
27
|
+
text, timestamptz, text, text, text, text, text, text, text, text, text,
|
|
28
|
+
text, text, text, text, text, date, text, text, text, text, numeric, text,
|
|
29
|
+
json, json, text, text, text, text, text, text, text, text, text, text,
|
|
30
|
+
text, text, text, text, text, text, text
|
|
31
|
+
)`.execute(db);
|
|
32
|
+
yield sql `
|
|
33
|
+
CREATE OR REPLACE FUNCTION insert_into_matomo_partitioned(
|
|
34
|
+
p_action_id text,
|
|
35
|
+
p_action_timestamp timestamptz,
|
|
36
|
+
p_idsite text DEFAULT '',
|
|
37
|
+
p_idvisit text DEFAULT '',
|
|
38
|
+
p_actions text DEFAULT NULL,
|
|
39
|
+
p_country text DEFAULT NULL,
|
|
40
|
+
p_region text DEFAULT NULL,
|
|
41
|
+
p_city text DEFAULT NULL,
|
|
42
|
+
p_operatingsystemname text DEFAULT NULL,
|
|
43
|
+
p_devicemodel text DEFAULT NULL,
|
|
44
|
+
p_devicebrand text DEFAULT NULL,
|
|
45
|
+
p_visitduration text DEFAULT NULL,
|
|
46
|
+
p_dayssincefirstvisit text DEFAULT NULL,
|
|
47
|
+
p_visitortype text DEFAULT NULL,
|
|
48
|
+
p_sitename text DEFAULT NULL,
|
|
49
|
+
p_userid text DEFAULT NULL,
|
|
50
|
+
p_serverdateprettyfirstaction date DEFAULT NULL,
|
|
51
|
+
p_action_type text DEFAULT '',
|
|
52
|
+
p_action_eventcategory text DEFAULT '',
|
|
53
|
+
p_action_eventaction text DEFAULT '',
|
|
54
|
+
p_action_eventname text DEFAULT '',
|
|
55
|
+
p_action_eventvalue numeric DEFAULT 0,
|
|
56
|
+
p_action_timespent text DEFAULT '0',
|
|
57
|
+
p_usercustomproperties json DEFAULT NULL,
|
|
58
|
+
p_usercustomdimensions json DEFAULT NULL,
|
|
59
|
+
p_dimension1 text DEFAULT NULL,
|
|
60
|
+
p_dimension2 text DEFAULT NULL,
|
|
61
|
+
p_dimension3 text DEFAULT NULL,
|
|
62
|
+
p_dimension4 text DEFAULT NULL,
|
|
63
|
+
p_dimension5 text DEFAULT NULL,
|
|
64
|
+
p_dimension6 text DEFAULT NULL,
|
|
65
|
+
p_dimension7 text DEFAULT NULL,
|
|
66
|
+
p_dimension8 text DEFAULT NULL,
|
|
67
|
+
p_dimension9 text DEFAULT NULL,
|
|
68
|
+
p_dimension10 text DEFAULT NULL,
|
|
69
|
+
p_action_url text DEFAULT NULL,
|
|
70
|
+
p_sitesearchkeyword text DEFAULT NULL,
|
|
71
|
+
p_action_title text DEFAULT NULL,
|
|
72
|
+
p_visitorid text DEFAULT NULL,
|
|
73
|
+
p_referrertype text DEFAULT NULL,
|
|
74
|
+
p_referrername text DEFAULT NULL,
|
|
75
|
+
p_resolution text DEFAULT NULL,
|
|
76
|
+
p_experiments jsonb DEFAULT NULL
|
|
77
|
+
)
|
|
78
|
+
RETURNS void
|
|
79
|
+
LANGUAGE plpgsql
|
|
80
|
+
SECURITY INVOKER
|
|
81
|
+
AS $$
|
|
82
|
+
BEGIN
|
|
83
|
+
PERFORM create_weekly_partition_if_not_exists('${sql.raw(PARTITIONED_MATOMO_TABLE_NAME)}', p_action_timestamp);
|
|
84
|
+
|
|
85
|
+
INSERT INTO ${sql.id(PARTITIONED_MATOMO_TABLE_NAME)} (
|
|
86
|
+
action_id,
|
|
87
|
+
action_timestamp,
|
|
88
|
+
idsite,
|
|
89
|
+
idvisit,
|
|
90
|
+
actions,
|
|
91
|
+
country,
|
|
92
|
+
region,
|
|
93
|
+
city,
|
|
94
|
+
operatingsystemname,
|
|
95
|
+
devicemodel,
|
|
96
|
+
devicebrand,
|
|
97
|
+
visitduration,
|
|
98
|
+
dayssincefirstvisit,
|
|
99
|
+
visitortype,
|
|
100
|
+
sitename,
|
|
101
|
+
userid,
|
|
102
|
+
serverdateprettyfirstaction,
|
|
103
|
+
action_type,
|
|
104
|
+
action_eventcategory,
|
|
105
|
+
action_eventaction,
|
|
106
|
+
action_eventname,
|
|
107
|
+
action_eventvalue,
|
|
108
|
+
action_timespent,
|
|
109
|
+
usercustomproperties,
|
|
110
|
+
usercustomdimensions,
|
|
111
|
+
dimension1,
|
|
112
|
+
dimension2,
|
|
113
|
+
dimension3,
|
|
114
|
+
dimension4,
|
|
115
|
+
dimension5,
|
|
116
|
+
dimension6,
|
|
117
|
+
dimension7,
|
|
118
|
+
dimension8,
|
|
119
|
+
dimension9,
|
|
120
|
+
dimension10,
|
|
121
|
+
action_url,
|
|
122
|
+
sitesearchkeyword,
|
|
123
|
+
action_title,
|
|
124
|
+
visitorid,
|
|
125
|
+
referrertype,
|
|
126
|
+
referrername,
|
|
127
|
+
resolution,
|
|
128
|
+
experiments
|
|
129
|
+
) VALUES (
|
|
130
|
+
p_action_id,
|
|
131
|
+
p_action_timestamp,
|
|
132
|
+
p_idsite,
|
|
133
|
+
p_idvisit,
|
|
134
|
+
p_actions,
|
|
135
|
+
p_country,
|
|
136
|
+
p_region,
|
|
137
|
+
p_city,
|
|
138
|
+
p_operatingsystemname,
|
|
139
|
+
p_devicemodel,
|
|
140
|
+
p_devicebrand,
|
|
141
|
+
p_visitduration,
|
|
142
|
+
p_dayssincefirstvisit,
|
|
143
|
+
p_visitortype,
|
|
144
|
+
p_sitename,
|
|
145
|
+
p_userid,
|
|
146
|
+
p_serverdateprettyfirstaction,
|
|
147
|
+
p_action_type,
|
|
148
|
+
p_action_eventcategory,
|
|
149
|
+
p_action_eventaction,
|
|
150
|
+
p_action_eventname,
|
|
151
|
+
p_action_eventvalue,
|
|
152
|
+
p_action_timespent,
|
|
153
|
+
p_usercustomproperties,
|
|
154
|
+
p_usercustomdimensions,
|
|
155
|
+
p_dimension1,
|
|
156
|
+
p_dimension2,
|
|
157
|
+
p_dimension3,
|
|
158
|
+
p_dimension4,
|
|
159
|
+
p_dimension5,
|
|
160
|
+
p_dimension6,
|
|
161
|
+
p_dimension7,
|
|
162
|
+
p_dimension8,
|
|
163
|
+
p_dimension9,
|
|
164
|
+
p_dimension10,
|
|
165
|
+
p_action_url,
|
|
166
|
+
p_sitesearchkeyword,
|
|
167
|
+
p_action_title,
|
|
168
|
+
p_visitorid,
|
|
169
|
+
p_referrertype,
|
|
170
|
+
p_referrername,
|
|
171
|
+
p_resolution,
|
|
172
|
+
p_experiments
|
|
173
|
+
)
|
|
174
|
+
ON CONFLICT (action_id, action_timestamp) DO NOTHING;
|
|
175
|
+
END;
|
|
176
|
+
$$;
|
|
177
|
+
`.execute(db);
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
export function down(db) {
|
|
181
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
182
|
+
// Drop the new version of the stored procedure
|
|
183
|
+
yield sql `DROP FUNCTION IF EXISTS insert_into_matomo_partitioned(
|
|
184
|
+
text, timestamptz, text, text, text, text, text, text, text, text, text,
|
|
185
|
+
text, text, text, text, text, date, text, text, text, text, numeric, text,
|
|
186
|
+
json, json, text, text, text, text, text, text, text, text, text, text,
|
|
187
|
+
text, text, text, text, text, text, text, jsonb
|
|
188
|
+
)`.execute(db);
|
|
189
|
+
// Restore the previous version (without experiments) so the downgrade is usable
|
|
190
|
+
yield sql `
|
|
191
|
+
CREATE OR REPLACE FUNCTION insert_into_matomo_partitioned(
|
|
192
|
+
p_action_id text,
|
|
193
|
+
p_action_timestamp timestamptz,
|
|
194
|
+
p_idsite text DEFAULT '',
|
|
195
|
+
p_idvisit text DEFAULT '',
|
|
196
|
+
p_actions text DEFAULT NULL,
|
|
197
|
+
p_country text DEFAULT NULL,
|
|
198
|
+
p_region text DEFAULT NULL,
|
|
199
|
+
p_city text DEFAULT NULL,
|
|
200
|
+
p_operatingsystemname text DEFAULT NULL,
|
|
201
|
+
p_devicemodel text DEFAULT NULL,
|
|
202
|
+
p_devicebrand text DEFAULT NULL,
|
|
203
|
+
p_visitduration text DEFAULT NULL,
|
|
204
|
+
p_dayssincefirstvisit text DEFAULT NULL,
|
|
205
|
+
p_visitortype text DEFAULT NULL,
|
|
206
|
+
p_sitename text DEFAULT NULL,
|
|
207
|
+
p_userid text DEFAULT NULL,
|
|
208
|
+
p_serverdateprettyfirstaction date DEFAULT NULL,
|
|
209
|
+
p_action_type text DEFAULT '',
|
|
210
|
+
p_action_eventcategory text DEFAULT '',
|
|
211
|
+
p_action_eventaction text DEFAULT '',
|
|
212
|
+
p_action_eventname text DEFAULT '',
|
|
213
|
+
p_action_eventvalue numeric DEFAULT 0,
|
|
214
|
+
p_action_timespent text DEFAULT '0',
|
|
215
|
+
p_usercustomproperties json DEFAULT NULL,
|
|
216
|
+
p_usercustomdimensions json DEFAULT NULL,
|
|
217
|
+
p_dimension1 text DEFAULT NULL,
|
|
218
|
+
p_dimension2 text DEFAULT NULL,
|
|
219
|
+
p_dimension3 text DEFAULT NULL,
|
|
220
|
+
p_dimension4 text DEFAULT NULL,
|
|
221
|
+
p_dimension5 text DEFAULT NULL,
|
|
222
|
+
p_dimension6 text DEFAULT NULL,
|
|
223
|
+
p_dimension7 text DEFAULT NULL,
|
|
224
|
+
p_dimension8 text DEFAULT NULL,
|
|
225
|
+
p_dimension9 text DEFAULT NULL,
|
|
226
|
+
p_dimension10 text DEFAULT NULL,
|
|
227
|
+
p_action_url text DEFAULT NULL,
|
|
228
|
+
p_sitesearchkeyword text DEFAULT NULL,
|
|
229
|
+
p_action_title text DEFAULT NULL,
|
|
230
|
+
p_visitorid text DEFAULT NULL,
|
|
231
|
+
p_referrertype text DEFAULT NULL,
|
|
232
|
+
p_referrername text DEFAULT NULL,
|
|
233
|
+
p_resolution text DEFAULT NULL
|
|
234
|
+
)
|
|
235
|
+
RETURNS void
|
|
236
|
+
LANGUAGE plpgsql
|
|
237
|
+
SECURITY INVOKER
|
|
238
|
+
AS $$
|
|
239
|
+
BEGIN
|
|
240
|
+
PERFORM create_weekly_partition_if_not_exists('${sql.raw(PARTITIONED_MATOMO_TABLE_NAME)}', p_action_timestamp);
|
|
241
|
+
|
|
242
|
+
INSERT INTO ${sql.id(PARTITIONED_MATOMO_TABLE_NAME)} (
|
|
243
|
+
action_id,
|
|
244
|
+
action_timestamp,
|
|
245
|
+
idsite,
|
|
246
|
+
idvisit,
|
|
247
|
+
actions,
|
|
248
|
+
country,
|
|
249
|
+
region,
|
|
250
|
+
city,
|
|
251
|
+
operatingsystemname,
|
|
252
|
+
devicemodel,
|
|
253
|
+
devicebrand,
|
|
254
|
+
visitduration,
|
|
255
|
+
dayssincefirstvisit,
|
|
256
|
+
visitortype,
|
|
257
|
+
sitename,
|
|
258
|
+
userid,
|
|
259
|
+
serverdateprettyfirstaction,
|
|
260
|
+
action_type,
|
|
261
|
+
action_eventcategory,
|
|
262
|
+
action_eventaction,
|
|
263
|
+
action_eventname,
|
|
264
|
+
action_eventvalue,
|
|
265
|
+
action_timespent,
|
|
266
|
+
usercustomproperties,
|
|
267
|
+
usercustomdimensions,
|
|
268
|
+
dimension1,
|
|
269
|
+
dimension2,
|
|
270
|
+
dimension3,
|
|
271
|
+
dimension4,
|
|
272
|
+
dimension5,
|
|
273
|
+
dimension6,
|
|
274
|
+
dimension7,
|
|
275
|
+
dimension8,
|
|
276
|
+
dimension9,
|
|
277
|
+
dimension10,
|
|
278
|
+
action_url,
|
|
279
|
+
sitesearchkeyword,
|
|
280
|
+
action_title,
|
|
281
|
+
visitorid,
|
|
282
|
+
referrertype,
|
|
283
|
+
referrername,
|
|
284
|
+
resolution
|
|
285
|
+
) VALUES (
|
|
286
|
+
p_action_id,
|
|
287
|
+
p_action_timestamp,
|
|
288
|
+
p_idsite,
|
|
289
|
+
p_idvisit,
|
|
290
|
+
p_actions,
|
|
291
|
+
p_country,
|
|
292
|
+
p_region,
|
|
293
|
+
p_city,
|
|
294
|
+
p_operatingsystemname,
|
|
295
|
+
p_devicemodel,
|
|
296
|
+
p_devicebrand,
|
|
297
|
+
p_visitduration,
|
|
298
|
+
p_dayssincefirstvisit,
|
|
299
|
+
p_visitortype,
|
|
300
|
+
p_sitename,
|
|
301
|
+
p_userid,
|
|
302
|
+
p_serverdateprettyfirstaction,
|
|
303
|
+
p_action_type,
|
|
304
|
+
p_action_eventcategory,
|
|
305
|
+
p_action_eventaction,
|
|
306
|
+
p_action_eventname,
|
|
307
|
+
p_action_eventvalue,
|
|
308
|
+
p_action_timespent,
|
|
309
|
+
p_usercustomproperties,
|
|
310
|
+
p_usercustomdimensions,
|
|
311
|
+
p_dimension1,
|
|
312
|
+
p_dimension2,
|
|
313
|
+
p_dimension3,
|
|
314
|
+
p_dimension4,
|
|
315
|
+
p_dimension5,
|
|
316
|
+
p_dimension6,
|
|
317
|
+
p_dimension7,
|
|
318
|
+
p_dimension8,
|
|
319
|
+
p_dimension9,
|
|
320
|
+
p_dimension10,
|
|
321
|
+
p_action_url,
|
|
322
|
+
p_sitesearchkeyword,
|
|
323
|
+
p_action_title,
|
|
324
|
+
p_visitorid,
|
|
325
|
+
p_referrertype,
|
|
326
|
+
p_referrername,
|
|
327
|
+
p_resolution
|
|
328
|
+
)
|
|
329
|
+
ON CONFLICT (action_id, action_timestamp) DO NOTHING;
|
|
330
|
+
END;
|
|
331
|
+
$$;
|
|
332
|
+
`.execute(db);
|
|
333
|
+
// Drop column for AB Testing
|
|
334
|
+
yield db.schema
|
|
335
|
+
.alterTable(MATOMO_TABLE_NAME)
|
|
336
|
+
.dropColumn('experiments')
|
|
337
|
+
.execute();
|
|
338
|
+
yield db.schema
|
|
339
|
+
.alterTable(PARTITIONED_MATOMO_TABLE_NAME)
|
|
340
|
+
.dropColumn('experiments')
|
|
341
|
+
.execute();
|
|
342
|
+
});
|
|
343
|
+
}
|
package/package.json
CHANGED