@oneuptime/common 7.0.4358 → 7.0.4395

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.
Files changed (83) hide show
  1. package/Models/AnalyticsModels/AnalyticsBaseModel/AnalyticsBaseModel.ts +0 -7
  2. package/Models/AnalyticsModels/AnalyticsBaseModel/CommonModel.ts +0 -13
  3. package/Models/AnalyticsModels/ExceptionInstance.ts +2 -2
  4. package/Models/DatabaseModels/Monitor.ts +1 -1
  5. package/Models/DatabaseModels/OnCallDutyPolicyEscalationRuleSchedule.ts +2 -2
  6. package/Models/DatabaseModels/OnCallDutyPolicyEscalationRuleTeam.ts +2 -2
  7. package/Models/DatabaseModels/OnCallDutyPolicyEscalationRuleUser.ts +2 -2
  8. package/Models/DatabaseModels/OnCallDutyPolicyTimeLog.ts +2 -2
  9. package/Models/DatabaseModels/Probe.ts +7 -1
  10. package/Models/DatabaseModels/ServiceCatalog.ts +2 -2
  11. package/Models/DatabaseModels/ServiceCopilotCodeRepository.ts +2 -2
  12. package/Server/Middleware/ProjectAuthorization.ts +11 -3
  13. package/Server/Services/OpenTelemetryIngestService.ts +13 -9
  14. package/Server/Utils/AnalyticsDatabase/Statement.ts +0 -1
  15. package/Server/Utils/AnalyticsDatabase/StatementGenerator.ts +28 -81
  16. package/Server/Utils/OpenAPI.ts +605 -16
  17. package/Server/Utils/StartServer.ts +2 -2
  18. package/Tests/Server/Utils/AnalyticsDatabase/StatementGenerator.test.ts +0 -49
  19. package/Types/AnalyticsDatabase/TableColumn.ts +0 -26
  20. package/Types/AnalyticsDatabase/TableColumnType.ts +2 -1
  21. package/Types/Database/TableColumnType.ts +3 -0
  22. package/Types/GenericFunction.ts +1 -1
  23. package/Types/GenericObject.ts +1 -1
  24. package/Types/Object.ts +1 -1
  25. package/UI/esbuild-config.js +214 -0
  26. package/Utils/Schema/AnalyticsModelSchema.ts +741 -0
  27. package/Utils/Schema/BaseSchema.ts +450 -0
  28. package/Utils/Schema/ModelSchema.ts +227 -460
  29. package/build/dist/Models/AnalyticsModels/AnalyticsBaseModel/AnalyticsBaseModel.js +0 -6
  30. package/build/dist/Models/AnalyticsModels/AnalyticsBaseModel/AnalyticsBaseModel.js.map +1 -1
  31. package/build/dist/Models/AnalyticsModels/AnalyticsBaseModel/CommonModel.js +0 -9
  32. package/build/dist/Models/AnalyticsModels/AnalyticsBaseModel/CommonModel.js.map +1 -1
  33. package/build/dist/Models/AnalyticsModels/ExceptionInstance.js +2 -2
  34. package/build/dist/Models/AnalyticsModels/ExceptionInstance.js.map +1 -1
  35. package/build/dist/Models/DatabaseModels/Monitor.js +1 -1
  36. package/build/dist/Models/DatabaseModels/Monitor.js.map +1 -1
  37. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyEscalationRuleSchedule.js +2 -2
  38. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyEscalationRuleSchedule.js.map +1 -1
  39. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyEscalationRuleTeam.js +2 -2
  40. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyEscalationRuleTeam.js.map +1 -1
  41. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyEscalationRuleUser.js +2 -2
  42. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyEscalationRuleUser.js.map +1 -1
  43. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyTimeLog.js +2 -2
  44. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyTimeLog.js.map +1 -1
  45. package/build/dist/Models/DatabaseModels/Probe.js +7 -1
  46. package/build/dist/Models/DatabaseModels/Probe.js.map +1 -1
  47. package/build/dist/Models/DatabaseModels/ServiceCatalog.js +2 -2
  48. package/build/dist/Models/DatabaseModels/ServiceCatalog.js.map +1 -1
  49. package/build/dist/Models/DatabaseModels/ServiceCopilotCodeRepository.js +2 -2
  50. package/build/dist/Models/DatabaseModels/ServiceCopilotCodeRepository.js.map +1 -1
  51. package/build/dist/Server/Middleware/ProjectAuthorization.js +7 -3
  52. package/build/dist/Server/Middleware/ProjectAuthorization.js.map +1 -1
  53. package/build/dist/Server/Services/OpenTelemetryIngestService.js +8 -4
  54. package/build/dist/Server/Services/OpenTelemetryIngestService.js.map +1 -1
  55. package/build/dist/Server/Utils/AnalyticsDatabase/Statement.js +0 -1
  56. package/build/dist/Server/Utils/AnalyticsDatabase/Statement.js.map +1 -1
  57. package/build/dist/Server/Utils/AnalyticsDatabase/StatementGenerator.js +15 -55
  58. package/build/dist/Server/Utils/AnalyticsDatabase/StatementGenerator.js.map +1 -1
  59. package/build/dist/Server/Utils/OpenAPI.js +467 -12
  60. package/build/dist/Server/Utils/OpenAPI.js.map +1 -1
  61. package/build/dist/Server/Utils/StartServer.js +2 -2
  62. package/build/dist/Server/Utils/StartServer.js.map +1 -1
  63. package/build/dist/Tests/Server/Utils/AnalyticsDatabase/StatementGenerator.test.js +0 -43
  64. package/build/dist/Tests/Server/Utils/AnalyticsDatabase/StatementGenerator.test.js.map +1 -1
  65. package/build/dist/Types/AnalyticsDatabase/TableColumn.js +0 -19
  66. package/build/dist/Types/AnalyticsDatabase/TableColumn.js.map +1 -1
  67. package/build/dist/Types/AnalyticsDatabase/TableColumnType.js +2 -1
  68. package/build/dist/Types/AnalyticsDatabase/TableColumnType.js.map +1 -1
  69. package/build/dist/Types/Database/TableColumnType.js +3 -0
  70. package/build/dist/Types/Database/TableColumnType.js.map +1 -1
  71. package/build/dist/Utils/Schema/AnalyticsModelSchema.js +619 -0
  72. package/build/dist/Utils/Schema/AnalyticsModelSchema.js.map +1 -0
  73. package/build/dist/Utils/Schema/BaseSchema.js +295 -0
  74. package/build/dist/Utils/Schema/BaseSchema.js.map +1 -0
  75. package/build/dist/Utils/Schema/ModelSchema.js +207 -390
  76. package/build/dist/Utils/Schema/ModelSchema.js.map +1 -1
  77. package/package.json +3 -1
  78. package/Models/AnalyticsModels/AnalyticsBaseModel/NestedModel.ts +0 -8
  79. package/Models/AnalyticsModels/NestedModels/KeyValueNestedModel.ts +0 -59
  80. package/build/dist/Models/AnalyticsModels/AnalyticsBaseModel/NestedModel.js +0 -7
  81. package/build/dist/Models/AnalyticsModels/AnalyticsBaseModel/NestedModel.js.map +0 -1
  82. package/build/dist/Models/AnalyticsModels/NestedModels/KeyValueNestedModel.js +0 -51
  83. package/build/dist/Models/AnalyticsModels/NestedModels/KeyValueNestedModel.js.map +0 -1
