问:
Javascript does not accept HTML String from MVC?
Javascript does not accept HTML String from MVC?
My MVC contoller from where I am sending the HTML template in string from txt file

```<code>using (StreamReader sr = new StreamReader(@"D:\Templates\NewGridTemplate.txt"))
            {
                // Read the stream to a string, and write the string to the console.
                obj.sGridTemplate = sr.ReadToEnd().Replace(Environment.NewLine, " ");
                //Console.WriteLine(line);
            }

            return View(obj);
</code>```

Actual code in csHTMl Javascript

```<code>  var sHTML=$(@Model.sGridTemplate);
</code>```

Below is screen shot for error . HTML string  is not accepted by Javascript. shows character "<" etc.. Please help let me know what I missed.Image 3

答:
You need to put your content within quotes so that it becomes a Javascript string, otherwise it'll be interpreted as syntax and you get the error because it's not valid JS syntax

```<code>var sHTML=$('@Model.sGridTemplate');
</code>```

And the problematic line in the resulting client-side code should look more like this:

```<code>var sHTML=$('    < ...
</code>```

... than:

```<code>var sHTML=$(    < ...
</code>```

Body:
Javascript does not accept HTML String from MVC?
My MVC contoller from where I am sending the HTML template in string from txt file

using (StreamReader sr = new StreamReader(@"D:\Templates\NewGridTemplate.txt"))
            {
                // Read the stream to a string, and write the string to the console.
                obj.sGridTemplate = sr.ReadToEnd().Replace(Environment.NewLine, " ");
                //Console.WriteLine(line);
            }

            return View(obj);

Actual code in csHTMl Javascript

  var sHTML=$(@Model.sGridTemplate);

Below is screen shot for error . HTML string  is not accepted by Javascript. shows character "<" etc.. Please help let me know what I missed.Image 3

Body:
You need to put your content within quotes so that it becomes a Javascript string, otherwise it'll be interpreted as syntax and you get the error because it's not valid JS syntax

var sHTML=$('@Model.sGridTemplate');

And the problematic line in the resulting client-side code should look more like this:

var sHTML=$('    &lt; ...

... than:

var sHTML=$(    &lt; ...


来源: stackexchange

问:
Re-activated virtual environment missing module
Here are my steps:

```<code>mkdir venv
virtualenv venv
source venv/bin/activate
pip install -e .
foo
# everything works
deactivate
source venv/bin/activate
pip install -e .
foo
#...
ImportError: No module named 'click'
</code>```

Here is my setup.py:

```<code>from setuptools import find_packages, setup

setup(
        author='...',
        author_email='...',
        entry_points={
            'console_scripts': [
                'foo=foo.cli:main']
            },
        name='foo',
        packages=find_packages(),
        version='0.0.0')
</code>```

I'm sure I'm missing something simple. It's not the first time I've used virtualenv but I've never had this problem.

答:
I don't know why it works the first time, just after virtualenv creation (I can't reproduce this bug). But at least install_requires=['Click'] is missing in your setup.py.

To fix that:

```<code>from setuptools import find_packages, setup

setup(
    author='...',
    author_email='...',
    entry_points={
        'console_scripts': [
            'foo=foo.cli:main']
    },
    name='foo',
    packages=find_packages(),
    version='0.0.0',
    install_requires=['Click']
)
</code>```

ContentLicense: CC BY-SA 3.0

Body:
Here are my steps:

mkdir venv
virtualenv venv
source venv/bin/activate
pip install -e .
foo
# everything works
deactivate
source venv/bin/activate
pip install -e .
foo
#...
ImportError: No module named 'click'

Here is my setup.py:

from setuptools import find_packages, setup

setup(
        author='...',
        author_email='...',
        entry_points={
            'console_scripts': [
                'foo=foo.cli:main']
            },
        name='foo',
        packages=find_packages(),
        version='0.0.0')

I'm sure I'm missing something simple. It's not the first time I've used virtualenv but I've never had this problem.

Body:
I don't know why it works the first time, just after virtualenv creation (I can't reproduce this bug). But at least install_requires=['Click'] is missing in your setup.py.

To fix that:

from setuptools import find_packages, setup

setup(
    author='...',
    author_email='...',
    entry_points={
        'console_scripts': [
            'foo=foo.cli:main']
    },
    name='foo',
    packages=find_packages(),
    version='0.0.0',
    install_requires=['Click']
)


问:
How to point a Chart.js plugin to different doughnut charts?
I found a Chart.js plugin that writes text in the middle of Chart.js doughnut chart, as below.

I have two doughnuts on the page. one called "myChart" and one called "secondChart". If I change the below code to point to the second chart if only points to the second chart.

But if I point it to the first chart is renders in both charts. Is there a way to change this plugin into a reusable function to use on multiple charts on a page?

```<code>  Chart.pluginService.register({
  beforeDraw: function(chart) {
    var width = chart.chart.width,
        height = chart.chart.height,
        ctx = chart.chart.ctx;

        ctx.restore();
        var fontSize = (height / 120).toFixed(2);
        ctx.font = fontSize + "em sans-serif";
        ctx.textBaseline = "middle";

     var text = "100%",
        textX = Math.round((width - ctx.measureText(text).width) / 2),
        textY = height / 2;

        ctx.fillText(text, textX, textY);
        ctx.save();
      }
    });
</code>```

答:
Try below code. Tested and working. Hope it helps :)</p>

```<code>   var doughnutCenterText = {
    beforeDraw: function (chart) {
    var width = chart.chart.width,
    height = chart.chart.height,
    ctx = chart.chart.ctx;

    ctx.restore();
    var fontSize = (height / 120).toFixed(2);
    ctx.font = fontSize + "em sans-serif";
    ctx.textBaseline = "middle";

    var text = "100%",
    textX = Math.round((width - ctx.measureText(text).width) / 2),
    textY = height / 2;

    ctx.fillText(text, textX, textY);
    ctx.save();
        }
    };

//Chart1
    this.doughnutChart1 = new Chart(this.doughnutCanvas1.nativeElement, {
        type: 'doughnut',
        data: {
            datasets: [{
                data: [65, 35],
                backgroundColor: [
                    'rgba(229, 57, 53, 1)',
                    'rgba(229, 57, 53, 0.2)',
                ],
                hoverBackgroundColor: [
                    'rgba(229, 57, 53, 1)',
                    'rgba(229, 57, 53, 0.2)',
                ],
                hoverBorderColor: [
                    '#fff',
                    '#fff'
                ]
            }]
        },
        plugins: [doughnutCenterText]    //Note here
    });

//Chart 2
    this.doughnutChart2 = new Chart(this.doughnutCanvas2.nativeElement, {
        type: 'doughnut',
        data: {
            datasets: [{
                data: [55, 45],
                backgroundColor: [
                    'rgba(0, 137, 123, 1)',
                    'rgba(0, 137, 123, 0.2)',
                ],
                hoverBackgroundColor: [
                    'rgba(0, 137, 123, 1)',
                    'rgba(0, 137, 123, 0.2)',
                ],
                hoverBorderColor: [
                    '#fff',
                    '#fff'
                ]
            }]
        },
        plugins: [doughnutCenterText]    //Note here
    });
</code>```

Body:
I found a Chart.js plugin that writes text in the middle of Chart.js doughnut chart, as below.

I have two doughnuts on the page. one called "myChart" and one called "secondChart". If I change the below code to point to the second chart if only points to the second chart.

But if I point it to the first chart is renders in both charts. Is there a way to change this plugin into a reusable function to use on multiple charts on a page?

  Chart.pluginService.register({
  beforeDraw: function(chart) {
    var width = chart.chart.width,
        height = chart.chart.height,
        ctx = chart.chart.ctx;

        ctx.restore();
        var fontSize = (height / 120).toFixed(2);
        ctx.font = fontSize + "em sans-serif";
        ctx.textBaseline = "middle";

     var text = "100%",
        textX = Math.round((width - ctx.measureText(text).width) / 2),
        textY = height / 2;

        ctx.fillText(text, textX, textY);
        ctx.save();
      }
    });

Body:
Try below code. Tested and working. Hope it helps :)

   var doughnutCenterText = {
    beforeDraw: function (chart) {
    var width = chart.chart.width,
    height = chart.chart.height,
    ctx = chart.chart.ctx;

    ctx.restore();
    var fontSize = (height / 120).toFixed(2);
    ctx.font = fontSize + "em sans-serif";
    ctx.textBaseline = "middle";

    var text = "100%",
    textX = Math.round((width - ctx.measureText(text).width) / 2),
    textY = height / 2;

    ctx.fillText(text, textX, textY);
    ctx.save();
        }
    };

//Chart1
    this.doughnutChart1 = new Chart(this.doughnutCanvas1.nativeElement, {
        type: 'doughnut',
        data: {
            datasets: [{
                data: [65, 35],
                backgroundColor: [
                    'rgba(229, 57, 53, 1)',
                    'rgba(229, 57, 53, 0.2)',
                ],
                hoverBackgroundColor: [
                    'rgba(229, 57, 53, 1)',
                    'rgba(229, 57, 53, 0.2)',
                ],
                hoverBorderColor: [
                    '#fff',
                    '#fff'
                ]
            }]
        },
        plugins: [doughnutCenterText]    //Note here
    });

//Chart 2
    this.doughnutChart2 = new Chart(this.doughnutCanvas2.nativeElement, {
        type: 'doughnut',
        data: {
            datasets: [{
                data: [55, 45],
                backgroundColor: [
                    'rgba(0, 137, 123, 1)',
                    'rgba(0, 137, 123, 0.2)',
                ],
                hoverBackgroundColor: [
                    'rgba(0, 137, 123, 1)',
                    'rgba(0, 137, 123, 0.2)',
                ],
                hoverBorderColor: [
                    '#fff',
                    '#fff'
                ]
            }]
        },
        plugins: [doughnutCenterText]    //Note here
    });


问:
Using java reflection to unit test that a specific class is used in a method implementation
I want to implement and unit test a method that aggregates some data using Java 8 Stream API (the Stream interface and Collectors class). See the code below:

```<code>import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class AggregationKata {

    public static Map<String, Double> getAverageGradeByDepartment(Stream<Student> students) {

        return students
                .collect(Collectors.groupingBy(Student::getDepartment,
                        Collectors.averagingDouble(Student::getGrade)));

    }
}
</code>```

I want to write a unit test that will enforce using the Stream API while implementing this method. In other words, Stream interface and Collectors class must be used. I guess I need to use java reflection in my unit test, but I cannot figure out how.

The question is - how do I write such a unit test? Thanks!

答:
What you want to do is not a unit test.

You don't want to test the behavior of your class.

You want ensure that the implementation follows a specific coding rule.

To address this requirement, you should rather define a rule in a tool designed to handle it (for example Sonar) or even a static Code Analysis tools in Jenkins at each commit.

By implementing a custom rule in Sonar, you use reflection and inspection of the source code but not directly (the API does the job for you).

For example :

```<code>@Override
public void visitNode(Tree tree) {
  MethodTree method = (MethodTree) tree;
  if (method.parameters().size() == 1) {
    MethodSymbol symbol = method.symbol();
    reportIssue(method.simpleName(), "Never do that!");
  }
}
</code>```

Body:
I want to implement and unit test a method that aggregates some data using Java 8 Stream API (the Stream interface and Collectors class). See the code below:

