Redshift View keeps reverting to previous definition - view

I created a view in Redshift that unions two queries, and it works great. We've thought of a third query that would be worthwhile to add in. eg
CREATE VIEW stem_alumni as
SELECT name, email
FROM students
WHERE graduated < 2019 AND major = 'Engineering'
UNION
SELECT name, email
FROM alumni
WHERE current_employer = 'Google'
The problem is when I try to add a third query in
UNION
SELECT name, email
FROM professors
WHERE department = 'Engineering'
it'll persist for maybe an hour, but then revert to just the original query.
I've run CREATE OR REPLACE VIEW... and dropping/recreate and get the same result.
How do I get an updated view definition to persist?
Adding more context
I created the view using DBeaver, a local SQL client using my specific Redshift credentials. The view is called by Periscope, our cloud-based BI tool using shared credentials. Querying the view in Periscope or separate DBeaver windows will eventually revert the view to its original definition.

Redshift shouldn't have a 'memory' of the view's prior DDL that it could revert to. I'm inclined to agree with the comments that something else is overwriting the updates to the view's DDL after you have committed them.
You should be able to see if something is overwriting the view, by querying the stl_query table:
SELECT q.starttime
, u.usename
, q.querytxt
FROM pg_user u
JOIN stl_query q ON u.usesysid = q.userid
WHERE POSITION('<view_name>' IN q.querytxt) > 0
ORDER BY q.starttime DESC
;
This table only contains recent query information (2-5 days according to the Redshift Documentation), so if you haven't experienced this behavior from the view within that timescale, you may need to force it to occur again in order to troubleshoot who/what is altering the DDL.
Additionally, if the view is being overwritten by a user other than yourself, you will need to query stl_query using a super user account (by default, non-super users will only be able to view information for queries that they themselves have executed).

Related

How to navigate XAMPP/myPHP and verify if mySQL is functional?

