<commit_before>var pg = require("pg");
var projector = require("../projector");
/*
 * Something like this eventually? 
 * https://github.com/mapbox/tilemill/blob/master/models/Layer.bones#L60
 */
module.exports = function(connectionString, table, geom_field, projection, encoding) {
  encoding = encoding || "utf8";
  projection = projection || "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext  +no_defs";
  // TODO better and more explicitly support projection autodetection, especially from PostGIS

  // loading synchronization
  var loadCallbacks = [];
  var loading = false;

  // stored state
  var loadError = null;
  var data = null;

  var source = function PostGISSource(minX, minY, maxX, maxY, mapProjection, callback) {
    if (!data && !loadError) {
      source.load(callback);
    }
    else {
      callback(loadError, data);
    }
  };

  source.load = function(callback) {
    callback && loadCallbacks.push(callback);
    if (!loading) {
      loading = true;

      var start = Date.now();
      console.log("Loading data in " + table + "...");

      loadPostGIS(connectionString, table, unique_field, geom_field,[minX, minY, maxX, maxY], projection, mapProjection, function(error, postgisData) {
        loadError = error;
        data = postgisData;

        console.log("Loaded in " + (Date.now() - start) + "ms");

        if (!error) {
          if (projection !== mapProjection) {
            console.log("Projecting features...");
            start = Date.now();

            projector.project.FeatureCollection(data, projection, mapProjection);

            console.log("Projected in " + (Date.now() - start) + "ms"); 
          }
          console.log("Projection not necessary")
        }


        loading = false;
        var callbacks = loadCallbacks;
        loadCallbacks = [];
        callbacks.forEach(function(callback) {
          callback(loadError, data);
        });
      });
    }
  };

  return source;
};

var loadPostGIS = function(connectionString, table, geom_field, coords callback) {
  pg.connect(connectionString, function(err, client) {
    if (!err) {

      // need some way to check projection equivalency programmatically so we can use built-in postgis projection i.e.
      //
      // check proj4 support with: SELECT PostGIS_Full_Version();
      // i.e. POSTGIS="1.3.3" GEOS="3.1.0-CAPI-1.5.0" PROJ="Rel. 4.4.9, 29 Oct 2004" USE_STATS
      // 
      //
      // if (!projector.equals(projection,mapProjection){
      //    var query = SELECT ST_TRANSFORM(query, projection, mapProjecion)
      //

      // might need this as well: http://www.postgis.org/docs/ST_AsGeoJSON.html
      var query = "SELECT * FROM "+table+" WHERE "+table+"."+geom_field+" && ST_MakeEnvelope($1,$2,$3,$4);";

      client.query(query, [coords], function(err, result) {
        callback(err, result);
      });

    } else {
      callback(err, null);
    }
  });
}
<commit_msg>Rewrote with new structure, hardcoded incoming coordinates since our internal SRS is still whack. Not drawing<commit_after>var pg = require("pg");
var projector = require("../projector");
/*
 * Something like this eventually? 
 * https://github.com/mapbox/tilemill/blob/master/models/Layer.bones#L60
 */

var PostGISSource = function(options) {
  this._projection = options.projection;
  this._connectionString = options.connectionString; //required
  this._tableName = options.tableName; // requried
  this._geomField = options.geomField; // required
  this._attrFields = typeof options.fields === "object" ? options.fields.join(',') : options.fields; // array of attribute fields, or comma separated suggested for better performanace

  this.name = options.tableName;
  this.sourceName = this.name; //not sure which we're using 

  this._loadCallbacks = [];
  this._loading = false;
  this._lastResult = null;

  //state
  this._client = null;
  this._connectError = null;
  this._connect();
}

PostGISSource.prototype = {
  constructor: PostGISSource,

  _connect: function() {
    console.log("Connecting to postGIS "+this._connectionString);
    if (this._connectionString){
      pg.connect(this._connectionString, function(error, client){
        if (!error) {
          console.log("Connected");
          this._client = client;
        } else {
          console.warn("Error connecting", error);
          this._connectError = error;
        }
      }.bind(this));
    } else {
      console.warn("No connection string provided");
      this._connectError = "No connection string provided";
    }
  },

  // need some way to check projection equivalency programmatically so we can use built-in postgis projection i.e.
  //
  // check proj4 support with: SELECT PostGIS_Full_Version();
  // i.e. POSTGIS="1.3.3" GEOS="3.1.0-CAPI-1.5.0" PROJ="Rel. 4.4.9, 29 Oct 2004" USE_STATS
  // 
  // if (!projector.equals(projection,mapProjection){
  //    var query = SELECT ST_TRANSFORM(query, projection, mapProjecion)

  getShapes: function(minX, minY, maxX, maxY, mapProjection, callback) {
    // we don't get real coordinates from Map.js yet so we'll fake it for now
    // minX = -122.4565;
    // minY = 37.756;
    // maxX = -122.451;
    // maxY = 37.761;

    minX = -122.5195;
    minY = 37.7062;
    maxX = -122.3812;
    maxY = 37.8036;
    
    callback && this._loadCallbacks.push(callback);
    
    if (!this._connectError && !this._client) {
      this._connect();
    }

    if (!this._loading && !this._connectError && this._client) {
      this._loading = true;
      console.log("Loading features...");
      start = Date.now();

      if (this._attrFields) {
        var query = "SELECT ST_AsGeoJson("+this._geomField+") as geometry, "+this._attrFields+" FROM "+this._tableName+" WHERE "+this._geomField+" && ST_MakeEnvelope($1,$2,$3,$4);";
      } else {
        // TODO: use dynamic sql here to not select geometry twice
        // TODO: build this query once
        var query = "SELECT ST_AsGeoJson("+this._geomField+") as geometry,* FROM "+this._tableName+" WHERE "+this._geomField+" && ST_MakeEnvelope($1,$2,$3,$4);";
      }

      console.log("Querying... "+query+" "+minX+", "+minY+", "+maxX+", "+maxY);
      this._client.query(query, [minX, minY, maxX, maxY], function(error, result) {
        this._loading = false;
        console.log("Loaded in " + (Date.now() - start) + "ms");

        if (result) {
          this._lastResult = this._toGeoJson(result.rows);
          this._lastResult = projector.project.FeatureCollection(this._projection, mapProjection, this._lastResult);
        }

        var callbacks = this._loadCallbacks;
        callbacks.forEach(function(callback) {
          callback(error, this._lastResult);
        }.bind(this));
      }.bind(this));

    } else {
      var callbacks = this._loadCallbacks;
      callbacks.forEach(function(callback) {
        callback(this._connectError);
      }.bind(this));
    }
  },

  _toGeoJson: function(rows){
    var obj={};
    obj.type = "FeatureCollection";
    obj.features = [];
    rows.forEach(function(item){
      var feature = {};
      feature.type = "Feature";
      feature.properties = {};
      feature.geometry = JSON.parse(item.geometry);
      delete item.geometry;
      for (var key in item) {
        feature.properties[key] = item[key];
      }
      obj.features.push(feature);
    });
    return obj;
  }
}

module.exports = PostGISSource;
{'fraction_non_alphanumeric': 0.1447951645399597, 'fraction_numerical': 0.017461383478844864, 'mean_word_length': 2.793173713703515, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 2, 'lorem ipsum': 0, 'www.': 1, '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': '5793886', 'n_tokens_mistral': 2424, 'n_tokens_neox': 2288, 'n_words': 534}