Browse Source

feat: template import(in progress)

Signed-off-by: Pranav C <pranavxc@gmail.com>
pull/743/head
Pranav C 3 years ago
parent
commit
4f6b93364f
  1. 44
      packages/nc-gui/components/project/settings/importTemplate.vue
  2. 50
      packages/nc-gui/components/project/settings/xcMeta.vue
  3. 24
      packages/nocodb/src/__tests__/TemplateParser.test.ts
  4. 707
      packages/nocodb/src/__tests__/template.ts
  5. 64
      packages/nocodb/src/lib/noco/meta/NcMetaMgr.ts
  6. 1339
      packages/nocodb/src/lib/sqlUi/MssqlUi.ts
  7. 1282
      packages/nocodb/src/lib/sqlUi/MysqlUi.ts
  8. 947
      packages/nocodb/src/lib/sqlUi/OracleUi.ts
  9. 1970
      packages/nocodb/src/lib/sqlUi/PgUi.ts
  10. 70
      packages/nocodb/src/lib/sqlUi/SqlUiFactory.ts
  11. 1114
      packages/nocodb/src/lib/sqlUi/SqliteUi.ts
  12. 6
      packages/nocodb/src/lib/sqlUi/index.ts
  13. 74
      packages/nocodb/src/lib/templateParser/NcTemplateParser.ts

44
packages/nc-gui/components/project/settings/importTemplate.vue

@ -0,0 +1,44 @@
<template>
<!-- <v-dialog :value="true">-->
<v-card>
<v-textarea v-model="template" />
<v-btn @click="importTemplate">
import
</v-btn>
</v-card>
<!-- </v-dialog>-->
</template>
<script>
export default {
name: 'ImportTemplate',
props: {
nodes: Object
},
data() {
return {
template: ''
}
},
methods: {
importTemplate() {
try {
const template = JSON.parse(this.template)
this.$store.dispatch('sqlMgr/ActSqlOp', [{
dbAlias: this.nodes.dbAlias,
env: '_noco'
}, 'xcModelsCreateFromTemplate', {
template
}])
} catch (e) {
this.$toast.error(e.message).goAway(3000)
}
}
}
}
</script>
<style scoped>
</style>

50
packages/nc-gui/components/project/settings/xcMeta.vue