Recently downloaded XAMPP on Windows and I would like to request a tutorial on how to navigate the program. I'm not sure how to open myPHP and test SQL Queries or create databases. Any help would be appreciated.
Welcome to XAMPP,
By now you should have the program installed in the location of your choice from the Apache friends website. I understand that it is quite difficult to get started on a new project utilizing unfamiliar tools, by the end of this short tutorial you can start building all sorts of ideas!
1. To start, open the application from the desktop. On windows, the opening screen will display as shown below. Click on "Start" for the Apache and MySQL modules.
Homepage of XAMPP
The port value will be 80 for Apache in most cases, this varies dependent on module type and other applications with respect to their assigned port numbers.
These can be viewed by navigating to "Netstat" which displays socket properties. Configurations can be completed under "Config" in the top right of the application and under "Service and Port Settings". Common issues to modules not working correctly is due to port error or overlapping and changing values will prevent this.
2. The status of the modules is portrayed in the panel below. In your preferred internet browser, type "http://localhost". The dashboard of Apache with given instructions will show when entered. Navigate to "PHPMyAdmin" at the top right of the webpage.
PHPMyAdmin
The critical step for this dashboard to be functional is to have the MySQL module running. On the left of the screen, databases are displayed when created.
3. Next, type "Create database test;" in the SQL tab queries text box. The console is displayed at the bottom of the page representing errors and program messages. Click the "Go" button. The "test" database will join the list of databases on the left side of the window.
This verifies that MySQL and Apache servers are functional on the local computer. URL's define locations for pages that are requested and identify webserver addresses. Apache is an application that provides access to these requested locations to the user.
4. A simple webpage can be generated by the user through XAMPP. Create a .txt file with its contents only including "<h1>StackOverFlow</h1>" and under this type "<p>I am learning, this is a test</p>". Save this file in the htdocs folder inside the xampp installation location as "StackOverFlow.html". Go to your browser and insert "http://localhost/StackOverFlow.html".
The process listed allows the browser URL to request the existing web server to obtain the page's contents "http://localhost/StackOverFlow.html"
5. Next, go back to step 3 where queries will be used to construct tables for relationships of entities and test values.
The test database was created previously and still exists. Keep the query tab open and edit the initial script to be "create database if not exists test;". Add the statement "drop database if exists test;". These steps permit the program to refresh the database and scripted queries each time the user clicks "Go" resulting in the removal of overlapping data.
Two tables will be created and their relationship can be expressed shortly. In the next step, a simple Company and Product association is used. Basic terms to know to write SQL queries:
SELECT -> extracts data from a database
UPDATE -> updates data in a database
DELETE -> deletes data from a database
INSERT INTO -> inserts new data into a database
CREATE DATABASE -> creates a new database
CREATE TABLE -> creates a new table
DROP TABLE -> deletes a table
VarChar -> Varying variable character of desired length
Char -> character of set length
Not Null -> term cannot be null
Date -> date term reference
Integer -> term must be an integer
Key -> uniquely identifies row(s) in a table
SQL Syntax
6. Insert "use test;" under the creation of the database query. Then structure the code in an organized fashion for easy reading for the user.
Add "create table Company(" and under insert "companyName varchar(40) not null primary key,", then "street varchar(40),". Also, "city varchar(40)," and "province char(2)," with "postalCode char(6));".
Add "create table Product(" and under insert "producedBy varchar(40) not null,", then "dateMade date not null,". Also, "productName varchar(40) not null);".
The Company and Product tables are now created with specific dimensions, ordering, and terms.
7. There are many types of relations within SQL that allow individuals to retrieve specific data, store, and construct relationships between many tables with set parameters through additional queries. This example is simple where producedBy references the companyName containing relevant data.
Position the following below both the table queries:
Test values for Company table
Test values for Product table
Select "Go" and this will create tables that can be viewed by clicking the database "test" on the left side.
Here, the statement INSERT INTO is used to input the data below into the table with the parameters created. Appropriate ordering of data from first to last must match with the corresponding table. Invalid inputs will result in the console returning an error. Selecting specific data from a larger database with numerous tables can be accessed by "SELECT * FROM TABLENAME", creating temporary relations and returning desired data. This concept can be further discussed in another tutorial. The interface is extremely useful and can be implemented within html websites to store, calculate, or retrieve data/user processes.
XAMPP is an exceptional tool to create and integrate into different areas of development, I would recommend taking a look at "https://www.w3schools.com/" to further learn SQL, HTML, and other skills to extend your range of capabilities.
Thank you for going through this tutorial! If you have any questions feel free to leave a comment.

Two Queries in one copy activity Data Factory v2

I'm new using Azure Data Factory and i would like to know if there is a mode to run two queries in one activity copy, for example:
I have a Data Set Oracle for my origin and other for my stage, both use Oracle DB.
i need copy all registries in a specific query, but before to run it, i need to alter session
ALTER session SET nls_language = 'AMERICAN';
and immediately run my query
Select * from ... where ....
This is posible? or it's not the way? thks for your answers
Important: We don't have the posibility to create objects in DB Origin
Of course you can, in the copy activity, click on the tab Source, and then select Query. Input your 2 step query into the textbox and you are good to go.
Hope this helped!

Proforma SalesInvoice doesn't show data from all tables