import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class AggregationKata {

    public static Map<String, Double> getAverageGradeByDepartment(Stream<Student> students) {

        return students
                .collect(Collectors.groupingBy(Student::getDepartment,
                        Collectors.averagingDouble(Student::getGrade)));

    }
}

I want to write a unit test that will enforce using the Stream API while implementing this method. In other words, Stream interface and Collectors class must be used. I guess I need to use java reflection in my unit test, but I cannot figure out how.

The question is - how do I write such a unit test? Thanks!

Body:
What you want to do is not a unit test.

You don't want to test the behavior of your class.

You want ensure that the implementation follows a specific coding rule.

To address this requirement, you should rather define a rule in a tool designed to handle it (for example Sonar) or even a static Code Analysis tools in Jenkins at each commit.

By implementing a custom rule in Sonar, you use reflection and inspection of the source code but not directly (the API does the job for you).

For example :

@Override
public void visitNode(Tree tree) {
  MethodTree method = (MethodTree) tree;
  if (method.parameters().size() == 1) {
    MethodSymbol symbol = method.symbol();
    reportIssue(method.simpleName(), "Never do that!");
  }
}


问:
Give any parameter to Vue.js via Blade (Laravel)
Is there any way to pass a variable down from my php blade template to a Vue component (not a child) like this?

```<code><component param="{{ $param }}"></component>
</code>```

in vue.js component:

```<code>props: ['param']
</code>```

I only get 'undefined'.

Thank you!

答:
It works just as I described. My problem was that I did not realise that HTML tags are not case sensitive. I had to correct

```<code><component paramId="{{ $paramId }}"></component>
</code>```

to

```<code><component param-id="{{ $paramId }}"></component>
</code>```

in order to access it via

```<code>props: ['tagId']
</code>```

Body:
Is there any way to pass a variable down from my php blade template to a Vue component (not a child) like this?

<component param="{{ $param }}"></component>

in vue.js component:

props: ['param']

I only get 'undefined'.

Thank you!

Body:
It works just as I described. My problem was that I did not realise that HTML tags are not case sensitive. I had to correct

<component paramId="{{ $paramId }}"></component>

to

<component param-id="{{ $paramId }}"></component>

in order to access it via

props: ['tagId']


问:
How to tell the debugger to ignore breaking on thrown exceptions?
I have a TextBox in which I validate the input with a third party library. However, this library throws custom exceptions when the syntax is incorrect. This is not a real big deal, except for when you are debugging.

When debugging, since the text in the TextBox will always be initially wrong (I am still typing it),  the debugger will stop after each letter until it is correct, which is really annoying as I validate with each letter.

How can I tell the debugger to not break at these custom exceptions?

P.S. I have already tried to filter the Debug -> Exceptions (added it in Common Language Runtime Exceptions), but this did not work for me. The debugger still stops at the line where the library is called.

P.P.S. Using Visual Studio 2010.

Answer:

In the end I was very close with my PS. It was a pretty silly mistake: I had a typo in the namespace. Thanks to Pop Catalin and Madhur Ahuja for pointing it out!

答:
There is an 'exceptions' window in
  Visual Studio ... try Ctrl-Alt-E when
  debugging and click on the 'Thrown'
  checkbox for the exception you want to
  stop on

You are looking for reverse of this:
Visual Studio: How to break on handled exceptions?

ContentLicense: CC BY-SA 2.5


问:
Pandas: how to deal with nan value when convert categories to numbers
Suppose I have dataframe like this and there is a significant number of categorical values (around 100) in favorite_food column, which includes nan value:

```<code>Name | favorite_food
Anna  | apple
Barbara | banana
Charlie | apple
Danie | nan
Emily | nan
............
```

My goal is to convert categorical value to numeric like this:
```<code>Name | favorite_food
Anna  | 1
Barbara | 2
Charlie | 1
Danie | 0
Emily | 0
............
```

So how should I modify this code df.favorite_food =df.favorite_food.astype('category')?
Or is there any other way to do?

答:
As per this link the default assignment to missing values is -1 which can be achieved with .cat.codes

You can use df.favorite_food =df.favorite_food.cat.codes for the given case, which will map the np.nan values to -1.

