Load unmapped tables in Symfony with Doctrine - database

I have tables in my database, that are not managed by Symfony; there are no entities for these tables. They are tables from another application, I import them and use Symfony to generate statistics from the data in the tables.
How do I access this?
Can i use doctrine and a regular repository for this?
I just want to read data, not update.
Right now I'm using straight mysqli_connect and mysqli_query, but that just doesn't feel right using Symfony 5.

You should just be able to query with sql. The following example comes straight from the docs:
// src/Repository/ProductRepository.php
// ...
class ProductRepository extends ServiceEntityRepository
{
public function findAllGreaterThanPrice(int $price): array
{
$conn = $this->getEntityManager()->getConnection();
$sql = '
SELECT * FROM product p
WHERE p.price > :price
ORDER BY p.price ASC
';
$stmt = $conn->prepare($sql);
$stmt->execute(['price' => $price]);
// returns an array of arrays (i.e. a raw data set)
return $stmt->fetchAllAssociative();
}
}
https://symfony.com/doc/current/doctrine.html#querying-with-sql

Related

Adding comments to database columns and retrieving from AWS Glue

I'm trying to incorporate a AWS GLUE Data Catalog to my Data Lake I'm building out. I'm using a few different databases and would like to add COMMENTS to columns in a few of these tables. These databases include Redshift and MySql. I usually add the comments to the column by doing something along the lines of
COMMENT ON COLUMN table.column_name IS 'This is the comment';
Now i know that Glue has a comment field that shows in the GUI. Is there a way to sync the comment field in Glue with the comments I add to the columns in a DB?
In order to update some meta information about a table that has been defined in AWS Glue Data Catalog, you would need to use a combination of get_table() and update_table() methods with boto3 for example .
Here is the most naive approach to do that:
import boto3
from pprint import pprint
glue_client = boto3.client('glue')
database_name = "__SOME_DATABASE__"
table_name = "__SOME_TABLE__"
response = glue_client.get_table(
DatabaseName=database_name,
Name=table_name
)
original_table = response['Table']
Here original_table adheres response syntax defined by get_table(). However, we need to remove some fields from it so it would pass validation when we use update_table(). List of allowed keys could be obtained by passing original_table directly to update_table() without any chagnes
allowed_keys = [
"Name",
"Description",
"Owner",
"LastAccessTime",
"LastAnalyzedTime",
"Retention",
"StorageDescriptor",
"PartitionKeys",
"ViewOriginalText",
"ViewExpandedText",
"TableType",
"Parameters"
]
updated_table = dict()
for key in allowed_keys:
if key in original_table:
updated_table[key] = original_table[key]
For simplicity sake, we will change comment of the very first column from the table
new_comment = "Foo Bar"
updated_table['StorageDescriptor']['Columns'][0]['Comment'] = new_comment
response = glue_client.update_table(
DatabaseName=database_name,
TableInput=updated_table
)
pprint(response)
Obviously, if you want to add a comment to a specific column you would need to extend this to
new_comment = "Targeted Foo Bar"
target_column_name = "__SOME_COLUMN_NAME__"
for col in updated_table['StorageDescriptor']['Columns']:
if col['Name'] == target_column_name:
col['Comment'] = new_comment
response = glue_client.update_table(
DatabaseName=database_name,
TableInput=updated_table
)
pprint(response)

Accessing new field value generated in SQL via dbContext

I'm using dbContext and I am running a SQL query that is rather complex (just showing a simple example below), so to avoid having to run the query twice to get a count, I am using COUNT AS to return the total number of records as per other advice on this site.
But, I haven't been able to figure out how to access the resulting property:
using (var db = new DMSContext())
{
string queryString = "select *, COUNT(1) OVER() AS TotalRecords FROM DMSMetas";
var Metas = db.DMSMetas.SqlQuery(queryString).ToList();
for (int i = 0; i <= Metas.Count - 1; i++)
{
var Item = Metas[i];
if (i == 0)
{
//Want to do this, but TotalRecords not part of the DMSMeta class. How to access the created column?
Console.WriteLine("Total records found: " + Item.TotalRecords);
}
}
}
In the sample above, the SQL query generates the extra field TotalRecords. When I run the query in Management Studio, the results are as expected. But how do I access the TotalRecords field through dbContext?
I also tried including the TotalRecords field as part of the DMSMeta class, but then the SQL query fails with the error that the TotalRecords field is specified twice. I tried creating a partial class for DMSMeta containing the TotalRecords field, but then the value remains the default value and is not updated during the query.
I also tried the following:
db.Entry(Item).Property("TotalRecords").CurrentValue
But that generated an error too. Any help would be much appreciated - I am sure I am missing something obvious! All I want is to figure out a way to access the total number of records returned by the query
you have to create a new class (not an entity class but a pure DAO class) DMSMetaWithCount (self explanatory ?) and then
context.Database.SqlQuery<DMSMetaWithCount>("select *, COUNT(1) OVER() AS TotalRecords FROM DMSMetas");
please note that
imho, select * is ALWAYS a bad practice.
you will have no tracking on the not entity new class

Select from 2 tables in Symfony2