In the salesInvoice ssrs Report i have added a table called carTableEquipTmp which is not there by default, which I insert into along with the other tables(SalesinvoiceTmp and SalesinvoiceHeaderFooterTmp) in SalesInvoiceDP.InsertIntoSalesInvoiceTmp().
Even though my table carTableEquipTmp is getting successfully inserted into, the data doesn't show up on the report if i print a proforma report.
If i add test values to the carTableEquipTmp table in SalesInvoiceDP.processReport() they show up on the proforma invoice, but there's no way for me to get any parameters needed to set in the correct data into the table at this point. If i stop at this point in the debugger none of the data is present because processreport() is being called from a lower level in the code.
I think it might be a problem with maybe pack/unpack or that the proforma code runs from a server instance as the code run when it is proforma is quite different.
I can see that SalesInvoiceJournalPostBase.CreateReportData() creates an instance of salesInvoiceDP
salesInvoiceDP = new SalesInvoiceDP();
salesInvoiceDP.parmDataContract(salesInvoiceContract);
salesInvoiceDP.parmUserConnection(new UserConnection(true));
salesInvoiceDP.createData();
And that this might have something to do with it... but i still cant get the data i want in the carTableEquipTmp table.
So any idea on how to make Ax 2012 accept this new table i have added as it gets inserted into just like the other tables and there seems to be no problem...
I hope you guys can help.
The SalesInvoice report has two data classes you need to look at for the data provider, SalesInvoiceDP and SalesInvoiceDPBase. SalesInvoiceDPBase extends SrsReportDataProviderPreProcess, so there are a couple extra steps you need to take in order to add new datasources to the report.
In the salesInvoiceDP class, there is a method called useExistingReportData(), which re-inserts the pro-forma temp table data under a user connection, so the SrsReportDataProviderPreProcess framework will pick it up in your report. When the pro-forma process creates the report data, it doesn't insert with a user connection so it doesn't get added to the report. This method only gets called when the report is being run pro-forma.
You will need to add your temp table to this method, and follow the pattern for the other tables, so your code will look something like this:
//this is different from the buffer you insert your data with
CarTableEquipTmp localCarTableEquipTmp;
...
recordList = new RecordSortedList(tableNum(carTableEquipTmp));
recordList.sortOrder(fieldNum(carTableEquipTmp, RecId));
//You will need to add a field to relate your temp table
//to the current invoice journal, and insert it in
//InsertIntoSalesInvoiceTmp() if thats where you're inserting your table.
while select localCarTableEquipTmp
where localCarTableEquipTmp.JournalRecId == jourRecId
{
recordList.ins(localCarTableEquipTmp);
}
delete_from localCarTableEquipTmp
where localCarTableEquipTmp.JournalRecId == jourRecId;
recordList.insertDatabase(this.parmUserConnection());
This method re-inserts your data under the framework and deletes the original data. The data that was re-inserted will then get picked up by the framework and show in your report. If you open CarTableEquipTmp in the table browser, you will most likely see data still there from all the times you have tried running the report. This is why we have the delete_from operation after we re-insert the data. When data is inserted under a userConnection, it is automatically deleted when the report is finished
The other method you will want to modify is SalesInvoiceDP.setTableConnections(), and you will just need to add the following line:
CarTableEquipTmp.setConnection(this.parmUserConnection());
This will set the user connection for your table when running regular (not pro-forma). You will probably want to delete the data that is stored currently in your temp table using alt+F9 from the table browser.
Other than that it's all standard RDP stuff, but it sounds like you have that part working fine. Your temp table must be of type "Regular" for this to work.

LINQ Query result makes no sense