If you want to define a specific mapping(np.nan = 0- as you've stated), you can do that with a dictionary

Body:
Suppose I have dataframe like this and there is a significant number of categorical values (around 100) in favorite_food column, which includes nan value:

Name | favorite_food
Anna  | apple
Barbara | banana
Charlie | apple
Danie | nan
Emily | nan
............

My goal is to convert categorical value to numeric like this:

Name | favorite_food
Anna  | 1
Barbara | 2
Charlie | 1
Danie | 0
Emily | 0
............

So how should I modify this code df.favorite_food =df.favorite_food.astype('category')?
Or is there any other way to do?


问:
Load unpacked Chrome extension programmatically
Is it possible to load and unload unpacked Chrome extensions from the Command Line?</p>

答:
Try to kill all existing instances of Chrome from task manager : TASKKILL /IM chrome.exe /F and then chrome.exe --load-extension=path/to/extension should work

This working C# code for console application can help

```<code>class Program
    {
        static void Main(string[] args)
        {
            Process cmd = new Process();

            cmd.StartInfo.FileName = "cmd.exe";
            cmd.StartInfo.RedirectStandardInput = true;
            cmd.StartInfo.RedirectStandardOutput = true;
            cmd.StartInfo.CreateNoWindow = true;
            cmd.StartInfo.UseShellExecute = false;

            cmd.Start();
            //kill all chrome instances
            cmd.StandardInput.WriteLine("TASKKILL /IM chrome.exe /F");
            //path to chrome.exe
            cmd.StandardInput.WriteLine("cd C:\\Program Files (x86)\\Google\\Chrome\\Application");
            //load extension
            cmd.StandardInput.WriteLine("chrome.exe --load-extension={path-to-extension}");

            cmd.StandardInput.Flush();
            cmd.StandardInput.Close();
            Console.WriteLine(cmd.StandardOutput.ReadToEnd());

        }
    }
</code>```

ContentLicense: CC BY-SA 4.0

Body:
Try to kill all existing instances of Chrome from task manager : TASKKILL /IM chrome.exe /F and then chrome.exe --load-extension=path/to/extension should work

This working C# code for console application can help

class Program
    {
        static void Main(string[] args)
        {
            Process cmd = new Process();

            cmd.StartInfo.FileName = "cmd.exe";
            cmd.StartInfo.RedirectStandardInput = true;
            cmd.StartInfo.RedirectStandardOutput = true;
            cmd.StartInfo.CreateNoWindow = true;
            cmd.StartInfo.UseShellExecute = false;

            cmd.Start();
            //kill all chrome instances
            cmd.StandardInput.WriteLine("TASKKILL /IM chrome.exe /F");
            //path to chrome.exe
            cmd.StandardInput.WriteLine("cd C:\\Program Files (x86)\\Google\\Chrome\\Application");
            //load extension
            cmd.StandardInput.WriteLine("chrome.exe --load-extension={path-to-extension}");

            cmd.StandardInput.Flush();
            cmd.StandardInput.Close();
            Console.WriteLine(cmd.StandardOutput.ReadToEnd());

        }
    }


问:
How to do multiple parallel readers for data export using Google Spanner?
External Backups/Snapshots for Google Cloud Spanner recommends to use queries with timestamp bounds to create snapshots for export.  On the bottom of the Timestamp Bounds documentation it states:

Cloud Spanner continuously garbage collects deleted and overwritten data in the background to reclaim storage space. This process is known as version GC. By default, version GC reclaims versions after they are one hour old. Because of this, Cloud Spanner cannot perform reads at a read timestamp more than one hour in the past.

So any export would need to complete within an hour.  A single reader (i.e. select * from table; using timestamp X) would not be able to export the entire table within an hour.

How can multiple parallel readers be implemented in spanner?

Note:  It is mentioned in one of the comments that support for Apache Beam is coming, but it looks like that uses a single reader:

/** A simplest read function implementation. Parallelism support is coming. */

https://github.com/apache/beam/blob/master/sdks/java/io/google-cloud-platform/src/main/java/org/apache/beam/sdk/io/gcp/spanner/NaiveSpannerReadFn.java#L26

Is there a way to do the parallel reader that beam requires today using exising APIs?  Or will Beam need to use something that isn't released yet on google spanner?

答:
Edit 2018-03-30 - The example project has been updated to use the BatchClient offered by Google Cloud Spanner

After the release of the BatchClient for reading/downloading large amounts of data, the example project below has been updated to use the new batch client instead of the standard database client. The basic idea behind the project is still the same: Copy data to/from Cloud Spanner and any other database using standard jdbc functionality. The following code snippet sets the jdbc connection in batch read mode:

```<code>if (source.isWrapperFor(ICloudSpannerConnection.class))
{
    ICloudSpannerConnection con = source.unwrap(ICloudSpannerConnection.class);
    // Make sure no transaction is running
    if (!con.isBatchReadOnly())
    {
        if (con.getAutoCommit())
        {
            con.setAutoCommit(false);
        }
        else
        {
            con.commit();
        }
        con.setBatchReadOnly(true);
    }
}
</code>```

When the connection is in 'batch read only mode', the connection will use the BatchClient of Google Cloud Spanner instead of the standard database client. When one of the Statement#execute(String) or PreparedStatement#execute() methods are called (as these allow multiple result sets to be returned) the jdbc driver will create a partitioned query instead of a normal query. The results of this partitioned query will be a number of result sets (one per partition) that can be fetched by the Statement#getResultSet() and Statement#getMoreResults(int) methods.

```<code>Statement statement = source.createStatement();
boolean hasResults = statement.execute(select);
int workerNumber = 0;
while (hasResults)
{
    ResultSet rs = statement.getResultSet();
    PartitionWorker worker = new PartitionWorker("PartionWorker-" + workerNumber, config, rs, tableSpec, table, insertCols);
    workers.add(worker);
    hasResults = statement.getMoreResults(Statement.KEEP_CURRENT_RESULT);
    workerNumber++;
}
</code>```

The result sets that are returned by the Statement#execute(String) are not executed directly, but only after the first call to ResultSet#next(). Passing these result sets to separate worker threads ensures parallel download and copying of the data.

Original answer:

This project was initially created for conversion in the other direction (from a local database to Cloud Spanner), but as it uses JDBC for both source and destination it can also be used the other way around: Converting a Cloud Spanner database to a local PostgreSQL database. Large tables are converted in parallel using a thread pool.

The project uses this open source JDBC driver instead of the JDBC driver supplied by Google. The source Cloud Spanner JDBC connection is set to read-only mode and autocommit=false. This ensures that the connection automatically creates a read-only transaction using the current time as timestamp the first time you execute a query. All subsequent queries within the same (read-only) transaction will use the same timestamp giving you a consistent snapshot of your Google Cloud Spanner database.

It works as follows:

Set the source database to read-only transactional mode.

The convert(String catalog, String schema) method iterates over all
tables in the source database (Cloud Spanner)

For each table the number of records is determined, and depending on the size of the table, the table is copied using either the main thread of the application or by a worker pool.

The class UploadWorker is responsible for the parallel copying. Each worker is assigned a range of records from the table (for example rows 1 to 2,400). The range is selected by a select statement in this format: 'SELECT * FROM $TABLE ORDER BY $PK_COLUMNS LIMIT $BATCH_SIZE OFFSET $CURRENT_OFFSET'

Commit the read-only transaction on the source database after ALL tables have been converted.

Below is a code snippet of the most important parts.

```<code>public void convert(String catalog, String schema) throws SQLException
{
    int batchSize = config.getBatchSize();
    destination.setAutoCommit(false);
    // Set the source connection to transaction mode (no autocommit) and read-only
    source.setAutoCommit(false);
    source.setReadOnly(true);
    try (ResultSet tables = destination.getMetaData().getTables(catalog, schema, null, new String[] { "TABLE" }))
    {
        while (tables.next())
        {
            String tableSchema = tables.getString("TABLE_SCHEM");
            if (!config.getDestinationDatabaseType().isSystemSchema(tableSchema))
            {
                String table = tables.getString("TABLE_NAME");
                // Check whether the destination table is empty.
                int destinationRecordCount = getDestinationRecordCount(table);
                if (destinationRecordCount == 0 || config.getDataConvertMode() == ConvertMode.DropAndRecreate)
                {
                    if (destinationRecordCount > 0)
                    {
                        deleteAll(table);
                    }
                    int sourceRecordCount = getSourceRecordCount(getTableSpec(catalog, tableSchema, table));
                    if (sourceRecordCount > batchSize)
                    {
                        convertTableWithWorkers(catalog, tableSchema, table);
                    }
                    else
                    {
                        convertTable(catalog, tableSchema, table);
                    }
                }
                else
                {
                    if (config.getDataConvertMode() == ConvertMode.ThrowExceptionIfExists)
                        throw new IllegalStateException("Table " + table + " is not empty");
                    else if (config.getDataConvertMode() == ConvertMode.SkipExisting)
                        log.info("Skipping data copy for table " + table);
                }
            }
        }
    }
    source.commit();
}

private void convertTableWithWorkers(String catalog, String schema, String table) throws SQLException
{
    String tableSpec = getTableSpec(catalog, schema, table);
    Columns insertCols = getColumns(catalog, schema, table, false);
    Columns selectCols = getColumns(catalog, schema, table, true);
    if (insertCols.primaryKeyCols.isEmpty())
    {
        log.warning("Table " + tableSpec + " does not have a primary key. No data will be copied.");
        return;
    }
    log.info("About to copy data from table " + tableSpec);

    int batchSize = config.getBatchSize();
    int totalRecordCount = getSourceRecordCount(tableSpec);
    int numberOfWorkers = calculateNumberOfWorkers(totalRecordCount);
    int numberOfRecordsPerWorker = totalRecordCount / numberOfWorkers;
    if (totalRecordCount % numberOfWorkers > 0)
        numberOfRecordsPerWorker++;
    int currentOffset = 0;
    ExecutorService service = Executors.newFixedThreadPool(numberOfWorkers);
    for (int workerNumber = 0; workerNumber < numberOfWorkers; workerNumber++)
    {
        int workerRecordCount = Math.min(numberOfRecordsPerWorker, totalRecordCount - currentOffset);
        UploadWorker worker = new UploadWorker("UploadWorker-" + workerNumber, selectFormat, tableSpec, table,
                insertCols, selectCols, currentOffset, workerRecordCount, batchSize, source,
                config.getUrlDestination(), config.isUseJdbcBatching());
        service.submit(worker);
        currentOffset = currentOffset + numberOfRecordsPerWorker;
    }
    service.shutdown();
    try
    {
        service.awaitTermination(config.getUploadWorkerMaxWaitInMinutes(), TimeUnit.MINUTES);
    }
    catch (InterruptedException e)
    {
        log.severe("Error while waiting for workers to finish: " + e.getMessage());
        throw new RuntimeException(e);
    }

}

public class UploadWorker implements Runnable
{
private static final Logger log = Logger.getLogger(UploadWorker.class.getName());

private final String name;

private String selectFormat;

private String sourceTable;

private String destinationTable;

private Columns insertCols;

private Columns selectCols;

private int beginOffset;

private int numberOfRecordsToCopy;

private int batchSize;

private Connection source;

private String urlDestination;

private boolean useJdbcBatching;

UploadWorker(String name, String selectFormat, String sourceTable, String destinationTable, Columns insertCols,
        Columns selectCols, int beginOffset, int numberOfRecordsToCopy, int batchSize, Connection source,
        String urlDestination, boolean useJdbcBatching)
{
    this.name = name;
    this.selectFormat = selectFormat;
    this.sourceTable = sourceTable;
    this.destinationTable = destinationTable;
    this.insertCols = insertCols;
    this.selectCols = selectCols;
    this.beginOffset = beginOffset;
    this.numberOfRecordsToCopy = numberOfRecordsToCopy;
    this.batchSize = batchSize;
    this.source = source;
    this.urlDestination = urlDestination;
    this.useJdbcBatching = useJdbcBatching;
}

@Override
public void run()
{
    // Connection source = DriverManager.getConnection(urlSource);
    try (Connection destination = DriverManager.getConnection(urlDestination))
    {
        log.info(name + ": " + sourceTable + ": Starting copying " + numberOfRecordsToCopy + " records");

        destination.setAutoCommit(false);
        String sql = "INSERT INTO " + destinationTable + " (" + insertCols.getColumnNames() + ") VALUES \n";
        sql = sql + "(" + insertCols.getColumnParameters() + ")";
        PreparedStatement statement = destination.prepareStatement(sql);

        int lastRecord = beginOffset + numberOfRecordsToCopy;
        int recordCount = 0;
        int currentOffset = beginOffset;
        while (true)
        {
            int limit = Math.min(batchSize, lastRecord - currentOffset);
            String select = selectFormat.replace("$COLUMNS", selectCols.getColumnNames());
            select = select.replace("$TABLE", sourceTable);
            select = select.replace("$PRIMARY_KEY", selectCols.getPrimaryKeyColumns());
            select = select.replace("$BATCH_SIZE", String.valueOf(limit));
            select = select.replace("$OFFSET", String.valueOf(currentOffset));
            try (ResultSet rs = source.createStatement().executeQuery(select))
            {
                while (rs.next())
                {
                    int index = 1;
                    for (Integer type : insertCols.columnTypes)
                    {
                        Object object = rs.getObject(index);
                        statement.setObject(index, object, type);
                        index++;
                    }
                    if (useJdbcBatching)
                        statement.addBatch();
                    else
                        statement.executeUpdate();
                    recordCount++;
                }
                if (useJdbcBatching)
                    statement.executeBatch();
            }
            destination.commit();
            log.info(name + ": " + sourceTable + ": Records copied so far: " + recordCount + " of "
                    + numberOfRecordsToCopy);
            currentOffset = currentOffset + batchSize;
            if (recordCount >= numberOfRecordsToCopy)
                break;
        }
    }
    catch (SQLException e)
    {
        log.severe("Error during data copy: " + e.getMessage());
        throw new RuntimeException(e);
    }
    log.info(name + ": Finished copying");
}

}
</code>```

Body:
Edit 2018-03-30 - The example project has been updated to use the BatchClient offered by Google Cloud Spanner

After the release of the BatchClient for reading/downloading large amounts of data, the example project below has been updated to use the new batch client instead of the standard database client. The basic idea behind the project is still the same: Copy data to/from Cloud Spanner and any other database using standard jdbc functionality. The following code snippet sets the jdbc connection in batch read mode:

if (source.isWrapperFor(ICloudSpannerConnection.class))
{
    ICloudSpannerConnection con = source.unwrap(ICloudSpannerConnection.class);
    // Make sure no transaction is running
    if (!con.isBatchReadOnly())
    {
        if (con.getAutoCommit())
        {
            con.setAutoCommit(false);
        }
        else
        {
            con.commit();
        }
        con.setBatchReadOnly(true);
    }
}

When the connection is in 'batch read only mode', the connection will use the BatchClient of Google Cloud Spanner instead of the standard database client. When one of the Statement#execute(String) or PreparedStatement#execute() methods are called (as these allow multiple result sets to be returned) the jdbc driver will create a partitioned query instead of a normal query. The results of this partitioned query will be a number of result sets (one per partition) that can be fetched by the Statement#getResultSet() and Statement#getMoreResults(int) methods.

Statement statement = source.createStatement();
boolean hasResults = statement.execute(select);
int workerNumber = 0;
while (hasResults)
{
    ResultSet rs = statement.getResultSet();
    PartitionWorker worker = new PartitionWorker("PartionWorker-" + workerNumber, config, rs, tableSpec, table, insertCols);
    workers.add(worker);
    hasResults = statement.getMoreResults(Statement.KEEP_CURRENT_RESULT);
    workerNumber++;
}

The result sets that are returned by the Statement#execute(String) are not executed directly, but only after the first call to ResultSet#next(). Passing these result sets to separate worker threads ensures parallel download and copying of the data.

Original answer:

This project was initially created for conversion in the other direction (from a local database to Cloud Spanner), but as it uses JDBC for both source and destination it can also be used the other way around: Converting a Cloud Spanner database to a local PostgreSQL database. Large tables are converted in parallel using a thread pool.

The project uses this open source JDBC driver instead of the JDBC driver supplied by Google. The source Cloud Spanner JDBC connection is set to read-only mode and autocommit=false. This ensures that the connection automatically creates a read-only transaction using the current time as timestamp the first time you execute a query. All subsequent queries within the same (read-only) transaction will use the same timestamp giving you a consistent snapshot of your Google Cloud Spanner database.

It works as follows:

Set the source database to read-only transactional mode.

The convert(String catalog, String schema) method iterates over all
tables in the source database (Cloud Spanner)

For each table the number of records is determined, and depending on the size of the table, the table is copied using either the main thread of the application or by a worker pool.

The class UploadWorker is responsible for the parallel copying. Each worker is assigned a range of records from the table (for example rows 1 to 2,400). The range is selected by a select statement in this format: 'SELECT * FROM $TABLE ORDER BY $PK_COLUMNS LIMIT $BATCH_SIZE OFFSET $CURRENT_OFFSET'

Commit the read-only transaction on the source database after ALL tables have been converted.

Below is a code snippet of the most important parts.

public void convert(String catalog, String schema) throws SQLException
{
    int batchSize = config.getBatchSize();
    destination.setAutoCommit(false);
    // Set the source connection to transaction mode (no autocommit) and read-only
    source.setAutoCommit(false);
    source.setReadOnly(true);
    try (ResultSet tables = destination.getMetaData().getTables(catalog, schema, null, new String[] { "TABLE" }))
    {
        while (tables.next())
        {
            String tableSchema = tables.getString("TABLE_SCHEM");
            if (!config.getDestinationDatabaseType().isSystemSchema(tableSchema))
            {
                String table = tables.getString("TABLE_NAME");
                // Check whether the destination table is empty.
                int destinationRecordCount = getDestinationRecordCount(table);
                if (destinationRecordCount == 0 || config.getDataConvertMode() == ConvertMode.DropAndRecreate)
                {
                    if (destinationRecordCount > 0)
                    {
                        deleteAll(table);
                    }
                    int sourceRecordCount = getSourceRecordCount(getTableSpec(catalog, tableSchema, table));
                    if (sourceRecordCount > batchSize)
                    {
                        convertTableWithWorkers(catalog, tableSchema, table);
                    }
                    else
                    {
                        convertTable(catalog, tableSchema, table);
                    }
                }
                else
                {
                    if (config.getDataConvertMode() == ConvertMode.ThrowExceptionIfExists)
                        throw new IllegalStateException("Table " + table + " is not empty");
                    else if (config.getDataConvertMode() == ConvertMode.SkipExisting)
                        log.info("Skipping data copy for table " + table);
                }
            }
        }
    }
    source.commit();
}

private void convertTableWithWorkers(String catalog, String schema, String table) throws SQLException
{
    String tableSpec = getTableSpec(catalog, schema, table);
    Columns insertCols = getColumns(catalog, schema, table, false);
    Columns selectCols = getColumns(catalog, schema, table, true);
    if (insertCols.primaryKeyCols.isEmpty())
    {
        log.warning("Table " + tableSpec + " does not have a primary key. No data will be copied.");
        return;
    }
    log.info("About to copy data from table " + tableSpec);

    int batchSize = config.getBatchSize();
    int totalRecordCount = getSourceRecordCount(tableSpec);
    int numberOfWorkers = calculateNumberOfWorkers(totalRecordCount);
    int numberOfRecordsPerWorker = totalRecordCount / numberOfWorkers;
    if (totalRecordCount % numberOfWorkers > 0)
        numberOfRecordsPerWorker++;
    int currentOffset = 0;
    ExecutorService service = Executors.newFixedThreadPool(numberOfWorkers);
    for (int workerNumber = 0; workerNumber < numberOfWorkers; workerNumber++)
    {
        int workerRecordCount = Math.min(numberOfRecordsPerWorker, totalRecordCount - currentOffset);
        UploadWorker worker = new UploadWorker("UploadWorker-" + workerNumber, selectFormat, tableSpec, table,
                insertCols, selectCols, currentOffset, workerRecordCount, batchSize, source,
                config.getUrlDestination(), config.isUseJdbcBatching());
        service.submit(worker);
        currentOffset = currentOffset + numberOfRecordsPerWorker;
    }
    service.shutdown();
    try
    {
        service.awaitTermination(config.getUploadWorkerMaxWaitInMinutes(), TimeUnit.MINUTES);
    }
    catch (InterruptedException e)
    {
        log.severe("Error while waiting for workers to finish: " + e.getMessage());
        throw new RuntimeException(e);
    }

}

public class UploadWorker implements Runnable
{
private static final Logger log = Logger.getLogger(UploadWorker.class.getName());

private final String name;

private String selectFormat;

private String sourceTable;

private String destinationTable;

private Columns insertCols;

private Columns selectCols;

private int beginOffset;

private int numberOfRecordsToCopy;

private int batchSize;

private Connection source;

private String urlDestination;

private boolean useJdbcBatching;

UploadWorker(String name, String selectFormat, String sourceTable, String destinationTable, Columns insertCols,
        Columns selectCols, int beginOffset, int numberOfRecordsToCopy, int batchSize, Connection source,
        String urlDestination, boolean useJdbcBatching)
{
    this.name = name;
    this.selectFormat = selectFormat;
    this.sourceTable = sourceTable;
    this.destinationTable = destinationTable;
    this.insertCols = insertCols;
    this.selectCols = selectCols;
    this.beginOffset = beginOffset;
    this.numberOfRecordsToCopy = numberOfRecordsToCopy;
    this.batchSize = batchSize;
    this.source = source;
    this.urlDestination = urlDestination;
    this.useJdbcBatching = useJdbcBatching;
}

@Override
public void run()
{
    // Connection source = DriverManager.getConnection(urlSource);
    try (Connection destination = DriverManager.getConnection(urlDestination))
    {
        log.info(name + ": " + sourceTable + ": Starting copying " + numberOfRecordsToCopy + " records");

        destination.setAutoCommit(false);
        String sql = "INSERT INTO " + destinationTable + " (" + insertCols.getColumnNames() + ") VALUES \n";
        sql = sql + "(" + insertCols.getColumnParameters() + ")";
        PreparedStatement statement = destination.prepareStatement(sql);

        int lastRecord = beginOffset + numberOfRecordsToCopy;
        int recordCount = 0;
        int currentOffset = beginOffset;
        while (true)
        {
            int limit = Math.min(batchSize, lastRecord - currentOffset);
            String select = selectFormat.replace("$COLUMNS", selectCols.getColumnNames());
            select = select.replace("$TABLE", sourceTable);
            select = select.replace("$PRIMARY_KEY", selectCols.getPrimaryKeyColumns());
            select = select.replace("$BATCH_SIZE", String.valueOf(limit));
            select = select.replace("$OFFSET", String.valueOf(currentOffset));
            try (ResultSet rs = source.createStatement().executeQuery(select))
            {
                while (rs.next())
                {
                    int index = 1;
                    for (Integer type : insertCols.columnTypes)
                    {
                        Object object = rs.getObject(index);
                        statement.setObject(index, object, type);
                        index++;
                    }
                    if (useJdbcBatching)
                        statement.addBatch();
                    else
                        statement.executeUpdate();
                    recordCount++;
                }
                if (useJdbcBatching)
                    statement.executeBatch();
            }
            destination.commit();
            log.info(name + ": " + sourceTable + ": Records copied so far: " + recordCount + " of "
                    + numberOfRecordsToCopy);
            currentOffset = currentOffset + batchSize;
            if (recordCount >= numberOfRecordsToCopy)
                break;
        }
    }
    catch (SQLException e)
    {
        log.severe("Error during data copy: " + e.getMessage());
        throw new RuntimeException(e);
    }
    log.info(name + ": Finished copying");
}

}


问:
Is it possible to images position like this (Possibly without float)?
I am trying to position images in the following way starting from Left to Right and also keep it in the center of the screen:

However, I cannot get it to do that instead the last image always appears in the center of the row like in the image below:

Is there a way to be able to display it like that but also keep it in the CENTER of the screen?

I am using display: inline-block in #gallery > div

CODE: https://jsfiddle.net/m9xuj8aa/

HTML:

```<code><div class="container">
            <header>
                <div id="logo">
                    <img src="" alt="">
                </div>
                <nav class="cl-effect-21">
                    <ul>
                        <li>
                            <a href="index.html" class="scroll">
                                <span data-hover="Home">Home</span>
                            </a>
                        </li>
                        <li>
                            <a href="#about" class="scroll">
                                <span data-hover="About Us">About Us</span>
                            </a>
                        </li>
                        <li>
                            <a href="#services" class="scroll">
                                <span data-hover="Services">Services</span>
                            </a>
                        </li>
                        <li>
                            <a href="Portfolio.html" class="scroll">
                                <span data-hover="Portfolio">Portfolio</span>
                            </a>
                        </li>
                        <li>
                            <a href="#testimonials" class="scroll">
                                <span data-hover="Testimonials">Testimonials</span>
                            </a>
                        </li>
                        <li>
                            <a href="Contact.html" class="scroll active">
                                <span data-hover="Contact Us">Contact Us</span>
                            </a>
                        </li>
                    </ul>
                </nav>
            </header>

            <div class="portfolio clearfix">
                <div id="gallery">
                    <div id="img-wrapper">
                        <a href="assets/images/DesiGotTalent3/1.jpg">
                            <img src="assets/images/DesiGotTalent3/1.jpg" alt="">
                            <div id="overlay">
                                <h1 class="fa fa-search"></h1>
                            </div>
                        </a>
                    </div>
                    <div id="img-wrapper">
                        <a href="assets/images/DesiGotTalent3/2.jpg">
                            <img src="assets/images/DesiGotTalent3/2.jpg" alt="">
                            <div id="overlay">
                                <h1 class="fa fa-search"></h1>
                            </div>
                        </a>
                    </div>

                    <div id="img-wrapper">
                        <a href="assets/images/DesiGotTalent3/3.jpg">
                            <img src="assets/images/DesiGotTalent3/3.jpg" alt="">
                            <div id="overlay">
                                <h1 class="fa fa-search"></h1>
                            </div>
                        </a>
                    </div>
                    <div id="img-wrapper">
                        <a href="assets/images/DesiGotTalent3/4.jpg">
                            <img src="assets/images/DesiGotTalent3/4.jpg" alt="">
                            <div id="overlay">
                                <h1 class="fa fa-search"></h1>
                            </div>
                        </a>
                    </div>
                    <div id="img-wrapper">
                        <a href="assets/images/DesiGotTalent3/5.jpg">
                            <img src="assets/images/DesiGotTalent3/5.jpg" alt="">
                            <div id="overlay">
                                <h1 class="fa fa-search"></h1>
                            </div>
                        </a>
                    </div>
                    <div id="img-wrapper">
                        <a href="assets/images/DesiGotTalent3/6.jpg">
                            <img src="assets/images/DesiGotTalent3/6.jpg" alt="">
                            <div id="overlay">
                                <h1 class="fa fa-search"></h1>
                            </div>
                        </a>
                    </div>
                    <div id="img-wrapper">
                        <a href="assets/images/DesiGotTalent3/7.jpg">
                            <img src="assets/images/DesiGotTalent3/7.jpg" alt="">
                            <div id="overlay">
                                <h1 class="fa fa-search"></h1>
                            </div>
                        </a>
                    </div>
                    <div id="img-wrapper">
                        <a href="assets/images/DesiGotTalent3/8.jpg">
                            <img src="assets/images/DesiGotTalent3/8.jpg" alt="">
                            <div id="overlay">
                                <h1 class="fa fa-search"></h1>
                            </div>
                        </a>
                    </div>
                    <div id="img-wrapper" class="last">
                        <a href="assets/images/DesiGotTalent3/9.jpg">
                            <img src="assets/images/DesiGotTalent3/9.jpg" alt="">
                            <div id="overlay">
                                <h1 class="fa fa-search"></h1>
                            </div>
                        </a>
                    </div>
                </div>
            </div>
      <div class="push"></div>
        </div>
        <footer>
            <div id="social">
                <span class="fa fa-facebook"></span>
                <span class="fa fa-instagram"></span>
                <span class="fa fa-vimeo"></span>
                <span class="fa fa-youtube"></span>
            </div>

            <h3>© 2016 Dinesh Joshi Photography</h3>
        </footer>
</code>```

CSS:

```<code>/** External Stylesheet **/
* { margin: 0; }
html, body { height: 100%; }

.container {
    min-height: 100%;
    margin: 0 auto -60px;
}

footer, .push {
    height: 20px;
    padding: 20px 0px;
}

footer {
    font-size: 10px;
    text-align: center;
}

#social {
    margin-bottom: 5px;
}

#social span {
    border: 1px solid rgba(0,0,0,.2);
    margin: 0px 3px;
    font-size: 1.6em;
    width: 1.6em;
    text-align: center;
    line-height: 1.6em;
    background: #D4AF37;
    color: white;
    border-radius: 50%;
}

/** Header **/
header {
    padding-top: 30px;
}

ul {
    text-align: center;
}

ul li {
    display: inline-block;
    font-family: 'Roboto', sans-serif;
    text-transform: uppercase;
    font-size: 12px;
    letter-spacing: 1px;
    margin: 0px 8px;
}

nav a {
    position: relative;
    display: inline-block;
    outline: none;
    color: black;
    text-decoration: none;
    text-transform: uppercase;
    letter-spacing: 1px;
    font-weight: 400;
    text-shadow: 0 0 1px rgba(255,255,255,0.3);
    font-size: 12px;
    font-family: 'Roboto', sans-serif;
}

nav a:hover,
nav a:focus {
    outline: none;
}

/* Effect 21: borders slight translate */
.cl-effect-21 a {
    padding: 10px;
    color: black;
    font-weight: 400;
    text-shadow: none;
    -webkit-transition: color 0.3s;
    -moz-transition: color 0.3s;
    transition: color 0.3s;
}

.cl-effect-21 a::before,
.cl-effect-21 a::after {
    position: absolute;
    left: 0;
    width: 100%;
    height: 1.2px;
    background: #D4AF37;
    content: '';
    opacity: 0;
    -webkit-transition: opacity 0.3s, -webkit-transform 0.3s;
    -moz-transition: opacity 0.3s, -moz-transform 0.3s;
    transition: opacity 0.3s, transform 0.3s;
    -webkit-transform: translateY(-10px);
    -moz-transform: translateY(-10px);
    transform: translateY(-10px);
}

.active {
    border-top: 1.2px solid #D4A347;
    border-bottom: 1.2px solid #D4A347;
}

.cl-effect-21 a::before {
    top: 0;
    -webkit-transform: translateY(-10px);
    -moz-transform: translateY(-10px);
    transform: translateY(-10px);
}

.cl-effect-21 a::after {
    bottom: 0;
    -webkit-transform: translateY(10px);
    -moz-transform: translateY(10px);
    transform: translateY(10px);
}
.cl-effect-21 a:hover::before,
.cl-effect-21 a:focus::before,
.cl-effect-21 a:hover::after,
.cl-effect-21 a:focus::after {
    opacity: 1;
    -webkit-transform: translateY(0px);
    -moz-transform: translateY(0px);
    transform: translateY(0px);
}

/* End of external stylesheet */
.portfolio {
                width: 100%;
                margin:0 auto;
            }

            #gallery {
                width: 100%;
                margin:0 auto;
                padding: 0px 10px;
                display: table;
                text-align: center;
            }

            #gallery img {
                width: 100%;
                height: auto;
            }

            #gallery > div {
        width: 150px;
        height: 140px;
        display:inline-block;
        vertical-align:top;
        background-color:black;
        margin: 5px;
            }

            #gallery a div {
                position:absolute;
                width: 150px;
                margin:0 auto;
                text-align: center;
                top: 0;
                right:0;
                left:0;
                bottom:0;
                z-index: 1;
                transform: translate(-110%, 0);
                -webkit-transition: all .3s ease-in-out;
        display:none;
            }

            #gallery a:hover #overlay {
                background-color:rgba(212, 175, 55, .3);
                transform: translate(0,0);
            }

            #gallery div:nth-of-type(9) {
                text-align: left;
            }

            #gallery h1 {
                font-size: 20px;
                color:white;
                margin:3.6em 0px;
            }

            .clearfix {
                clear: both;
            }
</code>```

答:
I figured it out. It seems the images were of different sizes and therefore weren't able to float from left to right properly.

Fixed by adding explicit height to the images

Body:
I am trying to position images in the following way starting from Left to Right and also keep it in the center of the screen:

However, I cannot get it to do that instead the last image always appears in the center of the row like in the image below:

Is there a way to be able to display it like that but also keep it in the CENTER of the screen?

I am using display: inline-block in #gallery > div

CODE: https://jsfiddle.net/m9xuj8aa/

HTML:

                                Home

                                About Us

                                Services

                                Portfolio

                                Testimonials

                                Contact Us

© 2016 Dinesh Joshi Photography

CSS:

/** External Stylesheet **/
* { margin: 0; }
html, body { height: 100%; }

.container {
    min-height: 100%;
    margin: 0 auto -60px;
}

footer, .push {
    height: 20px;
    padding: 20px 0px;
}

footer {
    font-size: 10px;
    text-align: center;
}

#social {
    margin-bottom: 5px;
}

