Add and improve introspection shortcuts
This commit is contained in:
parent
2beb66a334
commit
04db6ffcb4
1 changed files with 83 additions and 6 deletions
89
src/index.ts
89
src/index.ts
|
@ -8,6 +8,7 @@ import { findUpSync } from 'find-up'
|
||||||
interface OraTable {
|
interface OraTable {
|
||||||
OWNER: string
|
OWNER: string
|
||||||
TABLE_NAME: string
|
TABLE_NAME: string
|
||||||
|
KIND: 'table' | 'view'
|
||||||
}
|
}
|
||||||
|
|
||||||
interface OraColumn {
|
interface OraColumn {
|
||||||
|
@ -16,6 +17,8 @@ interface OraColumn {
|
||||||
COLUMN_NAME: string
|
COLUMN_NAME: string
|
||||||
DATA_TYPE: string
|
DATA_TYPE: string
|
||||||
DATA_LENGTH: number | null
|
DATA_LENGTH: number | null
|
||||||
|
DATA_DEFAULT: string | null
|
||||||
|
IDENTITY_COLUMN: 'YES' | 'NO'
|
||||||
NULLABLE: 'Y' | 'N'
|
NULLABLE: 'Y' | 'N'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,13 +29,16 @@ interface Schema {
|
||||||
interface Table {
|
interface Table {
|
||||||
owner: string
|
owner: string
|
||||||
name: string
|
name: string
|
||||||
|
kind: 'table' | 'view'
|
||||||
columns: Column[]
|
columns: Column[]
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Column {
|
interface Column {
|
||||||
name: string
|
name: string
|
||||||
datatype: string
|
datatype: string
|
||||||
|
identity: boolean
|
||||||
nullable: boolean
|
nullable: boolean
|
||||||
|
default?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
function getStringParts(str: string, offset: number) {
|
function getStringParts(str: string, offset: number) {
|
||||||
|
@ -134,30 +140,43 @@ async function main() {
|
||||||
async function refresh() {
|
async function refresh() {
|
||||||
const tables = await execute<OraTable>(
|
const tables = await execute<OraTable>(
|
||||||
`
|
`
|
||||||
select owner, table_name from all_tables
|
select owner, table_name, 'table' kind from all_tables
|
||||||
union all select owner, view_name table_name from all_views
|
union all select owner, view_name table_name, 'view' from all_views
|
||||||
union all select '' owner, table_name from user_tables
|
union all select '' owner, table_name, 'table' from user_tables
|
||||||
union all select '' owner, view_name table_name from user_views
|
union all select '' owner, view_name table_name, 'view' from user_views
|
||||||
`,
|
`,
|
||||||
)
|
)
|
||||||
|
|
||||||
const columns = await execute<OraColumn>(
|
const columns = await execute<OraColumn>(
|
||||||
'select owner, table_name, column_name, data_type, data_length, nullable from all_tab_cols',
|
`
|
||||||
|
select owner, table_name, column_name, data_type, data_length, nullable,
|
||||||
|
data_default, identity_column
|
||||||
|
from all_tab_cols
|
||||||
|
`,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const self = await execute<{ USER: string }>('select user from dual')
|
||||||
|
|
||||||
schema.tables.length = 0
|
schema.tables.length = 0
|
||||||
|
|
||||||
for (const table of tables.rows ?? []) {
|
for (const table of tables.rows ?? []) {
|
||||||
schema.tables.push({
|
schema.tables.push({
|
||||||
owner: table.OWNER ?? '',
|
owner: table.OWNER ?? '',
|
||||||
name: table.TABLE_NAME,
|
name: table.TABLE_NAME,
|
||||||
|
kind: table.KIND,
|
||||||
columns: (columns.rows ?? [])
|
columns: (columns.rows ?? [])
|
||||||
.filter((col) => col.OWNER === table.OWNER && col.TABLE_NAME === table.TABLE_NAME)
|
.filter(
|
||||||
|
(col) =>
|
||||||
|
col.OWNER === (table.OWNER || self.rows![0].USER) &&
|
||||||
|
col.TABLE_NAME === table.TABLE_NAME,
|
||||||
|
)
|
||||||
.map((col) => ({
|
.map((col) => ({
|
||||||
name: col.COLUMN_NAME,
|
name: col.COLUMN_NAME,
|
||||||
datatype:
|
datatype:
|
||||||
col.DATA_LENGTH === null ? col.DATA_TYPE : `${col.DATA_TYPE}(${col.DATA_LENGTH})`,
|
col.DATA_LENGTH === null ? col.DATA_TYPE : `${col.DATA_TYPE}(${col.DATA_LENGTH})`,
|
||||||
|
identity: col.IDENTITY_COLUMN === 'YES',
|
||||||
nullable: col.NULLABLE === 'Y',
|
nullable: col.NULLABLE === 'Y',
|
||||||
|
default: col.DATA_DEFAULT ?? undefined,
|
||||||
})),
|
})),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -181,6 +200,64 @@ async function main() {
|
||||||
} else if (query === '\\q') {
|
} else if (query === '\\q') {
|
||||||
await connection.close()
|
await connection.close()
|
||||||
process.exit(0)
|
process.exit(0)
|
||||||
|
} else if (query === '\\r') {
|
||||||
|
await refresh()
|
||||||
|
} else if (query.match(/^\\[dD][tv]?($|\s)/)) {
|
||||||
|
const tables = schema.tables.filter((tab) => {
|
||||||
|
if (query.startsWith('\\dt')) {
|
||||||
|
return tab.kind === 'table' && !tab.owner
|
||||||
|
} else if (query.startsWith('\\dv')) {
|
||||||
|
return tab.kind === 'view' && !tab.owner
|
||||||
|
} else if (query.startsWith('\\Dt')) {
|
||||||
|
return tab.kind === 'table' && tab.owner
|
||||||
|
} else if (query.startsWith('\\Dv')) {
|
||||||
|
return tab.kind === 'view' && tab.owner
|
||||||
|
} else if (query.startsWith('\\d')) {
|
||||||
|
return !tab.owner
|
||||||
|
} else if (query.startsWith('\\D')) {
|
||||||
|
return tab.owner
|
||||||
|
} else {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const [_, name] = query.split(/\s+/).map((part) => part.trim())
|
||||||
|
const upper = (name ?? '').toUpperCase()
|
||||||
|
|
||||||
|
console.table(
|
||||||
|
tables.filter((tab) => {
|
||||||
|
const fullName = `${tab.owner}.${tab.name}`
|
||||||
|
return fullName.toUpperCase().includes(upper)
|
||||||
|
}),
|
||||||
|
['owner', 'name', 'kind'],
|
||||||
|
)
|
||||||
|
} else if (query.match(/^\\[dD][tv]?\+?\s+\S+/)) {
|
||||||
|
const [_, name] = query.split(/\s+/).map((part) => part.trim())
|
||||||
|
const upper = name.toUpperCase()
|
||||||
|
|
||||||
|
const table = schema.tables.find((tab) => {
|
||||||
|
if (!tab.owner && (tab.name === name || tab.name === upper)) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
const fullName = `${tab.owner}.${tab.name}`
|
||||||
|
return fullName === name || fullName === upper
|
||||||
|
})
|
||||||
|
|
||||||
|
if (table) {
|
||||||
|
console.table(
|
||||||
|
table.columns.map((col) => ({
|
||||||
|
name: col.name,
|
||||||
|
type: col.datatype,
|
||||||
|
flags: [col.identity ? 'ID' : '', col.nullable ? '' : 'NOT NULL']
|
||||||
|
.filter(Boolean)
|
||||||
|
.join(' '),
|
||||||
|
default: col.default,
|
||||||
|
})),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
console.log('Did not find', name)
|
||||||
|
}
|
||||||
} else if (query) {
|
} else if (query) {
|
||||||
try {
|
try {
|
||||||
const result = await execute(query, [], 1024)
|
const result = await execute(query, [], 1024)
|
||||||
|
|
Loading…
Reference in a new issue