I am running a simple LINQ query that connects to a view and returns all of the data with the id that I send in.
My simple query is:
var data = db.ViewDataAlls.Where(x => x.guidRequirementId == guidRequirementId);
if I run this query in the database:
select * from viewDataAll where guidrequiremendid = '{Guid Id Sent In Here}'
I get 2 rows back, however the LINQ query is returning 2 rows, but the rows are a duplicate of the first row, not 2 unique rows.
Any ideas?
EDIT: if I run this LINQ Query:
List<string> nums = db.ViewDataAlls
.Where(x => x.guidRequirementId == guidRequirementId)
.Select(x=>x.strNumber).ToList();
I get the individual row numbers, but if I just try to pull the entire row I get a duplicate of the first row multiple times...
I had the same problem. I was ready to conclude that this was a bug in Linq-to-SQL. Direct SQL queries against the view worked, Linqpad queries worked, etc... but for some reason querying against a view sometimes (and not even very often mind you, but when I'd find a particular value that failed, it appeared to always do so) failed. I verified that the query being passed by Linq to the SQL Server was correct (from the SQLServer logs), so it appeared the results were being mangled when they were received by Linq. Querying directly against the view or accessing the contents of the view via a defined association gave the same bad results.
Realizing that the problem lay on the receiving side of the query (after the results were passed back to Linq), I finally tracked it down to the way I had added the view to the dbml. Originally I had dragged the view onto the dbml designer surface, and added an association to the table I wanted to link it to, a basic one-to-many association (using an basic fkid == id relationship). However I couldn't access the view from the table in code. I discovered that I needed to add a primary key to the child (view), so I set the id property as the PK. This seemed to work until I got an unexpected exception when doing a .SingleOrDefault() against the view through the association. Knowing that it should be impossible for my data to have more that one hit for the property I was filtering with, I ran it through the debugger, and sure enough I was getting the right number of results (2 in my case), but the second result was just a copy of the first. The same thing the OP saw.
The solution it turns out is to set all the fields of the view as part of the primary key (in the dbml; I only had 3). Somehow, having the id field as the lone PK was not sufficient for Linq. Once I did this I had no further problems. (It may not be necessary to designate every field as part of the PK, so you may wish to experiment, but just the one id is insufficient apparently).
Note that I did have the view set as "not unique" in the dbml, which one would think would keep this from happening. Apparently not so.
Is ViewDataAlls a view or a table. If it's a view, maybe the sql statement generating that view produces duplicates.
Thanks JHurdlow, you save my day. Looks like LINQ does not use the groupby or order-by in the views. In my case, the SQL Statement in the view was correct and data was presented very well, but for any reason when use LINQ on my MVC3 is different and duplicates rows. In my case I had a view with 5 tables and I had to put all fields as PK on the view at ___DataModel.edmx. Now works fine.
This solution implies that all fields must be not-null, otherwise has to use CASE NULL-THEN END on the View schema.

Retrofitting record-level access restrictions in classic asp applications

Like the title says, I've been asked to come up with an estimate for retrofitting an existing asp application.
The current security mechanism controls access to different parts of the application (page-level restrictions), but has no mechanism for flagging individual records as restricted. Assigning rights to a user (using the existing, custom access management code) is no problem, but enforcing the rights is a different matter - each asp page has embedded sql - there's no use of stored procs, objects, etc.
Is the only solution to modify each table and query, or is there a better way? Any pointers, suggestions or prayers would be welcome.
This is classic asp, running on IIS6, against an oracle database.
Update: Here's a user scenario.
We have users, managers, directors, and VPs. The managers can see data created by users who report to them, but not users who report to other managers. Users can't see data created by any managers. Same thing with directors - they can see down, but their reports can't see up.
This sounds like an ideal time to implement row-level security. Oracle has a package DBMS_RLS that allows you to define arbitrary access policies that can be applied to one or more tables that limit what rows a particular user is allowed to see. Conceptually, when a user issues a query with no filters on a protected table, i.e.
SELECT *
FROM my_table
Oracle automatically and transparently inserts a WHERE clause defined by your security policy that limits the result set. You shouldn't need to make any changes to the SQL your application is executing.
Assuming you need maximum granularity, the ability to "grant" each and any row to any of very many users, then you have a many-to-many relation, yes?
So apply the following pattern:
Add a tables of users.
Then, for each restricted table, so the following:
Rename it tablename + "_base".
create a many-to-many table that
associates that table's id with a
user id, called tablename +
"allowed_user".
create a view with the name table
name that joins tablename_base to
table_name_allowed_user, with a
select* from tablename_base and
user_id from tablename_allowed_user.
This view should meet Oracle's
requirements rto be "inherently
updatable."
Now comes the hard part. You need to add "and user_id = $user_id" to every query. Find the various functions you're using to make queries. Wrap those function(s) in ones that gets the user id from the session and add that predicate.
One passable way to do this is to read select string, find the all "where"s (for subqueries there may be more that one), and replace it with "where (user = $user) and ". For queries that don't have a where, you'll need to insert this before any "group by" or "order by". This is fragile, so obviously you'll test that this works for all pages (you have an automated test for all pages, right?), and add hacks to cover special cases.
"update" statements won't have to change; "inserts" will presumably insert both to the view and then do a separate insert to the table's "allow_user" table with the id of the inserting user, to automatically grant teh inserting user acces to what he inserted.
If your number of users is more limited, or you're restricting types of users, you can go with a strategy of multiple views named for the user or type; then you'd replace tables names in the queries with the appropriate views.

Resources