#social span {
    border: 1px solid rgba(0,0,0,.2);
    margin: 0px 3px;
    font-size: 1.6em;
    width: 1.6em;
    text-align: center;
    line-height: 1.6em;
    background: #D4AF37;
    color: white;
    border-radius: 50%;
}

/** Header **/
header {
    padding-top: 30px;
}

ul {
    text-align: center;
}

ul li {
    display: inline-block;
    font-family: 'Roboto', sans-serif;
    text-transform: uppercase;
    font-size: 12px;
    letter-spacing: 1px;
    margin: 0px 8px;
}

nav a {
    position: relative;
    display: inline-block;
    outline: none;
    color: black;
    text-decoration: none;
    text-transform: uppercase;
    letter-spacing: 1px;
    font-weight: 400;
    text-shadow: 0 0 1px rgba(255,255,255,0.3);
    font-size: 12px;
    font-family: 'Roboto', sans-serif;
}

nav a:hover,
nav a:focus {
    outline: none;
}

/* Effect 21: borders slight translate */
.cl-effect-21 a {
    padding: 10px;
    color: black;
    font-weight: 400;
    text-shadow: none;
    -webkit-transition: color 0.3s;
    -moz-transition: color 0.3s;
    transition: color 0.3s;
}

.cl-effect-21 a::before,
.cl-effect-21 a::after {
    position: absolute;
    left: 0;
    width: 100%;
    height: 1.2px;
    background: #D4AF37;
    content: '';
    opacity: 0;
    -webkit-transition: opacity 0.3s, -webkit-transform 0.3s;
    -moz-transition: opacity 0.3s, -moz-transform 0.3s;
    transition: opacity 0.3s, transform 0.3s;
    -webkit-transform: translateY(-10px);
    -moz-transform: translateY(-10px);
    transform: translateY(-10px);
}