@@ -140,13 +140,6 @@ export default class AnalyticsBaseModel extends CommonModel {
140
140
  this.crudApiPath = data.crudApiPath;
141
141
  this.enableRealtimeEventsOn = data.enableRealtimeEventsOn;
142
142
  this.partitionKey = data.partitionKey;
143
-
144
- // initialize Arrays.
145
- for (const column of this.tableColumns) {
146
- if (column.type === TableColumnType.NestedModel) {
147
- this.setColumnValue(column.key, []);
148
- }
149
- }
150
143
  }
151
144
 
152
145
  private _enableWorkflowOn: EnableWorkflowOn | undefined;
@@ -207,19 +207,6 @@ export default class CommonModel {
207
207
  return;
208
208
  }
209
209
 
210
- if (recordValue instanceof Array) {
211
- if (recordValue.length > 0 && column.nestedModelType) {
212
- json[column.key] = CommonModel.toJSONArray(
213
- recordValue as Array<CommonModel>,
214
- column.nestedModelType,
215
- );
216
- } else {
217
- json[column.key] = recordValue;
218
- }
219
-
220
- return;
221
- }
222
-
223
210
  json[column.key] = recordValue;
224
211
  });
225
212
 
@@ -12,8 +12,8 @@ export default class ExceptionInstance extends AnalyticsBaseModel {
12
12
  super({
13
13
  tableName: "ExceptionItem",
14
14
  tableEngine: AnalyticsTableEngine.MergeTree,
15
- singularName: "Exception",
16
- pluralName: "Exceptions",
15
+ singularName: "Exception Instance",
16
+ pluralName: "Exception Instances",
17
17
  enableRealtimeEventsOn: {
18
18
  create: true,
19
19
  },
@@ -531,7 +531,7 @@ export default class Monitor extends BaseModel {
531
531
  ],
532
532
  })
533
533
  @TableColumn({
534
- type: TableColumnType.JSON,
534
+ type: TableColumnType.MonitorSteps,
535
535
  required: false,
536
536
  title: "Monitor Steps",
537
537
  description: "What would you like to monitor and what is the criteria?",
@@ -53,8 +53,8 @@ import { Column, Entity, Index, JoinColumn, ManyToOne } from "typeorm";
53
53
  })
54
54
  @TableMetadata({
55
55
  tableName: "OnCallDutyPolicyEscalationRuleSchedule",
56
- singularName: "On-Call Duty Escalation Rule Schedule",
57
- pluralName: "On-Call Duty Escalation Rule Schedules",
56
+ singularName: "Schedule's On-Call Duty Escalation Rule",
57
+ pluralName: "Schedule's On-Call Duty Escalation Rules",
58
58
  icon: IconProp.Calendar,
59
59
  tableDescription:
60
60
  "Manage schedules for on-call duty policy escalation rules.",
@@ -53,8 +53,8 @@ import { Column, Entity, Index, JoinColumn, ManyToOne } from "typeorm";
53
53
  })
54
54
  @TableMetadata({
55
55
  tableName: "OnCallDutyPolicyEscalationRuleTeam",
56
- singularName: "On-Call Duty Escalation Rule",
57
- pluralName: "On-Call Duty Escalation Rules",
56
+ singularName: "Team On-Call Duty Escalation Rule",
57
+ pluralName: "Team On-Call Duty Escalation Rules",
58
58
  icon: IconProp.Call,
59
59
  tableDescription:
60
60
  "Manage on-call duty escalation rule for the on-call policy.",
@@ -52,8 +52,8 @@ import { Column, Entity, Index, JoinColumn, ManyToOne } from "typeorm";
52
52
  })
53
53
  @TableMetadata({
54
54
  tableName: "OnCallDutyPolicyEscalationRuleUser",
55
- singularName: "On-Call Duty Escalation Rule",
56
- pluralName: "On-Call Duty Esdcalation Rules",
55
+ singularName: "User's On-Call Duty Escalation Rule",
56
+ pluralName: "User's On-Call Duty Esdcalation Rules",
57
57
  icon: IconProp.Call,
58
58
  tableDescription:
59
59
  "Manage on-call duty escalation rule for the on-call policy.",
@@ -55,8 +55,8 @@ import { PlanType } from "../../Types/Billing/SubscriptionPlan";
55
55
  })
56
56
  @TableMetadata({
57
57
  tableName: "OnCallDutyPolicyTimeLog",
58
- singularName: "User Override",
59
- pluralName: "User Overrides",
58
+ singularName: "On Call Time Log",
59
+ pluralName: "On Call Time Logs",
60
60
  icon: IconProp.Call,
61
61
  tableDescription:
62
62
  "Manage on-call duty user overrides, for example if the user is on leave you can override the on-call duty policy for that user so all the alerts will be routed to the other user.",
@@ -71,7 +71,13 @@ export enum ProbeConnectionStatus {
71
71
  Permission.ProjectMember,
72
72
  Permission.CreateProjectProbe,
73
73
  ],
74
- read: [Permission.Public],
74
+ read: [
75
+ Permission.Public,
76
+ Permission.ProjectOwner,
77
+ Permission.ProjectAdmin,
78
+ Permission.ProjectMember,
79
+ Permission.ReadProjectProbe,
80
+ ],
75
81
  delete: [
76
82
  Permission.ProjectOwner,
77
83
  Permission.ProjectAdmin,
@@ -80,8 +80,8 @@ import {
80
80
  @SlugifyColumn("name", "slug")
81
81
  @TableMetadata({
82
82
  tableName: "ServiceCatalog",
83
- singularName: "Service",
84
- pluralName: "Services",
83
+ singularName: "Service in Service Catalog",
84
+ pluralName: "Services in Service Catalog",
85
85
  icon: IconProp.SquareStack,
86
86
  tableDescription:
87
87
  "Service Catalog is a collection of services that you have in your organization. It can be a collection of services that you are monitoring or services that you are providing to your customers. It can be anything that you want to keep track of.",
@@ -68,8 +68,8 @@ import { Column, Entity, Index, JoinColumn, ManyToOne } from "typeorm";
68
68
  @CrudApiEndpoint(new Route("/service-copilot-code-repository"))
69
69
  @TableMetadata({
70
70
  tableName: "ServiceCopilotCodeRepository",
71
- singularName: "Service",
72
- pluralName: "Services",
71
+ singularName: "Service Code Repository for Copilot",
72
+ pluralName: "Service Code Repositories for Copilot",
73
73
  icon: IconProp.SquareStack,
74
74
  tableDescription:
75
75
  "Add services to your code repository to categorize and manage them easily. This will help copilot understand and generate code.",
@@ -67,7 +67,7 @@ export default class ProjectMiddleware {
67
67
  next: NextFunction,
68
68
  ): Promise<void> {
69
69
  try {
70
- const tenantId: ObjectID | null = this.getProjectId(req);
70
+ let tenantId: ObjectID | null = this.getProjectId(req);
71
71
 
72
72
  const apiKey: ObjectID | null = this.getApiKey(req);
73
73
 
@@ -81,19 +81,27 @@ export default class ProjectMiddleware {
81
81
 
82
82
  let apiKeyModel: ApiKey | null = null;
83
83
 
84
- if (tenantId) {
84
+ if (apiKey) {
85
85
  apiKeyModel = await ApiKeyService.findOneBy({
86
86
  query: {
87
- projectId: tenantId,
88
87
  apiKey: apiKey,
89
88
  expiresAt: QueryHelper.greaterThan(OneUptimeDate.getCurrentDate()),
90
89
  },
91
90
  select: {
92
91
  _id: true,
92
+ projectId: true,
93
93
  },
94
94
  props: { isRoot: true },
95
95
  });
96
96
 
97
+ tenantId = apiKeyModel?.projectId || null;
98
+
99
+ if (!tenantId) {
100
+ throw new BadDataException(
101
+ "Project ID not found for the provided API Key.",
102
+ );
103
+ }
104
+
97
105
  if (apiKeyModel) {
98
106
  (req as OneUptimeRequest).userType = UserType.API;
99
107
  // TODO: Add API key permissions.
@@ -125,18 +125,22 @@ export default class OTelIngestService {
125
125
 
126
126
  const newDbMetric: Metric = Metric.fromJSON(
127
127
  dbMetric.toJSON(),
128
- Metric,
128
+ Metric
129
129
  ) as Metric;
130
130
 
131
- newDbMetric.startTimeUnixNano = datapoint["startTimeUnixNano"] as number;
132
- newDbMetric.startTime = OneUptimeDate.fromUnixNano(
133
- datapoint["startTimeUnixNano"] as number,
134
- );
131
+ if (datapoint["startTimeUnixNano"]) {
132
+ newDbMetric.startTimeUnixNano = datapoint["startTimeUnixNano"] as number;
133
+ newDbMetric.startTime = OneUptimeDate.fromUnixNano(
134
+ datapoint["startTimeUnixNano"] as number
135
+ );
136
+ }
135
137
 
136
- newDbMetric.timeUnixNano = datapoint["timeUnixNano"] as number;
137
- newDbMetric.time = OneUptimeDate.fromUnixNano(
138
- datapoint["timeUnixNano"] as number,
139
- );
138
+ if (datapoint["timeUnixNano"]) {
139
+ newDbMetric.timeUnixNano = datapoint["timeUnixNano"] as number;
140
+ newDbMetric.time = OneUptimeDate.fromUnixNano(
141
+ datapoint["timeUnixNano"] as number
142
+ );
143
+ }
140
144
 
141
145
  if (Object.keys(datapoint).includes("asInt")) {
142
146
  newDbMetric.value = datapoint["asInt"] as number;
@@ -169,7 +169,6 @@ export class Statement implements BaseQueryParams {
169
169
  [TableColumnType.Decimal]: "Double",
170
170
  [TableColumnType.Date]: "DateTime",
171
171
  [TableColumnType.JSON]: "JSON",
172
- [TableColumnType.NestedModel]: "Nested",
173
172
  [TableColumnType.ArrayNumber]: "Array(Int32)",
174
173
  [TableColumnType.ArrayText]: "Array(String)",
175
174
  [TableColumnType.LongNumber]: "Int128",
@@ -53,12 +53,18 @@ export default class StatementGenerator<TBaseModel extends AnalyticsBaseModel> {
53
53
  const whereStatement: Statement = this.toWhereStatement(updateBy.query);
54
54
 
55
55
  /* eslint-disable prettier/prettier */
56
- const statement: Statement = SQL`
57
- ALTER TABLE ${this.database.getDatasourceOptions().database!}.${this.model.tableName
56
+ const statement: Statement = SQL`
57
+ ALTER TABLE ${this.database.getDatasourceOptions().database!}.${
58
+ this.model.tableName
58
59
  }
59
- UPDATE `.append(setStatement).append(SQL`
60
- WHERE TRUE `).append(whereStatement);
61
- /* eslint-enable prettier/prettier */
60
+ UPDATE `
61
+ .append(setStatement)
62
+ .append(
63
+ SQL`
64
+ WHERE TRUE `
65
+ )
66
+ .append(whereStatement);
67
+ /* eslint-enable prettier/prettier */
62
68
 
63
69
  logger.debug(`${this.model.tableName} Update Statement`);
64
70
  logger.debug(statement);
@@ -71,27 +77,7 @@ export default class StatementGenerator<TBaseModel extends AnalyticsBaseModel> {
71
77
  ): Array<string> {
72
78
  const columnNames: Array<string> = [];
73
79
  for (const column of tableColumns) {
74
- if (column.type === TableColumnType.NestedModel) {
75
- // Example of nested model query:
76
-
77
- /**
78
- *
79
- * INSERT INTO opentelemetry_spans (trace_id, span_id, attributes.key, attributes.value) VALUES
80
- ('trace1', 'span1', ['key1', 'key2'], ['value1', 'value2']),
81
- ('trace2', 'span2', ['keyA', 'keyB'], ['valueA', 'valueB']);
82
- */
83
-
84
- // Nested Model Support.
85
- const nestedModelColumnNames: Array<string> = this.getColumnNames(
86
- column.nestedModel!.tableColumns,
87
- );
88
-
89
- for (const nestedModelColumnName of nestedModelColumnNames) {
90
- columnNames.push(`${column.key}.${nestedModelColumnName}`);
91
- }
92
- } else {
93
- columnNames.push(column.key);
94
- }
80
+ columnNames.push(column.key);
95
81
  }
96
82
 
97
83
  return columnNames;
@@ -168,45 +154,12 @@ export default class StatementGenerator<TBaseModel extends AnalyticsBaseModel> {
168
154
  const record: Record = [];
169
155
 
170
156
  for (const column of item.getTableColumns()) {
171
- if (column.type === TableColumnType.NestedModel) {
172
- // Nested Model Support.
173
-
174
- // THis is very werid, but the output should work in a query like this:
175
-
176
- /**
177
- *
178
- * INSERT INTO opentelemetry_spans (trace_id, span_id, attributes.key, attributes.value) VALUES
179
- ('trace1', 'span1', ['key1', 'key2'], ['value1', 'value2']),
180
- ('trace2', 'span2', ['keyA', 'keyB'], ['valueA', 'valueB']);
181
- */
182
-
183
- for (const subColumn of column.nestedModel!.tableColumns) {
184
- const subRecord: Record = [];
185
-
186
- for (const nestedModelItem of item.getColumnValue(
187
- column.key,
188
- ) as Array<CommonModel>) {
189
- const value: RecordValue = this.sanitizeValue(
190
- nestedModelItem.getColumnValue(subColumn.key),
191
- subColumn,
192
- {
193
- isNestedModel: true,
194
- },
195
- );
196
-
197
- subRecord.push(value);
198
- }
199
-
200
- record.push(subRecord);
201
- }
202
- } else {
203
- const value: RecordValue | undefined = this.sanitizeValue(
204
- item.getColumnValue(column.key),
205
- column,
206
- );
157
+ const value: RecordValue | undefined = this.sanitizeValue(
158
+ item.getColumnValue(column.key),
159
+ column,
160
+ );
207
161
 
208
- record.push(value);
209
- }
162
+ record.push(value);
210
163
  }
211
164
 
212
165
  return record;
@@ -625,16 +578,6 @@ export default class StatementGenerator<TBaseModel extends AnalyticsBaseModel> {
625
578
  columns.append(SQL`, `);
626
579
  }
627
580
 
628
- let nestedModelColumns: Statement | null = null;
629
-
630
- if (column.type === TableColumnType.NestedModel) {
631
- nestedModelColumns = SQL`(`
632
- .append(
633
- this.toColumnsCreateStatement(column.nestedModel!.tableColumns),
634
- )
635
- .append(SQL`)`);
636
- }
637
-
638
581
  // special case - ClickHouse does not support using an a query parameter
639
582
  // to specify the column name when creating the table
640
583
  const keyStatement: string = column.key;
@@ -649,10 +592,6 @@ export default class StatementGenerator<TBaseModel extends AnalyticsBaseModel> {
649
592
  .append(this.toColumnType(column.type))
650
593
  .append(SQL`)`),
651
594
  );
652
-
653
- if (nestedModelColumns) {
654
- columns.append(SQL` `).append(nestedModelColumns);
655
- }
656
595
  }
657
596
 
658
597
  return columns;
@@ -672,26 +611,34 @@ export default class StatementGenerator<TBaseModel extends AnalyticsBaseModel> {
672
611
  "Array(String)": TableColumnType.ArrayText,
673
612
  "Array(Int32)": TableColumnType.ArrayNumber,
674
613
  JSON: TableColumnType.JSON, //JSONArray is also JSON
675
- Nested: TableColumnType.NestedModel,
676
614
  Bool: TableColumnType.Boolean,
677
615
  }[clickhouseType];
678
616
  }
679
617
 
680
618
  public toColumnType(type: TableColumnType): Statement {
681
- return {
619
+ const statement: Statement | undefined = {
682
620
  [TableColumnType.Text]: SQL`String`,
683
621
  [TableColumnType.ObjectID]: SQL`String`,
684
622
  [TableColumnType.Boolean]: SQL`Bool`,
685
623
  [TableColumnType.Number]: SQL`Int32`,
686
624
  [TableColumnType.Decimal]: SQL`Double`,
625
+ [TableColumnType.IP]: SQL`String`,
626
+ [TableColumnType.Port]: SQL`String`,
687
627
  [TableColumnType.Date]: SQL`DateTime`,
688
628
  [TableColumnType.JSON]: SQL`String`, // we use JSON as a string because ClickHouse has really good JSON support for string types
689
629
  [TableColumnType.JSONArray]: SQL`String`, // we use JSON as a string because ClickHouse has really good JSON support for string types
690
- [TableColumnType.NestedModel]: SQL`Nested`,
691
630
  [TableColumnType.ArrayNumber]: SQL`Array(Int32)`,
692
631
  [TableColumnType.ArrayText]: SQL`Array(String)`,
693
632
  [TableColumnType.LongNumber]: SQL`Int128`,
694
633
  }[type];
634
+
635
+ if (!statement) {
636
+ throw new BadDataException(
637
+ `Unknown column type: ${type}. Please add support for this column type.`,
638
+ );
639
+ }
640
+
641
+ return statement;
695
642
  }
696
643
 
697
644
  public toDoesColumnExistStatement(columnName: string): string {