Grant and Revoke on a table in Informix - informix

If I try to execute
create table TEST(testColumn VARCHAR(255));
grant insert on TEST to test_user;
revoke insert on TEST from test_user;
I get the following error message (translated from German by myself):
1) [REVOKE - 0 row(s), 0.000 secs] [Error Code: -580, SQL State: IX000]
Could not detract access rights.
2) [Error Code: -111, SQL State: IX000] ISAM-Error: No data record was found.
(English version of error -580: Cannot revoke permission.)
Do you have any idea what is going on here?

All the statements are issued with the same user?
Usually this happens when trying to revoke a table-level privilege that your account name did not grant.
To find the correct grantee use:
SELECT a.grantee, a.grantor
FROM systabauth a, systables t
WHERE a.tabid = t.tabid
AND UPPER(t.tabname) = 'TEST';
Then it's possible to issue:
REVOKE INSERT ON TEST FROM 'test_user' AS '<GRANTEE>';
The other possibility that I didn’t mention, but #chris311 figure it out, is that you cannot revoke privileges from yourself.
What is happening “behind it”, take the next example, a database named chris311, owned by chris, bear in mind that I'm using the informix user:
[infx1210#tardis ~]$ id
uid=501(informix) gid=501(informix) groups=501(informix)
[infx1210#tardis ~]$ dbaccess chris311 -
Database selected.
> SELECT name, owner
> FROM sysmaster:sysdatabases
> WHERE name = DBINFO('dbname') ;
name chris311
owner chris
1 row(s) retrieved.
>
Both chris and informix have the DBA database-level privilege, and ricardo was granted the CONNECT privilege:
> SELECT username, usertype
> FROM sysusers;
username usertype
chris D
informix D
ricardo C
3 row(s) retrieved.
>
There is a table, tab1, owned by chris that ricardo was granted, by chris, the ALL table-level privilege:
> SELECT t.tabname, t.owner, a.grantee, a.tabauth, a.grantor
> FROM systabauth a, systables t
> WHERE a.tabid = t.tabid
> AND t.tabname= 'tab1';
tabname tab1
owner chris
grantee ricardo
tabauth su-idxar-
grantor chris
1 row(s) retrieved.
>
Then if informix whant's to revoke the INSERT privilege it must use the AS clause to specify chris as the revoker:
> REVOKE INSERT ON tab1 FROM ricardo;
580: Cannot revoke permission.
111: ISAM error: no record found.
Error in line 1
Near character position 33
> REVOKE INSERT ON tab1 FROM ricardo AS chris;
Permission revoked.
> SELECT t.tabname, t.owner, a.grantee, a.tabauth, a.grantor
> FROM systabauth a, systables t
> WHERE a.tabid = t.tabid
> AND t.tabname = 'tab1';
tabname tab1
owner chris
grantee ricardo
tabauth su--dxar-
grantor chris
1 row(s) retrieved.
>
If he tries to revoke the INSERT privilege from himself an error will return also:
> REVOKE INSERT ON tab1 FROM informix;
580: Cannot revoke permission.
111: ISAM error: no record found.
Error in line 1
Near character position 34
>
Now if we see the meaning of the 580 error we get:
[infx1210#tardis ~]$ finderr 580
-580 Cannot revoke permission.
This REVOKE statement cannot be carried out. Either it revokes a
database-level privilege, but you are not a Database Administrator in
this database, or it revokes a table-level privilege that your account
name did not grant. Review the privilege and the user names in the
statement to ensure that they are correct. To summarize the table-level
privileges you have granted, query systabauth as follows:
SELECT A.grantee, T.tabname FROM systabauth A, systables T
WHERE A.grantor = USER AND A.tabid = T.tabid
[infx1210#tardis ~]$
It doesn't says anything about revoking privileges from himself, but the documentations mentions it. Also, if we think about the 111: ISAM error: no record found. and associate it to the fact that the DBA doesn´t appear on the systabauth it makes sence, kind of.
The grants doesn´t return an error/warning because the DBA already have the privileges, the revoke returns it because the action didn't take effect.
Now let's take the DBA role from chris, let's do it twice:
> REVOKE DBA FROM chris;
Permission revoked.
> REVOKE DBA FROM chris;
Permission revoked.
> SELECT username, usertype
> FROM sysusers;
username usertype
chris C
informix D
ricardo C
3 row(s) retrieved.
> SELECT t.tabname, t.owner, a.grantee, a.tabauth, a.grantor
> FROM systabauth a, systables t
> WHERE a.tabid = t.tabid
> AND t.tabname= 'tab1';
tabname tab1
owner chris
grantee ricardo
tabauth su--dxar-
grantor chris
1 row(s) retrieved.
>
Again, the second REVOKE didn't return an error/warning because it was in effect. The user still doesn´t appear on the systabauth table.
But what table-level privileges it has?
[infx1210#tardis ~]$ dbaccess chris311 -
Database selected.
> INSERT INTO tab1 VALUES(1);
1 row(s) inserted.
> SELECT * FROM tab1;
col1
1
1 row(s) retrieved.
> DROP TABLE tab1;
Table dropped.
>
He isn't a DBA but he is the owner.

Related

Is there any way to list all schema in informix (including the ones which donot have any tables and any privileges)?

I am trying to fetch metadata in my application. For that, I need to list all schemas and their metadata in informix. I am not able to find any system table which will list all schemas (as in oracle).
I saw this question but couldn't get desired result.
Have referred to informix's official website for systables and sysusers
select username,usertype from sysusers;
-- fetches users or roles with database level privileges
select distinct owner from systables;
-- fetches schemas containing a database object.
Also, what exactly is present in sysmaster database's systables and sysusers? When to use them?
There is no actual schema object in an Informix database ( you cannot grant privileges on a schema ). There are various types of "objects" and each object has an owner. You could consider that the owner is the schema, if you really want to. Doing a simple search on the catalog tables on a newly created Informix ( version 14.10.FC1 ) database we get:
SELECT
t.tabname,
c.colname
FROM
systables AS t
INNER JOIN
syscolumns AS c
ON
t.tabid = c.tabid
WHERE
c.colname = 'owner'
;
tabname systables
tabname sysindices
tabname syssynonyms
tabname syssyntable
tabname sysconstraints
tabname sysprocedures
tabname sysopclstr
tabname systriggers
tabname sysobjstate
tabname sysxtdtypes
tabname syscasts
tabname sysopclasses
tabname sysaggregates
tabname sysdomains
tabname sysindexes
And there can be more, this was just a quick look at the catalog tables. So your schema information is spread over multiple catalogs.
About the sysmaster database, it is a database ( although a special one ) and therefore it has it's own catalogs tables, just like any other Informix database.

Select from table join select in Visual FoxPro

I want to get Users' info with their last dates of login.
select * from Users as UU
inner join
(select user_id, max(d_login) from Logins group by user_id) as LL
on UU.user_id = LL.user_id
Join doesn't work in VFP. We can't join table to query here?
VFP need to use ALLTRIM() in join, otherwise comparing 2 values could result undesirable data. your code should be like this
select * from Users as UU
inner join
(select user_id, max(d_login) from Logins group by
user_id) as LL
on ALLT(UU.user_id) == ALLT(LL.user_id)
Assuming you have normalised User_ID as primary key in both tables i.e. Users and Logins and have same Field Type and Field Length. I created the tables users and Logins and tested this query with a sample data and it worked smoothly and gave exact results.
select
Users.User_id,
Users.Cell1,
Users.Name,
max(d_login)
from Logins, users
WHERE users.user_id = logins.user_id
GROUP BY
Users.user_id, Users.Cell1, Users.Name, Logins

Reports for permissions to Informix user

I want to generate a report file based on the permissions granted to an Informix user for three different tables like follows:
USER Report
USER tbl1 tbl2 tbl3
A 1 0 0
B 1 0 0
C 0 1 1
D 0 1 1
In the above example 1 denotes user 'A' and 'B' has 'SELECT' permission on the 'tbl1' table and user 'C' and 'D' has 'SELECT' permission on the 'tbl2' and 'tbl3' tables.
I went through internet and got dbschema command. But its output is different then required.
Please guide me to generate this report.

bigQuery - Join

I'm trying to join two databases on the ID. The first database on price quotes does not have the data on websites, so I want to join it in from the logs database. However, in the logs database the ID is not unique, but the first chronological appearance of the ID - this is the right website.
When I run the query below, I get:
Resources exceeded during query execution.
Hence I don't know whether the problem is the code or something else.
Thanks
SELECT ID, user,busWeek, count(*) as num FROM [datastore.quotes]
Join (
select objectID, first(website) from (
select objectID, website, date from [datastore.allLogs]
order by date) group by objectID)
as Logs
on ID = objectID
group by ID,user,busWeek
Can you try:
SELECT ID, user,busWeek, count(*) as num FROM [datastore.quotes]
Join EACH (
select objectID, first(website) from (
select objectID, website, date from [datastore.allLogs]
order by date) group EACH by objectID)
as Logs
on ID = objectID
group by ID,user,busWeek
Note the 'EACH' - that keyword won't be needed in the future, but it's still useful today.
I think the issue is in ORDER BY. This brings all calculation to one node which causes "Resources Exceeded" message. I understand you need it to bring first (by date) website for each object.
Try to rewrite this select (inside join) to be partitioned.
For example using window functions with OVER(PARTITION BY ... ORDER BY)
In this case, I think, you have chance to make this in parallel
See below for reference
Window Functions

SQL Server - Selecting records with specific, multiple entries in an associative table

I’m working in SQL Server with the following sample problem. Brandon prefers PC’s and Macs, Sue prefers PC’s only, and Alan Prefers Macs. The data would be represented something like this. I've had to make some compromises here but hopefully you get the picture:
TABLE 1: User
uID (INT PK), uName (VARCHAR)
1 'Brandon'
2 'Sue'
3 'Alan'
TABLE 2: Computer
cID (INT PK), cName (VARCHAR)
1 'Mac'
2 'PC'
TABLE 3: UCPref --Stores the computer preferences for each user
uID (INT FK), cID (INT FK)
1 1
1 2
2 1
3 2
Now, if I want to select everyone who likes PC’s OR Macs that would be quite easy. There's a dozen ways to do it, but if I'm having a list of items fed in, then the IN clause is quite straight-forward:
SELECT u.uName
FROM User u
INNER JOIN UCPref p ON u.uID = p.uID
WHERE cID IN (1,2)
The problem I have is, what happens when I ONLY want to select people who like BOTH PC’s AND Mac’s? I can do it in multiple sub queries, however that isn’t very scalable.
SELECT u.uName
FROM User u
INNER JOIN UCPref p ON u.uID = p.uID
WHERE u.uID IN (SELECT uID FROM UCPref WHERE cID = 1)
AND u.uID IN (SELECT uID FROM UCPref WHERE cID = 2)
How does one write this query such that you can return the users who prefer multiple computers taking into consideration that there may be hundreds, maybe thousands of different kinds of computers (meaning no sub queries)? If only you could modify the IN clause to have a key word like 'ALL' to indicate that you want to match only those records that have all of the items in the parenthesis?
SELECT u.uName
FROM User u
INNER JOIN UCPref p ON u.uID = p.uID
WHERE cID IN *ALL* (1,2)
Using JOINs:
SELECT u.uname
FROM USERS u
JOIN UCPREF ucp ON ucp.uid = u.uid
JOIN COMPUTER mac ON mac.cid = ucp.cid
AND mac.cname = 'Mac'
JOIN COMPUTER pc ON pc.cid = ucp.cid
AND pc.cname = 'PC'
I'm using table aliases, because I'm JOINing onto the same table twice.
Using EXISTS:
SELECT u.uname
FROM USERS u
JOIN UCPREF ucp ON ucp.uid = u.uid
WHERE EXISTS (SELECT NULL
FROM COMPUTER c
WHERE c.cid = ucp.cid
AND c.cid IN (1, 2)
GROUP BY c.cid
HAVING COUNT(*) = 2)
If you're going to use the IN clause, you have to use GROUP BY/HAVING but there is a risk in the COUNT(). Some db's don't allow more than the *, while MySQL allows DISTINCT .... The problem is that if you can't use DISTINCT in the count, you could get two instances of the value 2, and it would valid to SQL - giving you a false positive.

Resources