.active {
    border-top: 1.2px solid #D4A347;
    border-bottom: 1.2px solid #D4A347;
}

.cl-effect-21 a::before {
    top: 0;
    -webkit-transform: translateY(-10px);
    -moz-transform: translateY(-10px);
    transform: translateY(-10px);
}

.cl-effect-21 a::after {
    bottom: 0;
    -webkit-transform: translateY(10px);
    -moz-transform: translateY(10px);
    transform: translateY(10px);
}
.cl-effect-21 a:hover::before,
.cl-effect-21 a:focus::before,
.cl-effect-21 a:hover::after,
.cl-effect-21 a:focus::after {
    opacity: 1;
    -webkit-transform: translateY(0px);
    -moz-transform: translateY(0px);
    transform: translateY(0px);
}

/* End of external stylesheet */
.portfolio {
                width: 100%;
                margin:0 auto;
            }

            #gallery {
                width: 100%;
                margin:0 auto;
                padding: 0px 10px;
                display: table;
                text-align: center;
            }

            #gallery img {
                width: 100%;
                height: auto;
            }

            #gallery > div {
        width: 150px;
        height: 140px;
        display:inline-block;
        vertical-align:top;
        background-color:black;
        margin: 5px;
            }

            #gallery a div {
                position:absolute;
                width: 150px;
                margin:0 auto;
                text-align: center;
                top: 0;
                right:0;
                left:0;
                bottom:0;
                z-index: 1;
                transform: translate(-110%, 0);
                -webkit-transition: all .3s ease-in-out;
        display:none;
            }

            #gallery a:hover #overlay {
                background-color:rgba(212, 175, 55, .3);
                transform: translate(0,0);
            }

            #gallery div:nth-of-type(9) {
                text-align: left;
            }

            #gallery h1 {
                font-size: 20px;
                color:white;
                margin:3.6em 0px;
            }

            .clearfix {
                clear: both;
            }


问:
Join two tables, where one is not uniqe
Hey everyone. I need to join two tables according to those parameters:

1) I need only data that are both in the first and in the second table

2) Data in the second table can have more rows attached to one row of the first table, but I need those rows displayed only once.

I tried this

```<code>SELECT * FROM table AS p
            JOIN `table2` AS ps ON (p.id = ps.`id_table2`)
            ORDER BY p.id
</code>```

but I am getting duplicates, as mentioned.

Thanks

答:
Assuming MySQL:

```<code>SELECT  *
FROM    table1 t1
JOIN    table2 t2
ON      t2.id =
        (
        SELECT  id
        FROM    table2 t2i
        WHERE   t2i.id_table2 = t1.id
        ORDER BY
                id
        LIMIT 1
        )
</code>```

Change ORDER BY clause to define which of the multiple records do you want.

In SQL Server, Oracle and PostgreSQL (8.4+), use this syntax:

```<code>SELECT  *
FROM    (
        SELECT  *, ROW_NUMBER() OVER (PARTITION BY t1.id ORDER BY t2.id) AS rn
        FROM    table1 t1
        JOIN    table2 t2
        ON      t2.id_table2 = t1.id
        ) q
WHERE   rn = 1
</code>```

Again, change ORDER BY accordingly.

Title: Join two tables, where one is not uniqe

Body:
Hey everyone. I need to join two tables according to those parameters:

1) I need only data that are both in the first and in the second table

2) Data in the second table can have more rows attached to one row of the first table, but I need those rows displayed only once.

I tried this

SELECT * FROM table AS p
            JOIN `table2` AS ps ON (p.id = ps.`id_table2`)
            ORDER BY p.id

but I am getting duplicates, as mentioned.

Thanks

Body:
Assuming MySQL:

SELECT  *
FROM    table1 t1
JOIN    table2 t2
ON      t2.id =
        (
        SELECT  id
        FROM    table2 t2i
        WHERE   t2i.id_table2 = t1.id
        ORDER BY
                id
        LIMIT 1
        )

Change ORDER BY clause to define which of the multiple records do you want.

In SQL Server, Oracle and PostgreSQL (8.4+), use this syntax:

SELECT  *
FROM    (
        SELECT  *, ROW_NUMBER() OVER (PARTITION BY t1.id ORDER BY t2.id) AS rn
        FROM    table1 t1
        JOIN    table2 t2
        ON      t2.id_table2 = t1.id
        ) q
WHERE   rn = 1

Again, change ORDER BY accordingly.


问:
Automate data pull from App Annie API issue
I am needing to automate a daily pull of app Annie data reviews and land them in S3. With the below I am trying to see if I can just pull one days worth of data but am getting an error 'TypeError: expected string or buffer'. I am new to python, can someone explain what I am doing wrong or another way to accomplish what I am trying to do?</p>

```<code>import json
import requests

url = 'https://api.appannie.com/v1.2/apps/ios/app/331177714/reviews?
start_date=2016-1-01&end_date=2016-6-26&countries=US'
key = 'Authorization: bearer 585e46.....'

response = requests.get(url,
                        headers = {'Authorization':'bearer 585e46.....'})

data = json.loads(response.json())
</code>```

答:
.json method you're using comes from requests object and it already converts string to proper json. So you can do two things

Convert to json with requests object method:
data = response.json()

Get text from your response and turn into json with Python json lib:
data = json.loads(response.text)

Body:
I am needing to automate a daily pull of app Annie data reviews and land them in S3. With the below I am trying to see if I can just pull one days worth of data but am getting an error 'TypeError: expected string or buffer'. I am new to python, can someone explain what I am doing wrong or another way to accomplish what I am trying to do?

import json
import requests

url = 'https://api.appannie.com/v1.2/apps/ios/app/331177714/reviews?
start_date=2016-1-01&end_date=2016-6-26&countries=US'
key = 'Authorization: bearer 585e46.....'