@ -112,28 +112,28 @@
>
</td>
</tr>
<!-- <tr>-->
<!-- <td>-->
<!-- &lt;!&ndash; Clear all metadata from meta tables. &ndash;&gt;-->
<!-- {{ $t('management.meta.reset.desc') }}-->
<!-- </td>-->
<!-- <td>-->
<!-- <v-btn-->
<!-- :loading="loading === 'reset-metadata'"-->
<!-- min-width="150"-->
<!-- color="error"-->
<!-- small-->
<!-- outlined-->
<!-- @click="resetMeta"-->
<!-- >-->
<!-- <v-icon small>-->
<!-- mdi-delete-variant-->
<!-- </v-icon>&nbsp;-->
<!-- &lt;!&ndash; Reset &ndash;&gt;-->
<!-- {{ $t('management.meta.reset.title') }}-->
<!-- </v-btn>-->
<!-- </td>-->
<!-- </tr>-->
<!-- <tr>-->
<!-- <td>-->
<!-- &lt;!&ndash; Clear all metadata from meta tables. &ndash;&gt;-->
<!-- {{ $t('management.meta.reset.desc') }}-->
<!-- </td>-->
<!-- <td>-->
<!-- <v-btn-->
<!-- :loading="loading === 'reset-metadata'"-->
<!-- min-width="150"-->
<!-- color="error"-->
<!-- small-->
<!-- outlined-->
<!-- @click="resetMeta"-->
<!-- >-->
<!-- <v-icon small>-->
<!-- mdi-delete-variant-->
<!-- </v-icon>&nbsp;-->
<!-- &lt;!&ndash; Reset &ndash;&gt;-->
<!-- {{ $t('management.meta.reset.title') }}-->
<!-- </v-btn>-->
<!-- </td>-->
<!-- </tr>-->
</tbody>
</v-simple-table>
@ -144,15 +144,21 @@
:dialog-show="dialogShow"
:heading="confirmMessage"
/>
<import-template
:nodes="{dbAlias: 'db'}"
/>
</div>
</template>
<script>
import DlgLabelSubmitCancel from '@/components/utils/dlgLabelSubmitCancel'
import ImportTemplate from '~/components/project/settings/importTemplate'
export default {
name: 'XcMeta',
components: {
ImportTemplate,
DlgLabelSubmitCancel
},
data: () => ({

24
packages/nocodb/src/__tests__/TemplateParser.test.ts

@ -0,0 +1,24 @@
import { expect } from 'chai';
import 'mocha';
import NcTemplateParser from '../lib/templateParser/NcTemplateParser';
import template from './template';
describe('Template parser', () => {
// Called once before any of the tests in this block begin.
before(function(done) {
done();
});
after(done => {
done();
});
describe('Parse blog templates', function() {
it('Simple formula', function() {
const parser = new NcTemplateParser('mysql');
const { tables } = parser.parse(template);
expect(tables).length(3);
});
});
});

707
packages/nocodb/src/__tests__/template.ts

@ -0,0 +1,707 @@
export default {
name: 'Project name',
tables: [
{
tn: 'blog',
columns: [
{
cn: 'title',
uidt: 'SingleLineText'
},
{
cn: 'body',
uidt: 'LongText'
}
]
},
{
tn: 'comment',
columns: [
{
cn: 'body',
uidt: 'LongText'
},
{
cn: 'blog_id',
uidt: 'ForeignKey',
rtn: 'blog'
}
]
},
{
tn: 'tag',
columns: [
{
cn: 'title',
uidt: 'SingleLineText'
},
{
cn: 'blog_id',
uidt: 'LinkToAnotherRecord',
rtn: 'blog'
}
]
}
]
};
export const blog = {
tn: 'blog',
_tn: 'blog',
columns: [
{
validate: {
func: [],
args: [],
msg: []
},
cn: 'id',
_cn: 'Id',
type: 'integer',
dt: 'int',
uidt: 'ID',
uip: '',
uicn: '',
dtx: 'integer',
ct: 'int(11)',
nrqd: false,
rqd: true,
ck: false,
pk: true,
un: true,
ai: true,
cdf: null,
clen: null,
np: 11,
ns: 0,
dtxp: '11',
dtxs: '',
tn: 'blog'
},
{
validate: {
func: [],
args: [],
msg: []
},
cn: 'title',
_cn: 'Title',
type: 'string',
dt: 'varchar',
uidt: 'SingleLineText',
uip: '',
uicn: '',
dtx: 'specificType',
ct: 'varchar(45)',
nrqd: true,
rqd: false,
ck: false,
pk: false,
un: false,
ai: false,
cdf: null,
clen: 45,
np: null,
ns: null,
dtxp: '45',
dtxs: '',
pv: true,
alias: 'Title'
},
{
validate: {
func: [],
args: [],
msg: []
},
cn: 'created_at',
_cn: 'CreatedAt',
type: 'timestamp',
dt: 'timestamp',
uidt: 'CreateTime',
uip: '',
uicn: '',
dtx: 'specificType',
ct: 'varchar(45)',
nrqd: true,
rqd: false,
ck: false,
pk: false,
un: false,
ai: false,
cdf: 'CURRENT_TIMESTAMP',
clen: 45,
np: null,
ns: null,
dtxp: '',
dtxs: '',
default: 'CURRENT_TIMESTAMP',
columnDefault: 'CURRENT_TIMESTAMP'
},
{
validate: {
func: [],
args: [],
msg: []
},
cn: 'updated_at',
_cn: 'UpdatedAt',
type: 'timestamp',
dt: 'timestamp',
uidt: 'LastModifiedTime',
uip: '',
uicn: '',
dtx: 'specificType',
ct: 'varchar(45)',
nrqd: true,
rqd: false,
ck: false,
pk: false,
un: false,
ai: false,
cdf: 'CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP',
clen: 45,
np: null,
ns: null,
dtxp: '',
dtxs: '',
default: 'CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP',
columnDefault: 'CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP'
},
{
validate: {
func: [],
args: [],
msg: []
},
cn: 'body',
_cn: 'body',
type: 'text',
dt: 'text',
uidt: 'LongText',
uip: '',
uicn: '',
dtx: 'specificType',
ct: 'integer(11)',
nrqd: true,
rqd: false,
ck: false,
pk: false,
un: false,
ai: false,
cdf: null,
clen: 45,
np: null,
ns: null,
dtxp: '',
dtxs: ' ',
cno: 'title5',
tn: 'blog',
alias: 'body'
}
],
pks: [],
hasMany: [
{
id: 3,
project_id: 'worrying_sloth_jum4',
db_alias: 'db',
tn: '_nc_m2m_tag_blog',
rtn: 'blog',
_tn: 'm2mtag_blog',
_rtn: 'blog',
cn: 'blog_c_id',
rcn: 'id',
_cn: null,
_rcn: null,
referenced_db_alias: null,
type: 'real',
db_type: 'mysql2',
ur: 'NO ACTION',
dr: 'NO ACTION',
created_at: '2021-10-29 07:28:12',
updated_at: '2021-10-29 07:28:12',
fkn: 'tag_blo_Dneo90_c_fk',
enabled: true
},
{
id: 1,
project_id: 'worrying_sloth_jum4',
db_alias: 'db',
tn: 'comment',
rtn: 'blog',
_tn: 'comment',
_rtn: 'blog',
cn: 'title5',
rcn: 'id',
_cn: null,
_rcn: null,
referenced_db_alias: null,
type: 'real',
db_type: 'mysql2',
ur: 'NO ACTION',
dr: 'NO ACTION',
created_at: '2021-10-29 07:27:54',
updated_at: '2021-10-29 07:27:54',
fkn: null,
enabled: true
}
],
belongsTo: [],
type: 'table',
v: [
{
hm: {
id: 1,
project_id: 'worrying_sloth_jum4',
db_alias: 'db',
tn: 'comment',
rtn: 'blog',
_tn: 'comment',
_rtn: 'blog',
cn: 'title5',
rcn: 'id',
_cn: null,
_rcn: null,
referenced_db_alias: null,
type: 'real',
db_type: 'mysql2',
ur: 'NO ACTION',
dr: 'NO ACTION',
created_at: '2021-10-29 07:27:54',
updated_at: '2021-10-29 07:27:54',
fkn: null,
enabled: true
},
_cn: 'blog => comment'
},
{
mm: {
tn: 'blog',
cn: 'id',
vtn: '_nc_m2m_tag_blog',
vcn: 'blog_c_id',
vrcn: 'tag_p_id',
rtn: 'tag',
rcn: 'id',
_tn: 'blog',
_cn: null,
_rtn: 'tag',
_rcn: null
},
_cn: 'blog <=> tag'
}
],
manyToMany: [
{
tn: 'blog',
cn: 'id',
vtn: '_nc_m2m_tag_blog',
vcn: 'blog_c_id',
vrcn: 'tag_p_id',
rtn: 'tag',
rcn: 'id',
_tn: 'blog',
_cn: null,
_rtn: 'tag',
_rcn: null
}
]
};
export const comment = {
tn: 'comment',
_tn: 'comment',
columns: [
{
validate: {
func: [],
args: [],
msg: []
},
cn: 'id',
_cn: 'Id',
type: 'integer',
dt: 'int',
uidt: 'ID',
uip: '',
uicn: '',
dtx: 'integer',
ct: 'int(11)',
nrqd: false,
rqd: true,
ck: false,
pk: true,
un: true,
ai: true,
cdf: null,
clen: null,
np: 11,
ns: 0,
dtxp: '11',
dtxs: '',
tn: 'comment'
},
{
validate: {
func: [],
args: [],
msg: []
},
cn: 'created_at',
_cn: 'CreatedAt',
type: 'timestamp',
dt: 'timestamp',
uidt: 'CreateTime',
uip: '',
uicn: '',
dtx: 'specificType',
ct: 'varchar(45)',
nrqd: true,
rqd: false,
ck: false,
pk: false,
un: false,
ai: false,
cdf: 'CURRENT_TIMESTAMP',
clen: 45,
np: null,
ns: null,
dtxp: '',
dtxs: '',
default: 'CURRENT_TIMESTAMP',
columnDefault: 'CURRENT_TIMESTAMP',
pv: true
},
{
validate: {
func: [],
args: [],
msg: []
},
cn: 'updated_at',
_cn: 'UpdatedAt',
type: 'timestamp',
dt: 'timestamp',
uidt: 'LastModifiedTime',
uip: '',
uicn: '',
dtx: 'specificType',
ct: 'varchar(45)',
nrqd: true,
rqd: false,
ck: false,
pk: false,
un: false,
ai: false,
cdf: 'CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP',
clen: 45,
np: null,
ns: null,
dtxp: '',
dtxs: '',
default: 'CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP',
columnDefault: 'CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP'
},
{
validate: {
func: [],
args: [],
msg: []
},
cn: 'body',
_cn: 'body',
type: 'text',
dt: 'text',
uidt: 'LongText',
uip: '',
uicn: '',
dtx: 'specificType',
ct: 'integer(11)',
nrqd: true,
rqd: false,
ck: false,
pk: false,
un: false,
ai: false,
cdf: null,
clen: 45,
np: null,
ns: null,
dtxp: '',
dtxs: ' ',
cno: 'title4',
tn: 'comment',
alias: 'body'
},
{
validate: {
func: [],
args: [],
msg: []
},
cn: 'title5',
_cn: 'title5',
type: 'integer',
dt: 'int',
uidt: 'ForeignKey',
uip: '',
uicn: '',
dtx: 'specificType',
ct: 'integer(11)',
nrqd: true,
rqd: false,
ck: false,
pk: false,
un: true,
ai: false,
cdf: null,
clen: 45,
np: null,
ns: null,
dtxp: '11',
dtxs: '',
cno: 'title5',
tn: 'comment'
}
],
pks: [],
hasMany: [],
belongsTo: [
{
id: 1,
project_id: 'worrying_sloth_jum4',
db_alias: 'db',
tn: 'comment',
rtn: 'blog',
_tn: 'comment',
_rtn: 'blog',
cn: 'title5',
rcn: 'id',
_cn: null,
_rcn: null,
referenced_db_alias: null,
type: 'real',
db_type: 'mysql2',
ur: 'NO ACTION',
dr: 'NO ACTION',
created_at: '2021-10-29 07:27:54',
updated_at: '2021-10-29 07:27:54',
fkn: null,
enabled: true
}
],
type: 'table',
v: [
{
bt: {
id: 1,
project_id: 'worrying_sloth_jum4',
db_alias: 'db',
tn: 'comment',
rtn: 'blog',
_tn: 'comment',
_rtn: 'blog',
cn: 'title5',
rcn: 'id',
_cn: null,
_rcn: null,
referenced_db_alias: null,
type: 'real',
db_type: 'mysql2',
ur: 'NO ACTION',
dr: 'NO ACTION',
created_at: '2021-10-29 07:27:54',
updated_at: '2021-10-29 07:27:54',
fkn: null,
enabled: true
},
_cn: 'blog <= comment'
}
]
};
export const tag = {
tn: 'tag',
_tn: 'tag',
columns: [
{
validate: {
func: [],
args: [],
msg: []
},
cn: 'id',
_cn: 'Id',
type: 'integer',
dt: 'int',
uidt: 'ID',
uip: '',
uicn: '',
dtx: 'integer',
ct: 'int(11)',
nrqd: false,
rqd: true,
ck: false,
pk: true,
un: true,
ai: true,
cdf: null,
clen: null,
np: 11,
ns: 0,
dtxp: '11',
dtxs: ''
},
{
validate: {
func: [],
args: [],
msg: []
},
cn: 'title',
_cn: 'Title',
type: 'string',
dt: 'varchar',
uidt: 'SingleLineText',
uip: '',
uicn: '',
dtx: 'specificType',
ct: 'varchar(45)',
nrqd: true,
rqd: false,
ck: false,
pk: false,
un: false,
ai: false,
cdf: null,
clen: 45,
np: null,
ns: null,
dtxp: '45',
dtxs: '',
pv: true,
alias: 'Title'
},
{
validate: {
func: [],
args: [],
msg: []
},
cn: 'created_at',
_cn: 'CreatedAt',
type: 'timestamp',
dt: 'timestamp',
uidt: 'CreateTime',
uip: '',
uicn: '',
dtx: 'specificType',
ct: 'varchar(45)',
nrqd: true,
rqd: false,
ck: false,
pk: false,
un: false,
ai: false,
cdf: 'CURRENT_TIMESTAMP',
clen: 45,
np: null,
ns: null,
dtxp: '',
dtxs: '',
default: 'CURRENT_TIMESTAMP',
columnDefault: 'CURRENT_TIMESTAMP'
},
{
validate: {
func: [],
args: [],
msg: []
},
cn: 'updated_at',
_cn: 'UpdatedAt',
type: 'timestamp',
dt: 'timestamp',
uidt: 'LastModifiedTime',
uip: '',
uicn: '',
dtx: 'specificType',
ct: 'varchar(45)',
nrqd: true,
rqd: false,
ck: false,
pk: false,
un: false,
ai: false,
cdf: 'CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP',
clen: 45,
np: null,
ns: null,
dtxp: '',
dtxs: '',
default: 'CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP',
columnDefault: 'CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP'
}
],
pks: [],
hasMany: [
{
id: 2,
project_id: 'worrying_sloth_jum4',
db_alias: 'db',
tn: '_nc_m2m_tag_blog',
rtn: 'tag',
_tn: 'm2mtag_blog',
_rtn: 'tag',
cn: 'tag_p_id',
rcn: 'id',
_cn: null,
_rcn: null,
referenced_db_alias: null,
type: 'real',
db_type: 'mysql2',
ur: 'NO ACTION',
dr: 'NO ACTION',
created_at: '2021-10-29 07:28:11',
updated_at: '2021-10-29 07:28:11',
fkn: 'tag_blo_rKb7Gq_p_fk',
enabled: true
}
],
belongsTo: [],
type: 'table',
v: [
{
mm: {
tn: 'tag',
cn: 'id',
vtn: '_nc_m2m_tag_blog',
vcn: 'tag_p_id',
vrcn: 'blog_c_id',
rtn: 'blog',
rcn: 'id',
_tn: 'tag',
_cn: null,
_rtn: 'blog',
_rcn: null
},
_cn: 'tag <=> blog'
}
],
manyToMany: [
{
tn: 'tag',
cn: 'id',
vtn: '_nc_m2m_tag_blog',
vcn: 'tag_p_id',
vrcn: 'blog_c_id',
rtn: 'blog',
rcn: 'id',
_tn: 'tag',
_cn: null,
_rtn: 'blog',
_rcn: null
}
]
};

64
packages/nocodb/src/lib/noco/meta/NcMetaMgr.ts

@ -37,6 +37,7 @@ import RestAuthCtrl from '../rest/RestAuthCtrlEE';
import { packageVersion } from 'nc-help';
import NcMetaIO, { META_TABLES } from './NcMetaIO';
import { promisify } from 'util';
import NcTemplateParser from '../../templateParser/NcTemplateParser';
const XC_PLUGIN_DET = 'XC_PLUGIN_DET';
@ -1429,6 +1430,10 @@ export default class NcMetaMgr {
result = await this.xcExportAsCsv(args, req, res);
break;
case 'xcModelsCreateFromTemplate':
result = await this.xcModelsCreateFromTemplate(args, req);
break;
case 'xcVisibilityMetaSet':
result = await this.xcVisibilityMetaSet(args);
break;
@ -3999,6 +4004,65 @@ export default class NcMetaMgr {
return { data: { list: procedures } };
}
protected async xcModelsCreateFromTemplate(args, req) {
const template = args.args.template;
const projectId = this.getProjectId(args);
const dbAlias = this.getDbAlias(args);
const projectConfig = this.projectConfigs[projectId];
const connectionConfig = projectConfig.envs?.['_noco']?.db?.find(
d => d?.meta?.dbAlias === dbAlias
);
const { tables } = new NcTemplateParser(connectionConfig?.client).parse(
template
);
for (const table of tables) {
console.log(table);
// create table and trigger listener
const out = await this.projectMgr
.getSqlMgr({ id: projectId })
.handleRequest('tableCreate', {
...args,
args: table
});
if (this.listener) {
await this.listener({
req: {
...args,
args: table,
api: 'tableCreate'
},
res: out,
user: req.user,
ctx: {
req
}
});
}
// create table
}
// iterate over tables
// iterate over tables
// map column datatypes
// group relations
// create tables
// create relations
//
}
protected async xcExportAsCsv(args, _req, res: express.Response) {
const projectId = this.getProjectId(args);
const dbAlias = this.getDbAlias(args);

1339
packages/nocodb/src/lib/sqlUi/MssqlUi.ts

File diff suppressed because it is too large Load Diff

1282
packages/nocodb/src/lib/sqlUi/MysqlUi.ts

File diff suppressed because it is too large Load Diff

947
packages/nocodb/src/lib/sqlUi/OracleUi.ts

@ -0,0 +1,947 @@
export class OracleUi {
static getNewTableColumns(): any[] {
return [
{
cn: 'id',
dt: 'integer',
dtx: 'integer',
ct: 'int(11)',
nrqd: false,
rqd: true,
ck: false,
pk: true,
un: false,
ai: false,
cdf: null,
clen: null,
np: null,
ns: null,
dtxp: '',
dtxs: '',
altered: 1,
uidt: 'ID',
uip: '',
uicn: ''
},
{
cn: 'title',
dt: 'varchar',
dtx: 'specificType',
ct: 'varchar(45)',
nrqd: true,
rqd: false,
ck: false,
pk: false,
un: false,
ai: false,
cdf: null,
clen: 45,
np: null,
ns: null,
dtxp: '45',
dtxs: '',
altered: 1,
uidt: 'SingleLineText',
uip: '',
uicn: ''
}
// {
// cn: "created_at",
// dt: "timestamp",
// dtx: "specificType",
// ct: "varchar(45)",
// nrqd: true,
// rqd: false,
// ck: false,
// pk: false,
// un: false,
// ai: false,
// cdf: 'CURRENT_TIMESTAMP',
// clen: 45,
// np: null,
// ns: null,
// dtxp: '',
// dtxs: ''
// },
// {
// cn: "updated_at",
// dt: "timestamp",
// dtx: "specificType",
// ct: "varchar(45)",
// nrqd: true,
// rqd: false,
// ck: false,
// pk: false,
// un: false,
// ai: false,
// cdf: 'CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP',
// clen: 45,
// np: null,
// ns: null,
// dtxp: '',
// dtxs: ''
// }
];
}
static getNewColumn(suffix) {
return {
cn: 'title' + suffix,
dt: 'integer',
dtx: 'specificType',
ct: 'integer(11)',
nrqd: true,
rqd: false,
ck: false,
pk: false,
un: false,
ai: false,
cdf: null,
clen: 45,
np: null,
ns: null,
// data_type_x_specific: ' ',
dtxp: '11',
dtxs: ' ',
altered: 1,
uidt: 'Number',
uip: '',
uicn: ''
};
}
// static getDefaultLengthForDatatype(type) {
// switch (type) {
// case "int":
// return 11;
// break;
// case "tinyint":
// return 1;
// break;
// case "smallint":
// return 5;
// break;
//
// case "mediumint":
// return 9;
// break;
// case "bigint":
// return 20;
// break;
// case "bit":
// return 64;
// break;
// case "boolean":
// return '';
// break;
// case "float":
// return 12;
// break;
// case "decimal":
// return 10;
// break;
// case "double":
// return 22;
// break;
// case "serial":
// return 20;
// break;
// case "date":
// return '';
// break;
// case "datetime":
// case "timestamp":
// return 6;
// break;
// case "time":
// return '';
// break;
// case "year":
// return '';
// break;
// case "char":
// return 255;
// break;
// case "varchar":
// return 45;
// break;
// case "nchar":
// return 255;
// break;
// case "text":
// return '';
// break;
// case "tinytext":
// return '';
// break;
// case "mediumtext":
// return '';
// break;
// case "longtext":
// return ''
// break;
// case "binary":
// return 255;
// break;
// case "varbinary":
// return 65500;
// break;
// case "blob":
// return '';
// break;
// case "tinyblob":
// return '';
// break;
// case "mediumblob":
// return '';
// break;
// case "longblob":
// return '';
// break;
// case "enum":
// return '\'a\',\'b\'';
// break;
// case "set":
// return '\'a\',\'b\'';
// break;
// case "geometry":
// return '';
// case "point":
// return '';
// case "linestring":
// return '';
// case "polygon":
// return '';
// case "multipoint":
// return '';
// case "multilinestring":
// return '';
// case "multipolygon":
// return '';
// case "json":
// return ''
// break;
//
// }
//
// }
static getDefaultLengthForDatatype(type) {
switch (type) {
default:
return '';
}
}
static getDefaultLengthIsDisabled(type): any {
switch (type) {
case 'integer':
return true;
case 'bfile':
case 'binary rowid':
case 'binary double':
case 'binary_float':
case 'blob':
case 'canoical':
case 'cfile':
case 'char':
case 'clob':
case 'content pointer':
case 'contigous array':
case 'date':
case 'decimal':
case 'double precision':
case 'float':
case 'interval day to second':
case 'interval year to month':
case 'lob pointer':
case 'long':
case 'long raw':
case 'named collection':
case 'named object':
case 'nchar':
case 'nclob':
case 'number':
case 'nvarchar2':
case 'octet':
case 'oid':
case 'pointer':
case 'raw':
case 'real':
case 'ref':
case 'ref cursor':
case 'rowid':
case 'signed binary integer':
case 'smallint':
case 'table':
case 'time':
case 'time with tz':
case 'timestamp':
case 'timestamp with local time zone':
case 'timestamp with local tz':
case 'timestamp with timezone':
case 'timestamp with tz':
case 'unsigned binary integer':
case 'urowid':
case 'varchar':
case 'varchar2':
case 'varray':
case 'varying array':
return false;
}
}
static getDefaultValueForDatatype(type) {
switch (type) {
default:
return '';
}
}
static getDefaultScaleForDatatype(type): any {
switch (type) {
case 'integer':
case 'bfile':
case 'binary rowid':
case 'binary double':
case 'binary_float':
case 'blob':
case 'canoical':
case 'cfile':
case 'char':
case 'clob':
case 'content pointer':
case 'contigous array':
case 'date':
case 'decimal':
case 'double precision':
case 'float':
case 'interval day to second':
case 'interval year to month':
case 'lob pointer':
case 'long':
case 'long raw':
case 'named collection':
case 'named object':
case 'nchar':
case 'nclob':
case 'number':
case 'nvarchar2':
case 'octet':
case 'oid':
case 'pointer':
case 'raw':
case 'real':
case 'ref':
case 'ref cursor':
case 'rowid':
case 'signed binary integer':
case 'smallint':
case 'table':
case 'time':
case 'time with tz':
case 'timestamp':
case 'timestamp with local time zone':
case 'timestamp with local tz':
case 'timestamp with timezone':
case 'timestamp with tz':
case 'unsigned binary integer':
case 'urowid':
case 'varchar':
case 'varchar2':
case 'varray':
case 'varying array':
return ' ';
}
}
static colPropAIDisabled(col, columns) {
// console.log(col);
if (
col.dt === 'int4' ||
col.dt === 'integer' ||
col.dt === 'bigint' ||
col.dt === 'smallint'
) {
for (let i = 0; i < columns.length; ++i) {
if (columns[i].cn !== col.cn && columns[i].ai) {
return true;
}
}
return false;
} else {
return true;
}
}
static colPropUNDisabled(_col) {
// console.log(col);
return true;
// if (col.dt === 'int' ||
// col.dt === 'tinyint' ||
// col.dt === 'smallint' ||
// col.dt === 'mediumint' ||
// col.dt === 'bigint') {
// return false;
// } else {
// return true;
// }
}
static onCheckboxChangeAI(col) {
console.log(col);
if (
col.dt === 'int' ||
col.dt === 'bigint' ||
col.dt === 'smallint' ||
col.dt === 'tinyint'
) {
col.altered = col.altered || 2;
}
// if (!col.ai) {
// col.dtx = 'specificType'
// } else {
// col.dtx = ''
// }
}
static showScale(_columnObj) {
return false;
}
static removeUnsigned(columns) {
for (let i = 0; i < columns.length; ++i) {
if (
columns[i].altered === 1 &&
!(
columns[i].dt === 'int' ||
columns[i].dt === 'bigint' ||
columns[i].dt === 'tinyint' ||
columns[i].dt === 'smallint' ||
columns[i].dt === 'mediumint'
)
) {
columns[i].un = false;
console.log('>> resetting unsigned value', columns[i].cn);
}
console.log(columns[i].cn);
}
}
static columnEditable(colObj) {
return colObj.tn !== '_evolutions' || colObj.tn !== 'nc_evolutions';
}
static extractFunctionName(query) {
const reg = /^\s*CREATE\s+(?:OR\s+REPLACE\s*)?\s*FUNCTION\s+(?:[\w\d_]+\.)?([\w_\d]+)/i;
const match = query.match(reg);
return match && match[1];
}
static extractProcedureName(query) {
const reg = /^\s*CREATE\s+(?:OR\s+REPLACE\s*)?\s*PROCEDURE\s+(?:[\w\d_]+\.)?([\w_\d]+)/i;
const match = query.match(reg);
return match && match[1];
}
static splitQueries(query) {
/***
* we are splitting based on semicolon
* there are mechanism to escape semicolon within single/double quotes(string)
*/
return query.match(/\b("[^"]*;[^"]*"|'[^']*;[^']*'|[^;])*;/g);
}
static onCheckboxChangeAU(col) {
console.log(col);
// if (1) {
col.altered = col.altered || 2;
// }
// if (!col.ai) {
// col.dtx = 'specificType'
// } else {
// col.dtx = ''
// }
}
/**
* if sql statement is SELECT - it limits to a number
* @param args
* @returns {string|*}
*/
sanitiseQuery(args) {
let q = args.query.trim().split(';');
if (q[0].startsWith('Select')) {
q = q[0] + ` LIMIT 0,${args.limit ? args.limit : 100};`;
} else if (q[0].startsWith('select')) {
q = q[0] + ` LIMIT 0,${args.limit ? args.limit : 100};`;
} else if (q[0].startsWith('SELECT')) {
q = q[0] + ` LIMIT 0,${args.limit ? args.limit : 100};`;
} else {
return args.query;
}
return q;
}
getColumnsFromJson(json, tn) {
const columns = [];
try {
if (typeof json === 'object' && !Array.isArray(json)) {
const keys = Object.keys(json);
for (let i = 0; i < keys.length; ++i) {
switch (typeof json[keys[i]]) {
case 'number':
if (Number.isInteger(json[keys[i]])) {
columns.push({
dp: null,
tn,
cn: keys[i],
cno: keys[i],
dt: 'int',
np: 10,
ns: 0,
clen: null,
cop: 1,
pk: false,
nrqd: false,
rqd: false,
un: false,
ct: 'int(11) unsigned',
ai: false,
unique: false,
cdf: null,
cc: '',
csn: null,
dtx: 'specificType',
dtxp: '11',
dtxs: 0,
altered: 1
});
} else {
columns.push({
dp: null,
tn,
cn: keys[i],
cno: keys[i],
dt: 'float',
np: 10,
ns: 2,
clen: null,
cop: 1,
pk: false,
nrqd: false,
rqd: false,
un: false,
ct: 'int(11) unsigned',
ai: false,
unique: false,
cdf: null,
cc: '',
csn: null,
dtx: 'specificType',
dtxp: '11',
dtxs: 2,
altered: 1
});
}
break;
case 'string':
if (json[keys[i]].length <= 255) {
columns.push({
dp: null,
tn,
cn: keys[i],
cno: keys[i],
dt: 'varchar',
np: 45,
ns: 0,
clen: null,
cop: 1,
pk: false,
nrqd: false,
rqd: false,
un: false,
ct: 'int(11) unsigned',
ai: false,
unique: false,
cdf: null,
cc: '',
csn: null,
dtx: 'specificType',
dtxp: '45',
dtxs: 0,
altered: 1
});
} else {
columns.push({
dp: null,
tn,
cn: keys[i],
cno: keys[i],
dt: 'text',
np: null,
ns: 0,
clen: null,
cop: 1,
pk: false,
nrqd: false,
rqd: false,
un: false,
ct: 'int(11) unsigned',
ai: false,
unique: false,
cdf: null,
cc: '',
csn: null,
dtx: 'specificType',
dtxp: null,
dtxs: 0,
altered: 1
});
}
break;
case 'boolean':
columns.push({
dp: null,
tn,
cn: keys[i],
cno: keys[i],
dt: 'boolean',
np: 3,
ns: 0,
clen: null,
cop: 1,
pk: false,
nrqd: false,
rqd: false,
un: false,
ct: 'int(11) unsigned',
ai: false,
unique: false,
cdf: null,
cc: '',
csn: null,
dtx: 'specificType',
dtxp: '1',
dtxs: 0,
altered: 1
});
break;
case 'object':
columns.push({
dp: null,
tn,
cn: keys[i],
cno: keys[i],
dt: 'json',
np: 3,
ns: 0,
clen: null,
cop: 1,
pk: false,
nrqd: false,
rqd: false,
un: false,
ct: 'int(11) unsigned',
ai: false,
unique: false,
cdf: null,
cc: '',
csn: null,
dtx: 'specificType',
dtxp: null,
dtxs: 0,
altered: 1
});
break;
default:
break;
}
}
}
} catch (e) {
console.log('Error in getColumnsFromJson', e);
}
return columns;
}
static colPropAuDisabled(_col) {
return true;
}
static getAbstractType(col): any {
switch ((col.dt || col.dt).toLowerCase()) {
case 'integer':
return 'integer';
case 'bfile':
case 'binary rowid':
case 'binary double':
case 'binary_float':
return 'string';
case 'blob':
return 'blob';
case 'canoical':
case 'cfile':
case 'char':
case 'clob':
case 'content pointer':
case 'contigous array':
return 'string';
case 'date':
return 'date';
case 'decimal':
case 'double precision':
case 'float':
return 'float';
case 'interval day to second':
case 'interval year to month':
return 'string';
case 'lob pointer':
return 'string';
case 'long':
return 'integer';
case 'long raw':
return 'string';
case 'named collection':
case 'named object':
case 'nchar':
case 'nclob':
return 'string';
case 'nvarchar2':
case 'octet':
case 'oid':
case 'pointer':
case 'raw':
return 'string';
case 'real':
case 'number':
return 'float';
case 'ref':
case 'ref cursor':
case 'rowid':
case 'signed binary integer':
return 'string';
case 'smallint':
return 'integer';
case 'table':
return 'string';
case 'time':
case 'time with tz':
return 'time';
case 'timestamp':
case 'timestamp with local time zone':
case 'timestamp with local tz':
case 'timestamp with timezone':
case 'timestamp with tz':
return 'datetime';
case 'unsigned binary integer':
case 'urowid':
case 'varchar':
case 'varchar2':
return 'string';
case 'varray':
case 'varying array':
return 'string';
}
}
static getUIType(col): any {
switch (this.getAbstractType(col)) {
case 'integer':
return 'Number';
case 'boolean':
return 'Checkbox';
case 'float':
return 'Decimal';
case 'date':
return 'Date';
case 'datetime':
return 'CreateTime';
case 'time':
return 'Time';
case 'year':
return 'Year';
case 'string':
return 'SingleLineText';
case 'text':
return 'LongText';
case 'blob':
return 'Attachment';
case 'enum':
return 'SingleSelect';
case 'set':
return 'MultiSelect';
case 'json':
return 'LongText';
}
}
static getDataTypeForUiType(col) {
const colProp: any = {};
switch (col.uidt) {
case 'ID':
colProp.dt = 'integer';
colProp.pk = true;
colProp.un = true;
colProp.ai = true;
colProp.rqd = true;
break;
case 'ForeignKey':
colProp.dt = 'varchar';
break;
case 'SingleLineText':
colProp.dt = 'varchar';
break;
case 'LongText':
colProp.dt = 'clob';
break;
case 'Attachment':
colProp.dt = 'clob';
break;
case 'Checkbox':
colProp.dt = 'tinyint';
colProp.dtxp = 1;
break;
case 'MultiSelect':
colProp.dt = 'varchar2';
break;
case 'SingleSelect':
colProp.dt = 'varchar2';
break;
case 'Collaborator':
colProp.dt = 'varchar';
break;
case 'Date':
colProp.dt = 'varchar';
break;
case 'Year':
colProp.dt = 'year';
break;
case 'Time':
colProp.dt = 'time';
break;
case 'PhoneNumber':
colProp.dt = 'varchar';
colProp.validate = {
func: ['isMobilePhone'],
args: [''],
msg: ['Validation failed : isMobilePhone']
};
break;
case 'Email':
colProp.dt = 'varchar';
colProp.validate = {
func: ['isEmail'],
args: [''],
msg: ['Validation failed : isEmail']
};
break;
case 'URL':
colProp.dt = 'varchar';
colProp.validate = {
func: ['isURL'],
args: [''],
msg: ['Validation failed : isURL']
};
break;
case 'Number':
colProp.dt = 'integer';
break;
case 'Decimal':
colProp.dt = 'decimal';
break;
case 'Currency':
colProp.dt = 'decimal';
colProp.validate = {
func: ['isCurrency'],
args: [''],
msg: ['Validation failed : isCurrency']
};
break;
case 'Percent':
colProp.dt = 'double';
break;
case 'Duration':
colProp.dt = 'integer';
break;
case 'Rating':
colProp.dt = 'float';
break;
case 'Formula':
colProp.dt = 'varchar';
break;
case 'Rollup':
colProp.dt = 'varchar';
break;
case 'Count':
colProp.dt = 'integer';
break;
case 'Lookup':
colProp.dt = 'varchar';
break;
case 'DateTime':
colProp.dt = 'timestamp';
break;
case 'CreateTime':
colProp.dt = 'timestamp';
break;
case 'LastModifiedTime':
colProp.dt = 'timestamp';
break;
case 'AutoNumber':
colProp.dt = 'integer';
break;
case 'Barcode':
colProp.dt = 'varchar';
break;
case 'Button':
colProp.dt = 'varchar';
break;
default:
colProp.dt = 'varchar';
break;
}
return colProp;
}
static getUnsupportedFnList() {
return [];
}
}
// module.exports = PgUiHelp;
/**
* @copyright Copyright (c) 2021, Xgene Cloud Ltd
*
* @author Naveen MR <oof1lab@gmail.com>
* @author Pranav C Balan <pranavxc@gmail.com>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

1970
packages/nocodb/src/lib/sqlUi/PgUi.ts

File diff suppressed because it is too large Load Diff

70
packages/nocodb/src/lib/sqlUi/SqlUiFactory.ts

@ -0,0 +1,70 @@
import { MysqlUi } from './MysqlUi';
import { PgUi } from './PgUi';
import { MssqlUi } from './MssqlUi';
import { OracleUi } from './OracleUi';
import { SqliteUi } from './SqliteUi';
// import {YugabyteUi} from "./YugabyteUi";
// import {TidbUi} from "./TidbUi";
// import {VitessUi} from "./VitessUi";
export class SqlUiFactory {
static create(connectionConfig) {
// connectionConfig.meta = connectionConfig.meta || {};
// connectionConfig.meta.dbtype = connectionConfig.meta.dbtype || "";
if (
connectionConfig.client === 'mysql' ||
connectionConfig.client === 'mysql2'
) {
// if (connectionConfig.meta.dbtype === "tidb")
// return Tidb;
// if (connectionConfig.meta.dbtype === "vitess")
// return Vitess;
console.log('- - - -In Mysql UI');
return MysqlUi;
}
if (connectionConfig.client === 'sqlite3') {
return SqliteUi;
}
if (connectionConfig.client === 'mssql') {
return MssqlUi;
}
if (connectionConfig.client === 'oracledb') {
return OracleUi;
}
if (connectionConfig.client === 'pg') {
// if (connectionConfig.meta.dbtype === "yugabyte")
// return Yugabyte;
return PgUi;
}
throw new Error('Database not supported');
}
}
/**
* @copyright Copyright (c) 2021, Xgene Cloud Ltd
*
* @author Naveen MR <oof1lab@gmail.com>
* @author Pranav C Balan <pranavxc@gmail.com>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

1114
packages/nocodb/src/lib/sqlUi/SqliteUi.ts

File diff suppressed because it is too large Load Diff

6
packages/nocodb/src/lib/sqlUi/index.ts

@ -0,0 +1,6 @@
export * from './MysqlUi';
export * from './PgUi';
export * from './MssqlUi';
export * from './OracleUi';
export * from './SqliteUi';
export * from './SqlUiFactory';

74
packages/nocodb/src/lib/templateParser/NcTemplateParser.ts

@ -0,0 +1,74 @@
import {
MssqlUi,
MysqlUi,
OracleUi,
PgUi,
SqliteUi,
SqlUiFactory
} from '../sqlUi';
export default class NcTemplateParser {
sqlUi:
| typeof MysqlUi
| typeof MssqlUi
| typeof PgUi
| typeof OracleUi
| typeof SqliteUi;
constructor(client) {
this.sqlUi = SqlUiFactory.create({ client });
}
public parse(template: any): any {
const tables = [];
for (const tableTemplate of template.tables) {
const table = this.extractTable(tableTemplate);
tables.push(table);
}
return { tables };
}
private extractTable(tableTemplate) {
if (!tableTemplate?.tn) {
throw Error('Missing table name in template');
}
const defaultColumns = this.sqlUi
.getNewTableColumns()
.filter(
column =>
column.cn !== 'title' &&
(column.uidt !== 'ID' ||
tableTemplate.columns.every(c => c.uidt !== 'ID'))
);
return {
tn: tableTemplate.tn,
columns: [
...defaultColumns,
...this.extractTableColumns(tableTemplate.columns)
]
};
}
private extractTableColumns(tableColumns: any[]) {
const columns = [];
for (const tableColumn of tableColumns) {
if (!tableColumn?.cn) {
throw Error('Missing column name in template');
}
const column = {
...this.sqlUi.getNewColumn(''),
cn: tableColumn.cn,
_cn: tableColumn.cn,
uidt: tableColumn.uidt,
...this.sqlUi.getDataTypeForUiType(tableColumn)
};
columns.push(column);
}
return columns;
}
private ex;
}
Loading…
Cancel
Save