Stack: node 16 / Express+TS / TypeORM^0.2.45
I happen to have two databases mysql and oracle that require interoperability. Some queries depend on vendor-specific functions like date_diff(a, b) vs a - b and year(a) vs extract(year from a)... I couldn't find any utils that help translating that; is there any built-in function or lib that could do the trick before I resort to implementing my own?
Related
I am wondering which version is the best one to implement.
The parameters are states that have 2 possible values.
This is an abstract example of the actual problem.
I am programming in a language that is procedural (without classes) and does not have typed variable.
I just read an article stating that version 1 is bad for readability and the caller. Personally I don't like version 2 either. Maybe there is a better option?
Version 1:
doSth(par1, par2)
Not redundant +
Single Method for a task +
More complex implementation -
Wrong parameters can be passed easily -
Version 2:
doSthWithPar1Is1AndPar2Is1()
doSthWithPar1Is1AndPar2Is2()
doSthWithPar1Is2AndPar2Is1()
doSthWithPar1Is2AndPar2Is2()
Redundant -
Too many methods (especially with more parameters) -
Long Method Names -
Simple implementation +
No parameters that could be passed wrong +
Given that you already have considered V1 feasible tells me, that the different argument value combinations have something in common with regards to how the values are to be processed.
In V2 you simply have to type and read more, which I'd say is the single most frequent reason for introducing errors/incorrectness and lose track of your requirements.
In V2 you have to repeat what is common in the individual implementations and if you make a mistake, the overall logic will be inconsistent at best. And if you want to fix it, you probably have to fix it in several places.
But, you can optimize code safety based on V1: choose a more "verbose" name for the procedure, like
doSomethingVerySpecificWithPar1OfTypeXAppliedToPar2OfTypeY(par1, par2)
(I am exaggerating a bit...) so you see immediately what you have originally intended.
You could even take the best out of V2 and introduce the individual functions, which simply redirect to the common function of V1 (so you avoid the redundancy). The gain in clarity almost always outweighs the slight loss of efficiency.
doSthWithPar1Is1AndPar2Is1()
{
doSomethingVerySpecificWithPar1OfTypeXAppliedToPar2OfTypeY(1, 1);
}
Always remember David Wheeler: "All problems in computer science can be solved by another level of indirection".
Btw: I don't consider long method names a problem but rather a benefit (up to a certain length of course).
Using SQL databases, it is easy to do statistical / aggregate functions like covariance, standard deviation, kurtosis, skewness, deviations, means and medians, summation and product etc, without taking the data out to an application server.
http://www.xarg.org/2012/07/statistical-functions-in-mysql/
How are such computations done effectively (as close as possible to the store, assuming map/reduce "jobs" won't be realtime) on NoSql databases in general and dynamodb(cassandra) in particular, for large datasets.
AWS RDS (MySQL, PostgresSQL, ...) is, well, not NoSQL and Amazon Redshift (ParAccel) - a column store - has a SQL interface and may be an overkill ($6.85/hr). Redshift has limited aggregation functionality (http://docs.aws.amazon.com/redshift/latest/dg/c_Aggregate_Functions.html, http://docs.aws.amazon.com/redshift/latest/dg/c_Window_functions.html)
For DB's which have no aggregate functionality (e.g. Cassandra) you are always going to have to pull some data out. Building distributed computation clusters close to your DB is a popular option at the moment (using projects such as Storm). This way you can request and process data in parallel to do your operations. Think of it as a "real time" Hadoop (though it isn't the same).
Implementing such a setup is obviously more complicated than having a system that supports it out of the box, so factor that into your decision. The upside is that, if needed, a cluster allows you to do perform complex custom analysis way beyond anything that will be supported in a traditional DB solution.
Well, in MongoDB you have a possibility to create a some kind of UDF:
db.system.js.save( { _id : "Variance" ,
value : function(key,values)
{
var squared_Diff = 0;
var mean = Avg(key,values);
for(var i = 0; i < values.length; i++)
{
var deviation = values[i] - mean;
squared_Diff += deviation * deviation;
}
var variance = squared_Diff/(values.length);
return variance;
}});
db.system.js.save( { _id : "Standard_Deviation"
, value : function(key,values)
{
var variance = Variance(key,values);
return Math.sqrt(variance);
}});
The description is here.
MongoDB has some aggregation capabilities that might fit your needs http://docs.mongodb.org/manual/aggregation/
Example of the problem:
Schema name - schema123
Function name = function123
Can't find -> variable:=function123();
Can find -> variable:=schema123.function123()
Using PostgreSQL 8.4
try:
SET search_path='public, schema123';
Then run your function.
A much better approach would be to use the fully qualify the function name with the schema name as in your second example. That is far less error-prone.
As a note unless you have the schema in the search path functions will not find it. In Pg 8.4, you have to have complicated logic inside the stored procedures to set and restore the search. In 9.2 you can actually set this for the function which may be a good reason to consider upgrading.
I've used to use something like this with the regular PHP's PDO:
$data = array(
":name" => "james",
":location" => "Palo Alto, CA"
);
SQL:
SELECT * FROM people WHERE name LIKE :name and location = :location
When i've started to use Codeigniter, it won't let me use namespace keys anymore, it only accepts the traditional ? marks.
Anyway to fix that?
Unfortunately, no, there isn't. Not with CodeIgniter natively.
It helps to remember that CodeIgniter's roots are in PHP4 compliant code (and some of the things they did are not even the most recent PHP 4 -- they use a custom file searching system which is substantially slower than glob which was around by PHP 4.3 (4.4? It was around for the minimum required version), this means that the old '?' was really the best option at the time.
If you feel better about using the newer style, then you might be better off using the PDO classes. They're better and faster anyway. (Frankly, I only use CI's DB classes for compliance. I have a very strong preference for PDO's, especially since all of the modern frameworks seem to use them). I will warn you, though, that the use of PDO's completely invalidates the ActiveRecord framework offered by CodeIgniter. You will not be able to use $this->db->select()->from('table')->where($array)->limit(1,4); More importantly, you will need to know the differences between the different dialects of SQL, something CodeIgniter lets you avoid (and your code won't be DB agnostic anymore).
Maybe you will be more comfortable using Active Record in Codeigniter and doing something like
$this->db->like();
Look here: http://codeigniter.com/user_guide/database/active_record.html
I created a project to test out NHibernate 3+ vs. Entity Framework 4.1, wrapping it in a repository, making it very testable using interfaces etc.
I do not want to expose either ORM outside of the repositories (I do not even expose IQueryables). Everything should be handled in that layer and until I tried to handle fetching in an abstract way, everything was good.
Microsoft's implementation of adding eager loading uses either magic strings (yuck) or Linq expressions (yay) on the Include function. Their syntax follows something like this:
IQueryableThing.Include(o => o.Person);
IQueryableThing.Include(o => o.Company.Contact);
IQueryableThing.Include(o => o.Orders.Select(p => p.LineItem.Cost);
The first will just load the associated person. (parent)
The second will load the associated company and each company's contact. (parent and grandparent).
The third will load all associated orders, line items and costs for each order.
It's a pretty slick implementation.
NHibernate uses a slightly different approach. They still use Linq expressions, but they make heavier use of extension methods (fluent approach).
IQueryableThing.Fetch(o => o.Person);
IQueryableThing.Fetch(o => o.Company).ThenFetch(o => o.Contact);
IQueryableThing.FetchMany(o => o.Orders).ThenFetch(p => p.LineItem).ThenFetch(q => q.Cost);
(I'm not sure I if the third line is the correct syntax)
I can encapsulate a list of expressions in a separate class and then apply those expression to the IQueryable within that class. So what I would need to do is standardize on the Microsoft expression syntax and then translate that into NHibernate's syntax by walking the expression tree and rebuilding each expression.
This is the part that's really tricky. I have to maintain a particular order of operations in order to call the correct function for the IQueryable (must start with either Fetch or FetchMany, with each subsequent being a "ThenFetch" or "ThenFetchMany"), which stops me from using the built-in ExpressionVisitor class.
Edit:
I finally created an expression parser that will take any level of nesting of properties, collections, and selects on collections and produce an array of expressions. Unfortunately, the built in Fetch extensions methods do not take LambdaExpression as a parameter.
The part I am stuck on currently is not being able to use the built in Fetch definitions from nHibernate. It looks like I may have to hit the Remotion library's functions directly or register my own extension methods that will satisfy their parser.
Funky.
Have you tried using NHiberanteUtil.Initialize()? I haven't attempted to do what you are doing, but I think Initialize will work akin to Include().