response = requests.get(url,
                        headers = {'Authorization':'bearer 585e46.....'})

data = json.loads(response.json())


答:
Reflection can not access methods bodies. So it can't be used enforce specific implementations.

The only way to analyse the methods bodies is source code analysis (a parser + constraints), or if the code is already compiled byte code analysis.

So use a parser for java and implement the necessary constraints you want; or use a byte code tool like asm.

In my opinion byte code analysis is easier than source code, so i would use asm.

Here rather primitice example of how it could look, that code will print [java/util/stream/Collectors::groupingBy, java/util/stream/Stream::collect, java/util/stream/Collectors::averagingDouble] for your example. (Requires org.ow2.asm:asm:jar:5.2)

```<code>public static class MethodsCalledClassVisitor extends ClassVisitor {
    private Set<String> methodsCalled = new HashSet<>();

    public MethodsCalledClassVisitor() {
        super(Opcodes.ASM5);
    }

    @Override
    public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
        if ("getAverageGradeByDepartment".equals(name)) {
            return new MyMethodVisitor(this);
        } else {
            return super.visitMethod(access, name, desc, signature, exceptions);
        }
    }

    public void addMethodCalled(String methodCall) {
        methodsCalled.add(methodCall);
    }

    public Set<String> getMethodsCalled() {
        return methodsCalled;
    }
}

public static class MyMethodVisitor extends MethodVisitor {
    private final MethodsCalledClassVisitor visit;

    public MyMethodVisitor(MethodsCalledClassVisitor visit) {
        super(Opcodes.ASM5);
        this.visit = visit;
    }

    @Override
    public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {
        visit.addMethodCalled(owner + "::" + name);
        super.visitMethodInsn(opcode, owner, name, desc, itf);
    }

}

public static void main(String[] args) throws IOException {
    ClassReader reader = new ClassReader(AggregationKata.class.getName());

    MethodsCalledClassVisitor classVisitor = new MethodsCalledClassVisitor();
    reader.accept(classVisitor, 0);
    System.out.println(classVisitor.getMethodsCalled());
}
</code>```

Title: Using java reflection to unit test that a specific class is used in a method implementation

Body:
Reflection can not access methods bodies. So it can't be used enforce specific implementations.

The only way to analyse the methods bodies is source code analysis (a parser + constraints), or if the code is already compiled byte code analysis.

So use a parser for java and implement the necessary constraints you want; or use a byte code tool like asm.

In my opinion byte code analysis is easier than source code, so i would use asm.

Here rather primitice example of how it could look, that code will print [java/util/stream/Collectors::groupingBy, java/util/stream/Stream::collect, java/util/stream/Collectors::averagingDouble] for your example. (Requires org.ow2.asm:asm:jar:5.2)

public static class MethodsCalledClassVisitor extends ClassVisitor {
    private Set<String> methodsCalled = new HashSet<>();

    public MethodsCalledClassVisitor() {
        super(Opcodes.ASM5);
    }

    @Override
    public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
        if ("getAverageGradeByDepartment".equals(name)) {
            return new MyMethodVisitor(this);
        } else {
            return super.visitMethod(access, name, desc, signature, exceptions);
        }
    }

    public void addMethodCalled(String methodCall) {
        methodsCalled.add(methodCall);
    }

    public Set<String> getMethodsCalled() {
        return methodsCalled;
    }
}

public static class MyMethodVisitor extends MethodVisitor {
    private final MethodsCalledClassVisitor visit;

    public MyMethodVisitor(MethodsCalledClassVisitor visit) {
        super(Opcodes.ASM5);
        this.visit = visit;
    }

    @Override
    public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {
        visit.addMethodCalled(owner + "::" + name);
        super.visitMethodInsn(opcode, owner, name, desc, itf);
    }

}

public static void main(String[] args) throws IOException {
    ClassReader reader = new ClassReader(AggregationKata.class.getName());

    MethodsCalledClassVisitor classVisitor = new MethodsCalledClassVisitor();
    reader.accept(classVisitor, 0);
    System.out.println(classVisitor.getMethodsCalled());
}


问:
MySQL queries waiting for other queries to finish
We have 30-40 different projects in Python and PHP that update, insert and select more than 1 million rows of data in MySQL DB every day.

Currently we use InnoDB Engine for our tables.

The problem: we have peaks in MySQL when almost all projects are working and lots of queries are processing in DB. There are main queries that are very important to finish ASAP (high priority) and queries that can wait for finish of main queries (less priority).
But as they go to MySQL concurrent it causes main queries to wait finishing of less priority queries.

Questions:

Is there any possibility to release all lock in tables before executing main queries (so they can finish ASAP)? or create locks if it help?

Can we pause the less priority queries execution when start execution main queries automatically?

Can use HIGH_PRIORITY and LOW_PRIORITY in queries help?

Are there some configurations in MySQL that can help?

Can changing tables to MyISAM or other DB engine help?

Let me know your thoughts and ideas.

答:
it's hard giving a definitive answer without the locking queries.
If you could add them it will be more useful.
Several things you can look into:
Look for locking statements such as "select for update", "insert on conflict update" etc...
-many times it's better to catch an exception on the application side then let the db do extra work.

the read concurrency: it could be that "read-committed " is enough for you and it takes less locks.

If you have replication- dedicate instances according to usage (e.g. Critical only server)

Regards
Jony


问:
Mysql: LIKE CONCAT Replacement --> less performance heavy
So I have a SELECT Statement that is comparing the current column content from the table_1 column "table_1_content" with the content of another column (table_2_content) in table_2, whereas content in "table_2_content" can be found anywhere in "table_1_content":

```<code>$select = "SELECT * FROM table_1, table_2 WHERE `table_1_content` LIKE CONCAT('%', table_2_content, '%')";
$result = mysqli_query($con, $select);
</code>```

My problem is that LIKE CONCAT is pretty performance heavy.

Is there another way to search through two columns from different tables, so that no full table scan is performed every time the query is executed?

答:
The LIKE in total free text format (% at the start and at the end of the search string) is the performance heavy part. Is the wildcard at the start of the string necessary? If so: You might have to consider pre-processing the data in a different way so that the search can use a single wildcard or no wildcard at all. This last part (depending on the data) is for example done by splitting the string by a delimiter and storing the data in separate rows, after which a much faster comparison and indexes are possible to be used.

To put data in multiple rows, we would assume a usable separator (can be multiple, the code just gets longer):

```<code>CREATE TABLE baseinfo (id INT NOT NULL auto_increment primary key,
  some other columns);

CREATE TABLE explodedstring(id INT NOT NULL, str VARCHAR(200),
   FOREIGN KEY (id) REFERENCES baseinfo(id));

CREATE PROCEDURE explodestring(id int, fullstr VARCHAR(4000))
BEGIN
  {many examples exist already how to do this on SO}
END;
</code>```

The procedure would take as input your key from the original data (id in this case), and the original string.
The output of the procedure would end up in a secondary table explodedstring against which you now could run a normal select (add some index for performance). The resulting ids would tell you which record would match.

Body:
So I have a SELECT Statement that is comparing the current column content from the table_1 column "table_1_content" with the content of another column (table_2_content) in table_2, whereas content in "table_2_content" can be found anywhere in "table_1_content":

$select = "SELECT * FROM table_1, table_2 WHERE `table_1_content` LIKE CONCAT('%', table_2_content, '%')";
$result = mysqli_query($con, $select);

My problem is that LIKE CONCAT is pretty performance heavy.

Is there another way to search through two columns from different tables, so that no full table scan is performed every time the query is executed?

Body:
The LIKE in total free text format (% at the start and at the end of the search string) is the performance heavy part. Is the wildcard at the start of the string necessary? If so: You might have to consider pre-processing the data in a different way so that the search can use a single wildcard or no wildcard at all. This last part (depending on the data) is for example done by splitting the string by a delimiter and storing the data in separate rows, after which a much faster comparison and indexes are possible to be used.

To put data in multiple rows, we would assume a usable separator (can be multiple, the code just gets longer):

CREATE TABLE baseinfo (id INT NOT NULL auto_increment primary key,
  some other columns);

CREATE TABLE explodedstring(id INT NOT NULL, str VARCHAR(200),
   FOREIGN KEY (id) REFERENCES baseinfo(id));

CREATE PROCEDURE explodestring(id int, fullstr VARCHAR(4000))
BEGIN
  {many examples exist already how to do this on SO}
END;

The procedure would take as input your key from the original data (id in this case), and the original string.
The output of the procedure would end up in a secondary table explodedstring against which you now could run a normal select (add some index for performance). The resulting ids would tell you which record would match.


问:
How to get every array element of this json decoded array
With this php code:

```<code>$ajaxData = json_encode($_POST['data']);

$jsonDecode = json_decode($ajaxData, true);
var_dump($jsonDecode);
</code>```

I get this array:

```<code>array(1) {
  [0]=>
  array(5) {
    ["id"]=>
    string(8) "2_page-1"
    ["x"]=>
    string(1) "0"
    ["y"]=>
    string(1) "0"
    ["width"]=>
    string(2) "12"
    ["height"]=>
    string(1) "1"
  }
}
</code>```

How do I get each array element (as a string) so I can use it to put it in database rows?

答:
You have an array inside an array (at the position of 0).
Use a 'for' loop over the first element of the array :

```<code>for($i = 0;$i<count($jsonDecode[0]);$i++){
    $text = $jsonDecode[0][$i];
}
</code>```

'$text' contains the string of each element.

This id of course if the output of your json_decode will always return this same syntax : an array inside the first element of an array.