I am making a query inside a form.
The idea is : Now I have a dropdown with all the users, ok?
I have a query like this:
'query_builder' => function(EntityRepository $er) {
return $er->createQueryBuilder('u')->orderBy('u.lastName', 'ASC');
}
This works flawless!
Instead of displaying all the users, I only need the users that are associated with a category. This definition is in the "user_data" table (user_id + category_id).
So, I need to do something like:
SELECT * FROM users
WHERE user_id IN (SELECT user_id FROM user_data WHERE category_id='2')
I don't have any entity that looks like UserData, I only have User.php, but inside this file I found this:
/**
*#ORM\ManyToMany(targetEntity="My\Bundle\Entity\Data", inversedBy="users")
*#ORM\joinTable(name="user_data")
*/
protected $datas;
[...]
So I see that a relationship is build, but I don't get it how to use it in order to build my query based on the 2 tables...
Anyone can help me with this issue? :)
Thanks!
Try this,
'query_builder' => function(EntityRepository $er) {
return $er->createQueryBuilder('u')
->innerJoin('u.datas', 'd')
->where('d.category = :category') // Check your Data entity to get the right field name
->setParameter('category', $yourCategoryId) // you could use options here
->orderBy('u.lastName', 'ASC');
}
Also, update your question with all your entities (Data, ...)

Salesforce SOQL describe table

Is there a way to fetch a list of all fields in a table in Salesforce? DESCRIBE myTable doesn't work, and SELECT * FROM myTable doesn't work.
From within Apex, you can get this by running the following Apex code snippet. If your table/object is named MyObject__c, then this will give you a Set of the API names of all fields on that object that you have access to (this is important --- even as a System Administrator, if certain fields on your table/object are not visible through Field Level Security to you, they will not show up here):
// Get a map of all fields available to you on the MyObject__c table/object
// keyed by the API name of each field
Map<String,Schema.SObjectField> myObjectFields
= MyObject__c.SObjectType.getDescribe().fields.getMap();
// Get a Set of the field names
Set<String> myObjectFieldAPINames = myObjectFields.keyset();
// Print out the names to the debug log
String allFields = 'ALL ACCESSIBLE FIELDS on MyObject__c:\n\n';
for (String s : myObjectFieldAPINames) {
allFields += s + '\n';
}
System.debug(allFields);
To finish this off, and achieve SELECT * FROM MYTABLE functionality, you would need to construct a dynamic SOQL query using these fields:
List<String> fieldsList = new List<String>(myObjectFieldAPINames);
String query = 'SELECT ';
// Add in all but the last field, comma-separated
for (Integer i = 0; i < fieldsList.size()-1; i++) {
query += fieldsList + ',';
}
// Add in the final field
query += fieldsList[fieldsList.size()-1];
// Complete the query
query += ' FROM MyCustomObject__c';
// Perform the query (perform the SELECT *)
List<SObject> results = Database.query(query);
the describeSObject API call returns all the metadata about a given object/table including its fields. Its available in the SOAP, REST & Apex APIs.
Try using Schema.FieldSet
Schema.DescribeSObjectResult d = Account.sObjectType.getDescribe();
Map<String, Schema.FieldSet> FsMap = d.fieldSets.getMap();
complete documentation
Have you tried DESC myTable?
For me it works fine, it's also in the underlying tips in italic. Look:

Obtain 'Identity' setting for a column in VistaDB

I am reading the database schema for VistaDB 4.0 database using the standard ADO.NET 'DbConnection.GetSchema' API. I haven't found a way to obtain the 'Identity' setting for a column? The 'Columns' schema collection doesn't seem to have a column for this and I am not aware of any other collection that I should look into.
If it is not possible by querying any of the available collections, do I have to query some system table or view?
Any help would be appreciated.
There are no "sys" tables in VistaDB. There is a [database schema] table that contains most of what you need though.
[database schema]
You can get the identity columns for a database using the database schema table like this:
select * from [database schema] where typeid = 6
Look in the help file for the typeid list and what they mean.
Then once you have the list, you can match it up to the typeid for tables to see what table the identity column came from.
The only catch with the database schema table is that you cannot self reference or join it to itself (design limitation). So if you need to pull and reference from itself you have to do it in two commands, or through a temp table. The help file has an example of how to do this as well.
Alternate Way
You can also find all the identity columns using a VistaDB stored proc:
select * from VistaDBColumnSchema() where is_identity = true
DDA
If you need to find the next value, seed, etc you can also get those through DDA (Direct Data Access) methods.
The Identities property on an IVistaDBTableSchema object is a collection of the identities for that table. That collection can then be walked to pull the individual values.
The identity information included is the Seed, Step, Tablename, and Columnname.
ADO.NET GetSchemaTable Way
And yes, there is still another way. You can call GetSchemaTable on a reader to get some more information about the underlying structure.
using (VistaDBConnection cn = new VistaDBConnection("Data Source=" + dbName))
{
cn.Open();
using (VistaDBCommand cmd = new VistaDBCommand("Select * from simpletable", cn))
{
using (VistaDBDataReader myReader = cmd.ExecuteReader(CommandBehavior.KeyInfo))
{
//Retrieve column schema into a DataTable.
DataTable schemaTable = myReader.GetSchemaTable();
foreach (DataRow myField in schemaTable.Rows)
{
foreach (DataColumn myProperty in schemaTable.Columns)
{
System.Diagnostics.Debug.WriteLine(myProperty.ColumnName + " = " + myField[myProperty].ToString());
}
}
}
}
}

Resources