<commit_before>/**
 * Created by ctalmacel on 12/8/15.
 */

var Q = require('q');
var createRawObject = require("../../lib/abstractPersistence.js").createRawObject;
var modelUtil = require("../../lib/ModelDescription.js");
var mysqlUtils = require("./mysqlUtils.js");

function sqlPersistenceStrategy(mysqlPool) {
    var self = this;
    var runQuery = Q.nbind(mysqlPool.query,mysqlPool);

    this.validateModel = function(typeName,description,callback){
        runQuery(mysqlUtils.describeTable(typeName)).
        then(validate,createTable).
        then(function(isValid){callback(null,isValid)}).
        catch(callback);

        function validate(tableStructure){

            var validModel = true;
            var model = new modelUtil.ModelDescription(typeName,description,self);

            tableStructure[0].forEach(function(column){
                column['Type'] = column['Type'].split('(')[0];   //ignore size specifications such as INT(10) ... not neccesarily reccomender
            });

            model.persistentProperties.some(function(modelProperty){
                var expectedDbType = self.getDatabaseType(model.getFieldType(modelProperty));
                if(expectedDbType === undefined){
                    validModel = false;
                    return true;
                }

                var validProperty = false;
                tableStructure[0].some(function(column){
                    if(column['Field'] === modelProperty){
                        validProperty = true;
                        var dbType = column['Type'];

                        if(dbType.indexOf(')')!==-1){
                            dbType = dbType.slice(dbType.indexOf('('));
                        }

                        if(dbType !== expectedDbType) {
                            validProperty = false;
                        }

                        if(column['Key']==='PRI') {
                            if (column['Field'] !== model.getPKField()) {
                                validProperty = false;
                            }
                        }
                        return true; // arry.some(callback) breaks when the callback returns true
                    }
                });

                if(validProperty === false){
                    validModel = false;
                    return true; // same motivation
                }
            });
            return validModel;
        }

        function createTable(){
            var persistentFields = modelUtil.getModel(typeName).persistentProperties;
            var tableDescription = {};
            persistentFields.forEach(function(field){
                tableDescription[field] = description[field];
            });
            return runQuery(mysqlUtils.createTable(self,typeName,tableDescription));
        }

    };

    this.findById = function (typeName, serialized_id, callback) {
        self.getObject(typeName,serialized_id,function(err,obj){
            if(err){
                callback(err);
            }else{
                if(obj.__meta.freshRawObject===true){
                    callback(null,null);
                }else{
                    callback(undefined,obj);
                }
            }
        });
    };

    this.getObject = function (typeName, serialized_id, callback) {
        var query = mysqlUtils.find(typeName,modelUtil.getPKField(typeName),serialized_id);
        mysqlPool.query(query,function(err,result){
            if(err){
                callback(err);
            }else{
                var model = modelUtil.getModel(typeName);
                var deserialized_id = modelUtil.deserialiseField(typeName,model.getPKField(),serialized_id,self);
                var retObj = createRawObject(typeName, deserialized_id);
                if (result.length>0) {
                    modelUtil.load(retObj, result[0], self);
                }
                self.cache[deserialized_id] = retObj;
                callback(null,retObj);<commit_msg>better validation for sql tables<commit_after>/**
 * Created by ctalmacel on 12/8/15.
 */

var Q = require('q');
var createRawObject = require("../../lib/abstractPersistence.js").createRawObject;
var modelUtil = require("../../lib/ModelDescription.js");
var mysqlUtils = require("./mysqlUtils.js");

function sqlPersistenceStrategy(mysqlPool) {
    var self = this;
    var runQuery = Q.nbind(mysqlPool.query,mysqlPool);

    this.validateModel = function(typeName,description,callback){
        mysqlPool.query("DESCRIBE "+typeName,function (err,sqlProperties) {
            if(err){
                if(err.message.match('ER_NO_SUCH_TABLE')) {
                    var persistentFields = modelUtil.getModel(typeName).persistentProperties;
                    var tableDescription = {};
                    persistentFields.forEach(function (field) {
                        tableDescription[field] = description[field];
                    });
                    mysqlPool.query(mysqlUtils.createTable(self, typeName, tableDescription), callback);
                }else{
                    callback(err);
                }
            }else{
                var invalidProperties = [];
                var model = new modelUtil.ModelDescription(typeName,description,self);
                sqlProperties.forEach(function(column){
                    column['Type'] = column['Type'].split('(')[0];   //ignore size specifications such as INT(10)
                });
                model.persistentProperties.forEach(function(modelProperty){
                    var expectedDbType = self.getDatabaseType(model.getFieldType(modelProperty));
                    if(expectedDbType === undefined){
                        invalidProperties.push(new Error("Property "+modelProperty+" is invalid because the sql type for "+model.getFieldType(modelProperty)+" apersistence Type is unknown"));
                        return;
                    }
                    sqlProperties.forEach(function(sqlProperty){
                        if(sqlProperty.field === modelProperty && sqlProperty.type !== expectedDbType){
                            invalidProperties.push(new Error("Property "+modelProperty+" is invalid because the expected sql type for "
                                +model.getFieldType(modelProperty)+" apersistence Type is "+expectedDbType+" " +
                                "whereas in the table the type is "+column['Type']));
                        }
                    })
                });
                if(invalidProperties.length >0){
                    callback(invalidProperties)
                }else{
                    callback();
                }
            }
        })
    };

    this.findById = function (typeName, serialized_id, callback) {
        self.getObject(typeName,serialized_id,function(err,obj){
            if(err){
                callback(err);
            }else{
                if(obj.__meta.freshRawObject===true){
                    callback(null,null);
                }else{
                    callback(undefined,obj);
                }
            }
        });
    };

    this.getObject = function (typeName, serialized_id, callback) {
        var query = mysqlUtils.find(typeName,modelUtil.getPKField(typeName),serialized_id);
        mysqlPool.query(query,function(err,result){
            if(err){
                callback(err);
            }else{
                var model = modelUtil.getModel(typeName);
                var deserialized_id = modelUtil.deserialiseField(typeName,model.getPKField(),serialized_id,self);
                var retObj = createRawObject(typeName, deserialized_id);
                if (result.length>0) {
                    modelUtil.load(retObj, result[0], self);
                }
                self.cache[deserialized_id] = retObj;
                callback(null,retObj);
{'fraction_non_alphanumeric': 0.10987059122050241, 'fraction_numerical': 0.0030449124587668104, 'mean_word_length': 1.6767402376910017, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 6, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7118810', 'n_tokens_mistral': 1963, 'n_tokens_neox': 1847, 'n_words': 327}