(In my opinion you should change your '$ajaxData' structure - there is no need for that array of only one element - put the data in side one array.

Body:
With this php code:

$ajaxData = json_encode($_POST['data']);

$jsonDecode = json_decode($ajaxData, true);
var_dump($jsonDecode);

I get this array:

array(1) {
  [0]=>
  array(5) {
    ["id"]=>
    string(8) "2_page-1"
    ["x"]=>
    string(1) "0"
    ["y"]=>
    string(1) "0"
    ["width"]=>
    string(2) "12"
    ["height"]=>
    string(1) "1"
  }
}

How do I get each array element (as a string) so I can use it to put it in database rows?

Body:
You have an array inside an array (at the position of 0).
Use a 'for' loop over the first element of the array :

for($i = 0;$i<count($jsonDecode[0]);$i++){
    $text = $jsonDecode[0][$i];
}

'$text' contains the string of each element.

This id of course if the output of your json_decode will always return this same syntax : an array inside the first element of an array.

(In my opinion you should change your '$ajaxData' structure - there is no need for that array of only one element - put the data in side one array.


问:
Syntax to concatenate two columns
I want to concatenate two fields of my Access 2007 database.

This is my query:

```<code>sql="SELECT CONCAT(COGNOME & ' ' & NOME) AS NOMECOMPLETO FROM clienti WHERE NOMECOMPLETO LIKE '%Rossi Paolo%'"
</code>```

But it does not work, what is the syntax error?

答:
MS Access does not look like other SQL dialects.  This should be closer to what you want:

```<code>SELECT (COGNOME & " " & NOME) AS NOMECOMPLETO
FROM clienti
WHERE (COGNOME & " " & NOME) LIKE "*Rossi Paolo*";
</code>```

Changes:

There is no CONCAT().

& is used for string concatentation.

Double quotes are used for strings.

The wildcard for LIKE is *.

Title: Syntax to concatenate two columns

Body:
I want to concatenate two fields of my Access 2007 database.

This is my query:

sql="SELECT CONCAT(COGNOME & ' ' & NOME) AS NOMECOMPLETO FROM clienti WHERE NOMECOMPLETO LIKE '%Rossi Paolo%'"

But it does not work, what is the syntax error?

Body:
MS Access does not look like other SQL dialects.  This should be closer to what you want:

SELECT (COGNOME & " " & NOME) AS NOMECOMPLETO
FROM clienti
WHERE (COGNOME & " " & NOME) LIKE "*Rossi Paolo*";

Changes:

There is no CONCAT().

& is used for string concatentation.

Double quotes are used for strings.

The wildcard for LIKE is *.


问:
Why is jupyter notebook throwing an IndentationError?
I have some really strange behaviour using jupyter notebook.

Here's a basic python function:

```<code>def configure_wg_drem(data_file_pattern): return data_file_pattern

configure_wg_drem('Adult/Adult_*.txt')
</code>```

which gives me:

```<code>'Adult/Adult_*.txt'
</code>```

But the same function with normal python formatting:

```<code>def configure_wg_drem(data_file_pattern):
    return data_file_pattern

configure_wg_drem('Adult/Adult_*.txt')
</code>```

Throws an error:

```<code>  File "<ipython-input-97-c97da191fc79>", line 29
    return data_file_pattern
         ^
IndentationError: expected an indented block
</code>```

Does anybody have an explanation for this?

I've tried using the automatic indentation that jupyter notebook gives when you use a colon and press enter, a single tab as well as four spaces instead of a tab. All with the same results.

I've also tried restarting jupyter notebook and get the same behaviour.

答:
You may have mixed TAB and spaces in your code.

I recommend you using spaces only.

Body:
I have some really strange behaviour using jupyter notebook.

Here's a basic python function:

def configure_wg_drem(data_file_pattern): return data_file_pattern

configure_wg_drem('Adult/Adult_*.txt')

which gives me:

'Adult/Adult_*.txt'

But the same function with normal python formatting:

def configure_wg_drem(data_file_pattern):
    return data_file_pattern

configure_wg_drem('Adult/Adult_*.txt')

Throws an error:

  File "<ipython-input-97-c97da191fc79>", line 29
    return data_file_pattern
         ^
IndentationError: expected an indented block

Does anybody have an explanation for this?

I've tried using the automatic indentation that jupyter notebook gives when you use a colon and press enter, a single tab as well as four spaces instead of a tab. All with the same results.

I've also tried restarting jupyter notebook and get the same behaviour.


问:
ARSCNView's root node's "heading" doesn't match the device heading
I want a node which I add to my scene to point north. I get the heading data from Core Location, so that represents the direction the device is currently facing at the point my scene was created (and thus the direction my root node faces), and then I add the heading to my new sceneNode's eulerAngles.y, to rotate it so it faces north.

```<code>func renderer(_ renderer: SCNSceneRenderer, didRenderScene scene: SCNScene, atTime time: TimeInterval) {
    if sceneNode == nil,
        let heading = self.locationManager.heading {
        sceneNode = SCNNode()
        sceneNode.eulerAngles.y += Float(heading).degreesToRadians
        sceneView.scene.rootNode.addChildNode(sceneNode)
    }
}
</code>```

The heading information is correct, and so rotating it by that much does rotate it by the required amount, presuming that the heading is the same direction that my root node is facing. But I'm finding that my root node's direction is not equivalent to where the device's heading is, and can sometimes by wildly off. So that means the assumption that the heading is the same as the scene node's "heading" is incorrect, and I need to be able to know how far out from the heading it is, so I can then correct it properly within my sceneNode.

答:
Change your session configuration's worldAlignment to .gravityAndHeading.

With the default .gravity alignment, there's no absolute reference for where the x and z axes of the AR world coordinate system point — their directions are based on the initial orientation of your device when the session starts.

With the .gravityAndHeading option, the x and z axes are aligned to compass directions, so you can safely orient content relative to compass directions.

Body:
I want a node which I add to my scene to point north. I get the heading data from Core Location, so that represents the direction the device is currently facing at the point my scene was created (and thus the direction my root node faces), and then I add the heading to my new sceneNode's eulerAngles.y, to rotate it so it faces north.

func renderer(_ renderer: SCNSceneRenderer, didRenderScene scene: SCNScene, atTime time: TimeInterval) {
    if sceneNode == nil,
        let heading = self.locationManager.heading {
        sceneNode = SCNNode()
        sceneNode.eulerAngles.y += Float(heading).degreesToRadians
        sceneView.scene.rootNode.addChildNode(sceneNode)
    }
}

The heading information is correct, and so rotating it by that much does rotate it by the required amount, presuming that the heading is the same direction that my root node is facing. But I'm finding that my root node's direction is not equivalent to where the device's heading is, and can sometimes by wildly off. So that means the assumption that the heading is the same as the scene node's "heading" is incorrect, and I need to be able to know how far out from the heading it is, so I can then correct it properly within my sceneNode.


问:
How to get the key in Collectors.toMap merge function?
When a duplicate key entry is found during Collectors.toMap(), the merge function (o1, o2) is called.

Question: how can I get the key that caused the duplication?

```<code>String keyvalp = "test=one\ntest2=two\ntest2=three";

Pattern.compile("\n")
    .splitAsStream(keyval)
    .map(entry -> entry.split("="))
    .collect(Collectors.toMap(
        split -> split[0],
        split -> split[1],
        (o1, o2) -> {
            //TODO how to access the key that caused the duplicate? o1 and o2 are the values only
            //split[0]; //which is the key, cannot be accessed here
        },
    HashMap::new));
</code>```

Inside the merge function I want to decide based on the key which if I cancel the mapping, or continue and take on of those values.

答:
There is, of course, simple and trivial trick - saving the key in the 'key mapper' function and getting the key in the 'merge' function. So, the code may look like the following (assuming the key is Integer):

```<code>final AtomicInteger key = new AtomicInteger();
...collect( Collectors.toMap(
   item -> { key.set(item.getKey()); return item.getKey(); }, // key mapper
   item -> ..., // value mapper
   (v1, v2) -> { log(key.get(), v1, v2); return v1; } // merge function
);
</code>```

Note: this is not good for parallel processing.

Body:
When a duplicate key entry is found during Collectors.toMap(), the merge function (o1, o2) is called.

Question: how can I get the key that caused the duplication?

String keyvalp = "test=one\ntest2=two\ntest2=three";

Pattern.compile("\n")
    .splitAsStream(keyval)
    .map(entry -> entry.split("="))
    .collect(Collectors.toMap(
        split -> split[0],
        split -> split[1],
        (o1, o2) -> {
            //TODO how to access the key that caused the duplicate? o1 and o2 are the values only
            //split[0]; //which is the key, cannot be accessed here
        },
    HashMap::new));

Inside the merge function I want to decide based on the key which if I cancel the mapping, or continue and take on of those values.

Body:
There is, of course, simple and trivial trick - saving the key in the 'key mapper' function and getting the key in the 'merge' function. So, the code may look like the following (assuming the key is Integer):

final AtomicInteger key = new AtomicInteger();
...collect( Collectors.toMap(
   item -> { key.set(item.getKey()); return item.getKey(); }, // key mapper
   item -> ..., // value mapper
   (v1, v2) -> { log(key.get(), v1, v2); return v1; } // merge function
);

Note: this is not good for parallel processing.


问:
react-router: passing props to a component that is rendered with <Link />
I'm using react-router's <Link /> so that when a user clicks the link, myComponent is rendered.

My question is, how can I pass props into the myComponent from the Navigation component? This doesn't work, but I'm trying to pass a element.name prop from Navigation to myComponent.

```<code>class Navigation extends Component {
  const items = store.getState().items.map((element, index) =>
    <Link to={element.id} name={element.name}> element.id </Link>
  )

  render() {
    return (
      {items}
    )
  }
}
</code>```

Here's the route setup & component setup:

```<code><Route path=":id" component={myComponent} />

// I'd like to pass in props to be used here from the Navigation component, for example, a name prop passed through <Link />

class myCompnent extends Component {
  render() {
    return (
      <div>
        <p> hello {this.props.name} </p>
      </div>
    )
  }
}
</code>```

答:
What you can do is pass the props by appending them to the Component link in Parent Component and get them using componentWillReceiveProps method in child component.

For Example :

Parent Component

```<code><Link to {`element.id/{$element.name}`}>{element.id}</Link>
</code>```

Child Component

```<code>componentWillReceiveProps(nextProps) {
    if (nextProps.value !== this.props.value) {
        console.log(this.props); //Here you can fetch the props which you have passed
    }
}
</code>```

Body:
I'm using react-router's <Link /> so that when a user clicks the link, myComponent is rendered.

My question is, how can I pass props into the myComponent from the Navigation component? This doesn't work, but I'm trying to pass a element.name prop from Navigation to myComponent.

class Navigation extends Component {
  const items = store.getState().items.map((element, index) =>
    <Link to={element.id} name={element.name}> element.id </Link>
  )

  render() {
    return (
      {items}
    )
  }
}

Here's the route setup & component setup:

<Route path=":id" component={myComponent} />

// I'd like to pass in props to be used here from the Navigation component, for example, a name prop passed through <Link />

class myCompnent extends Component {
  render() {
    return (

 hello {this.props.name}

    )
  }
}

Body:
What you can do is pass the props by appending them to the Component link in Parent Component and get them using componentWillReceiveProps method in child component.

For Example :

Parent Component

<Link to {`element.id/{$element.name}`}>{element.id}</Link>

Child Component

componentWillReceiveProps(nextProps) {
    if (nextProps.value !== this.props.value) {
        console.log(this.props); //Here you can fetch the props which you have passed
    }
}


问:
How can I generate sitemaps on heroku?
I've seen some older threads on generating a sitemap on heroku...the challenges being it needs to be stored on S3 and configuring it so that the sitemap is legitimate since it is hosted elsewhere.

I didn't see anything definitive, however, some conversations and suggested patches.

Is there something out-of-the-box that can work well with heroku?

答:
I can't speak English not well.
But explan to you my code.
xml is create using 'xmlbuilder'.</p>

```<code>CreateXmlFile(request, response, next, function(request, response, next, xml){
      response.type('text/xml');
      response.send(xml);
      if(typeof next == "function"){
        next();
      }
    });
</code>```

Title: How can I generate sitemaps on heroku?

Body:
I can't speak English not well.
But explan to you my code.
xml is create using 'xmlbuilder'.

CreateXmlFile(request, response, next, function(request, response, next, xml){
      response.type('text/xml');
      response.send(xml);
      if(typeof next == "function"){
        next();
      }
    });


问:
How to mount component only when i change class props
I have a ReactJS project where i get JSON from REST Django host and creating a table with filters for it. I have a Table class :

```<code>class MainTable extends React.Component {

  constructor(props) {
    super(props);
    this.state = {
      results: []
    };
  }

  componentDidMount(){
    axios.get(this.props.link)
      .then(res => {
        this.setState({results: res.data.results});
    });
  }

  render() {
    return (
      <Table hover striped bordered responsive size="sm">
        <thead>
          <tr>
            <th>Name</th>
            <th>Name</th>
          </tr>
        </thead>
        <tbody>
          {this.state.results.map(result =>
            <tr key={result.fileId}>
              <td>{result.Name}</td>
              <td>{result.Name}</td>
            </tr>
          )}
        </tbody>
      </Table>
    );
  }
}
</code>```

And Main where i run all filter classes :

```<code>class Main extends React.Component {
  constructor() {
    super();
    this.state = {
      origin: '',
      limit: 10
    };

    this.handleChangeOrigin = this.handleChangeOrigin.bind(this);
    this.handleChangeLimit = this.handleChangeLimit.bind(this);
  }

  handleChangeLimit(event) {
    this.setState({limit: event.target.value});
  }
  handleChangeOrigin(event) {
    this.setState({origin: event.target.value});
  }

  render() {
    var link = `http://106.120.89.142:8000/database/?limit=${this.state.limit}&`;
    if (this.state.origin){
      link += `ORIGIN=${this.state.origin.toLowerCase()}`;
      console.log(link)
    }
    return (
      <div>
        <div>
          <h1 className="jumbotron-heading display-4">Here u got database *_*</h1>
        </div>
        <div>
          <Limit handleChange = {this.handleChangeLimit} />
        </div>
        <div>
          <OriginRow handleChange = {this.handleChangeOrigin} />
        </div>
        <div id="tableWrapper">
          <MainTable link={link} />
        </div>
      </div>
    );
  }
}
</code>```

And i have a problem with it, cause when i use componentDidMount(), my axios.get(my link to REST JSON) runs only once. When i use axios in Table class render(), it hits my server few times per second. Can i make mounting only when my props to Table class changed?

答:
As pointed out you can implement shouldComponentUpdate.  Alternatively if you dont need a deep comparison, ie on any collections or objects, just use PureComponent instead of Component:

https://github.com/facebook/react/blob/master/docs/docs/reference-react.md

React.PureComponent#
React.PureComponent is exactly like React.Component but implements shouldComponentUpdate() with a shallow prop and state comparison.

Body:
I have a ReactJS project where i get JSON from REST Django host and creating a table with filters for it. I have a Table class :

class MainTable extends React.Component {

  constructor(props) {
    super(props);
    this.state = {
      results: []
    };
  }

  componentDidMount(){
    axios.get(this.props.link)
      .then(res => {
        this.setState({results: res.data.results});
    });
  }

  render() {
    return (

            Name
            Name

          {this.state.results.map(result =>

              {result.Name}
              {result.Name}

          )}

    );
  }
}

And Main where i run all filter classes :

class Main extends React.Component {
  constructor() {
    super();
    this.state = {
      origin: '',
      limit: 10
    };

    this.handleChangeOrigin = this.handleChangeOrigin.bind(this);
    this.handleChangeLimit = this.handleChangeLimit.bind(this);
  }

  handleChangeLimit(event) {
    this.setState({limit: event.target.value});
  }
  handleChangeOrigin(event) {
    this.setState({origin: event.target.value});
  }

  render() {
    var link = `http://106.120.89.142:8000/database/?limit=${this.state.limit}&`;
    if (this.state.origin){
      link += `ORIGIN=${this.state.origin.toLowerCase()}`;
      console.log(link)
    }
    return (

Here u got database *_*

          <Limit handleChange = {this.handleChangeLimit} />

          <OriginRow handleChange = {this.handleChangeOrigin} />

          <MainTable link={link} />

    );
  }
}

And i have a problem with it, cause when i use componentDidMount(), my axios.get(my link to REST JSON) runs only once. When i use axios in Table class render(), it hits my server few times per second. Can i make mounting only when my props to Table class changed?


问:
same case value but run different formula if first character is
I am making a renaming script and all is working unless I have a specific file name. Which is common in every project.

I am renaming file names based on the file length. I have 2 file lengths that are both = to 12 but need to be named differently. Can I have an if statement inside of that one case to see if the first Character is =0,c,e"?

```<code>Sub Convert()
Application.ScreenUpdating = False

Dim rng As Range, aCell As Range
Dim val As String
Dim LastRow As Long
LastRow = Range("A" & Rows.Count).End(xlUp).Row
Set rng = Range("A2:A" & LastRow)

For Each aCell In rng.Cells
Select Case Len(aCell)
    Case 12
        If val = Left(aCell, 1) = "0" Or "c" Or "e" Then 'Example: 01730101.pdf = S-173-0101.pdf
        val = "S-" & Mid(aCell, 2, Len(aCell) - 9) & "-" & Mid(aCell, 5, Len(aCell) - 8)
        Else 'Example: 173d0071.pdf = S-173-D7.pdf
        val = "S-" & Left(aCell, Len(aCell) - 9) & "-" & Mid(aCell, 4, Len(aCell) - 8)
        End If
    Case 13 'Example: 173d00710.pdf = S-173-D7.pdf
        val = "S-" & Left(aCell, Len(aCell) - 10) & "-" & Mid(aCell, 4, Len(aCell) - 9)
    Case 15 'Example: 173d170c071.pdf = SD-170-C7.pdf
        val = "SD-" & Left(aCell, Len(aCell) - 15) & Mid(aCell, 5, Len(aCell) - 12) & "-" & Mid(aCell, 8, Len(aCell) - 12)
    Case 16 'Example: REF-173d0071.pdf = REF-173-D7.pdf
        val = Left(aCell, Len(aCell) - 9) & "-" & (Mid(aCell, 8, Len(aCell) - 12))
    Case 17 'Example: REF173d00710.pdf = REF-173-D7.pdf
        val = Left(aCell, Len(aCell) - 10) & "-" & (Mid(aCell, 8, Len(aCell) - 13))
On Error GoTo whoa
    Case Else
        val = "_Mod " & Left(aCell, Len(aCell) - 4)
End Select

val = UCase(val)

val = val & " " & aCell.Offset(, 2) & aCell.Offset(, 3)

aCell.Offset(, 1).Value = val
Next
Call RemoveZero
Call RemoveBadChar
    Range("C1").Select
    Worksheets("Rename").Columns("B").AutoFit
    Application.ScreenUpdating = True
whoa:
MsgBox "Please delete any empty rows."
ActiveSheet.Range("A1").End(xlDown).Offset(1).EntireRow.Select
Application.ScreenUpdating = True
Exit Sub
End Sub
</code>```

Thx for any help

答:
```<code>Sub Convert()
Application.ScreenUpdating = False

Dim rng As Range, aCell As Range
Dim val As String, check
Dim LastRow As Long
LastRow = Range("A" & Rows.Count).End(xlUp).Row
Set rng = Range("A2:A" & LastRow)

For Each aCell In rng.Cells
Select Case Len(aCell)
    Case 12
        'I added a check here
        check = Left(aCell, 1)
        If check = "0" Or check = "c" Or check = "e" Then  'Example: 01730101.pdf = S-173-0101.pdf
        val = "S-" & Mid(aCell, 2, Len(aCell) - 9) & "-" & Mid(aCell, 5, Len(aCell) - 8)
        Else 'Example: 173d0071.pdf = S-173-D7.pdf
        val = "S-" & Left(aCell, Len(aCell) - 9) & "-" & Mid(aCell, 4, Len(aCell) - 8)
        End If
        check = ""
    Case 13 'Example: 173d00710.pdf = S-173-D7.pdf
        val = "S-" & Left(aCell, Len(aCell) - 10) & "-" & Mid(aCell, 4, Len(aCell) - 9)
    Case 15 'Example: 173d170c071.pdf = SD-170-C7.pdf
        val = "SD-" & Left(aCell, Len(aCell) - 15) & Mid(aCell, 5, Len(aCell) - 12) & "-" & Mid(aCell, 8, Len(aCell) - 12)
    Case 16 'Example: REF-173d0071.pdf = REF-173-D7.pdf
        val = Left(aCell, Len(aCell) - 9) & "-" & (Mid(aCell, 8, Len(aCell) - 12))
    Case 17 'Example: REF173d00710.pdf = REF-173-D7.pdf
        val = Left(aCell, Len(aCell) - 10) & "-" & (Mid(aCell, 8, Len(aCell) - 13))
On Error GoTo whoa
    Case Else
        val = "_Mod " & Left(aCell, Len(aCell) - 4)
End Select

val = UCase(val)

val = val & " " & aCell.Offset(, 2) & aCell.Offset(, 3)

aCell.Offset(, 1).Value = val
Next
Call RemoveZero
Call RemoveBadChar
    Range("C1").Select
    Worksheets("Rename").Columns("B").AutoFit
    Application.ScreenUpdating = True
whoa:
MsgBox "Please delete any empty rows."
ActiveSheet.Range("A1").End(xlDown).Offset(1).EntireRow.Select
Application.ScreenUpdating = True
Exit Sub
</code>```

Body:
I am making a renaming script and all is working unless I have a specific file name. Which is common in every project.

I am renaming file names based on the file length. I have 2 file lengths that are both = to 12 but need to be named differently. Can I have an if statement inside of that one case to see if the first Character is =0,c,e"?

Sub Convert()
Application.ScreenUpdating = False

Dim rng As Range, aCell As Range
Dim val As String
Dim LastRow As Long
LastRow = Range("A" & Rows.Count).End(xlUp).Row
Set rng = Range("A2:A" & LastRow)

For Each aCell In rng.Cells
Select Case Len(aCell)
    Case 12
        If val = Left(aCell, 1) = "0" Or "c" Or "e" Then 'Example: 01730101.pdf = S-173-0101.pdf
        val = "S-" & Mid(aCell, 2, Len(aCell) - 9) & "-" & Mid(aCell, 5, Len(aCell) - 8)
        Else 'Example: 173d0071.pdf = S-173-D7.pdf
        val = "S-" & Left(aCell, Len(aCell) - 9) & "-" & Mid(aCell, 4, Len(aCell) - 8)
        End If
    Case 13 'Example: 173d00710.pdf = S-173-D7.pdf
        val = "S-" & Left(aCell, Len(aCell) - 10) & "-" & Mid(aCell, 4, Len(aCell) - 9)
    Case 15 'Example: 173d170c071.pdf = SD-170-C7.pdf
        val = "SD-" & Left(aCell, Len(aCell) - 15) & Mid(aCell, 5, Len(aCell) - 12) & "-" & Mid(aCell, 8, Len(aCell) - 12)
    Case 16 'Example: REF-173d0071.pdf = REF-173-D7.pdf
        val = Left(aCell, Len(aCell) - 9) & "-" & (Mid(aCell, 8, Len(aCell) - 12))
    Case 17 'Example: REF173d00710.pdf = REF-173-D7.pdf
        val = Left(aCell, Len(aCell) - 10) & "-" & (Mid(aCell, 8, Len(aCell) - 13))
On Error GoTo whoa
    Case Else
        val = "_Mod " & Left(aCell, Len(aCell) - 4)
End Select

val = UCase(val)

val = val & " " & aCell.Offset(, 2) & aCell.Offset(, 3)

aCell.Offset(, 1).Value = val
Next
Call RemoveZero
Call RemoveBadChar
    Range("C1").Select
    Worksheets("Rename").Columns("B").AutoFit
    Application.ScreenUpdating = True
whoa:
MsgBox "Please delete any empty rows."
ActiveSheet.Range("A1").End(xlDown).Offset(1).EntireRow.Select
Application.ScreenUpdating = True
Exit Sub
End Sub

Thx for any help